Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2025-01-23 23:23:53 +08:00
77 changed files with 1682 additions and 1680 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
name: Feature request name: Feature request
description: Suggest an idea for this project description: Suggest an idea for this project
title: "Feature: " title: "Feature: "
labels: [Suggestion] type: "Feature"
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Thank you for taking your time to fill out a feature request. Remember to fill out all fields including the title above. Thank you for taking the time to fill out a feature request. Remember to fill out all fields including the title above.
An issue that is not properly filled out will be closed. An issue that is not properly filled out will be closed.
- type: textarea - type: textarea
id: description id: description
+24
View File
@@ -15,6 +15,7 @@ results = {
"Multiple blank lines check": "Passed", "Multiple blank lines check": "Passed",
"Trailing whitespace check": "Passed", "Trailing whitespace check": "Passed",
"SQL codestyle check": "Passed", "SQL codestyle check": "Passed",
"INSERT safety usage check": "Passed",
"Missing semicolon check": "Passed" "Missing semicolon check": "Passed"
} }
@@ -43,6 +44,7 @@ def parsing_file(files: list) -> None:
multiple_blank_lines_check(file, file_path) multiple_blank_lines_check(file, file_path)
trailing_whitespace_check(file, file_path) trailing_whitespace_check(file, file_path)
sql_check(file, file_path) sql_check(file, file_path)
insert_safety_check(file, file_path)
semicolon_check(file, file_path) semicolon_check(file, file_path)
except UnicodeDecodeError: except UnicodeDecodeError:
print(f"\nCould not decode file {file_path}") print(f"\nCould not decode file {file_path}")
@@ -108,6 +110,10 @@ def sql_check(file: io, file_path: str) -> None:
print( print(
f"DON'T EDIT broadcast_text TABLE UNLESS YOU KNOW WHAT YOU ARE DOING!\nThis error can safely be ignored if the changes are approved to be sniffed: {file_path} at line {line_number}") f"DON'T EDIT broadcast_text TABLE UNLESS YOU KNOW WHAT YOU ARE DOING!\nThis error can safely be ignored if the changes are approved to be sniffed: {file_path} at line {line_number}")
check_failed = True check_failed = True
if "EntryOrGuid" in line:
print(
f"Please use entryorguid syntax instead of EntryOrgGuid in {file_path} at line {line_number}\nWe recommend to use keira to have the right syntax in auto-query generation")
check_failed = True
if [match for match in [';;'] if match in line]: if [match for match in [';;'] if match in line]:
print( print(
f"Double semicolon (;;) found in {file_path} at line {line_number}") f"Double semicolon (;;) found in {file_path} at line {line_number}")
@@ -128,6 +134,24 @@ def sql_check(file: io, file_path: str) -> None:
error_handler = True error_handler = True
results["SQL codestyle check"] = "Failed" results["SQL codestyle check"] = "Failed"
def insert_safety_check(file: io, file_path: str) -> None:
global error_handler, results
file.seek(0) # Reset file pointer to the beginning
check_failed = False
previous_line = ""
# Parse all the file
for line_number, line in enumerate(file, start = 1):
if "INSERT" in line and "DELETE" not in previous_line:
print(f"No DELETE keyword found after the INSERT in {file_path} at line {line_number}\nIf this error is intended, please advert a maintainer")
check_failed = True
previous_line = line
# Handle the script error and update the result output
if check_failed:
error_handler = True
results["INSERT safety usage check"] = "Failed"
def semicolon_check(file: io, file_path: str) -> None: def semicolon_check(file: io, file_path: str) -> None:
global error_handler, results global error_handler, results
file.seek(0) # Reset file pointer to the beginning file.seek(0) # Reset file pointer to the beginning
+37 -12
View File
@@ -7,7 +7,7 @@
# #
#================================================================= #=================================================================
FROM ubuntu:22.04 as dev FROM ubuntu:24.04 as dev
ARG USER_ID=1000 ARG USER_ID=1000
ARG GROUP_ID=1000 ARG GROUP_ID=1000
ARG DOCKER_USER=acore ARG DOCKER_USER=acore
@@ -29,13 +29,37 @@ ENV TZ=$TZ
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y \ && apt-get install -y --no-install-recommends \
gdb gdbserver git dos2unix lsb-core sudo curl unzip \ # Classic install
make cmake clang libmysqlclient-dev libboost-all-dev \ git \
build-essential libtool cmake-data openssl libgoogle-perftools-dev google-perftools \ clang lldb lld clang-format clang-tidy \
libssl-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev mysql-client \ make cmake \
libncurses5-dev ccache tzdata \ gcc g++ \
&& rm -rf /var/lib/apt/lists/* libmysqlclient-dev \
libssl-dev \
libbz2-dev \
libreadline-dev \
libncurses-dev \
mysql-server \
libboost-all-dev \
# Other
curl \
unzip \
sudo \
gdb gdbserver \
libtool \
build-essential \
cmake-data \
openssl \
google-perftools libgoogle-perftools-dev \
libmysql++-dev \
ccache \
tzdata \
# Utility for column command used by dashboard
util-linux \
# Certificates for downloading client data
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Ensure git will work with the AzerothCore source directory # Ensure git will work with the AzerothCore source directory
RUN git config --global --add safe.directory /azerothcore RUN git config --global --add safe.directory /azerothcore
@@ -45,10 +69,11 @@ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata && echo $TZ > /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata
# Create a non-root user # Create a non-root user
RUN addgroup --gid "$GROUP_ID" "$DOCKER_USER" && \ RUN userdel --remove ubuntu \
adduser --disabled-password --gecos '' --uid "$USER_ID" --gid "$GROUP_ID" "$DOCKER_USER" && \ && addgroup --gid "$GROUP_ID" "$DOCKER_USER" \
passwd -d "$DOCKER_USER" && \ && adduser --disabled-password --gecos '' --uid "$USER_ID" --gid "$GROUP_ID" "$DOCKER_USER" \
echo "$DOCKER_USER ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers && passwd -d "$DOCKER_USER" \
&& echo "$DOCKER_USER ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers
# must be created to set the correct permissions on them # must be created to set the correct permissions on them
RUN mkdir -p \ RUN mkdir -p \
@@ -0,0 +1,6 @@
-- DB update 2025_01_15_03 -> 2025_01_15_04
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 23597) AND (`source_type` = 0) AND (`id` IN (12, 18));
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
(23597, 0, 12, 0, 1, 1, 100, 515, 6200, 6200, 6200, 6200, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Amani\'shi Guardian - Out of Combat - Remove Flags Immune To Players & Immune To NPC\'s (Phase 1) (No Repeat) (Normal Dungeon)'),
(23597, 0, 18, 0, 1, 2, 100, 515, 7600, 7600, 7600, 7600, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Amani\'shi Guardian - Out of Combat - Remove Flags Immune To Players & Immune To NPC\'s (Phase 2) (No Repeat) (Normal Dungeon)');
@@ -0,0 +1,3 @@
-- DB update 2025_01_15_04 -> 2025_01_16_00
--
UPDATE `creature_template` SET `ScriptName` = 'npc_deathstalker_fearleia' WHERE `entry` = 2058;
@@ -0,0 +1,3 @@
-- DB update 2025_01_16_00 -> 2025_01_16_01
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 24043) AND (`source_type` = 0) AND (`id` IN (2));
@@ -0,0 +1,8 @@
-- DB update 2025_01_16_01 -> 2025_01_16_02
--
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24138;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 24138) AND (`source_type` = 0) AND (`id` IN (0, 1));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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
(24138, 0, 0, 0, 0, 0, 100, 0, 4000, 8000, 8000, 16000, 0, 0, 11, 43353, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Tamed Amani Crocolisk - In Combat - Cast \'Infected Bite\''),
(24138, 0, 1, 0, 0, 0, 100, 0, 5000, 10000, 15000, 30000, 0, 0, 11, 43352, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Tamed Amani Crocolisk - In Combat - Cast \'Tail Swipe\'');
@@ -0,0 +1,4 @@
-- DB update 2025_01_16_02 -> 2025_01_16_03
DELETE FROM `spell_target_position` WHERE `ID` = 41234 AND `EffectIndex` = 0;
INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES
(41234, 0, 530, -3560.52, 583.353, 10.9431, 4.751223087310791015, 58558);
@@ -0,0 +1,10 @@
-- DB update 2025_01_16_03 -> 2025_01_16_04
-- Bloodscalp Witch Doctor SmartAI
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 660;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 660);
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
(660, 0, 0, 0, 0, 0, 100, 1, 8000, 12000, 0, 0, 0, 0, 11, 8376, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bloodscalp Witch Doctor - In Combat - Cast \'Earthgrab Totem\' (No Repeat)'),
(660, 0, 1, 0, 2, 0, 100, 513, 0, 30, 0, 0, 0, 0, 11, 8599, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bloodscalp Witch Doctor - Between 0-30% Health - Cast \'Enrage\' (No Repeat)'),
(660, 0, 2, 0, 2, 0, 100, 1, 0, 50, 0, 0, 0, 0, 11, 5605, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bloodscalp Witch Doctor - Between 0-50% Health - Cast \'Healing Ward\' (No Repeat)');
@@ -0,0 +1,3 @@
-- DB update 2025_01_16_04 -> 2025_01_17_00
--
UPDATE `creature_template_movement` SET `Rooted` = 0 WHERE `CreatureId` = 21221;
@@ -0,0 +1,9 @@
-- DB update 2025_01_17_00 -> 2025_01_17_01
--
UPDATE `acore_string` SET
`content_default` = "No waypoint information was found for Creature (GUID: {}). Make sure 'wp show on' command was properly executed.",
`locale_deDE` = "Keine Wegpunktinformationen wurden für das Wesen (GUID: {}) gefunden. Stellen Sie sicher, dass der Befehl 'wp show on' korrekt ausgeführt wurde.",
`locale_zhCN` = "未找到生物(GUID: {})的路径点信息。请确保正确执行了“wp show on”命令。",
`locale_esES` = "No se encontraron información de punto de ruta para la criatura (GUID: {}). Asegúrese de que el comando 'wp show on' se haya ejecutado correctamente.",
`locale_esMX` = "No se encontraron información de punto de ruta para la criatura (GUID: {}). Asegúrese de que el comando 'wp show on' se haya ejecutado correctamente."
WHERE `entry` = 223;
+148
View File
@@ -0,0 +1,148 @@
-- DB update 2025_01_17_01 -> 2025_01_18_00
-- Update gameobject 'Giant Clam' with sniffed values and add pooling
-- updated spawns
DELETE FROM `gameobject` WHERE (`id` IN (19018))
AND (`guid` IN (100079, 100080, 14630, 32609, 32617, 32619, 32934, 47894, 48528));
INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`, `Comment`) VALUES
(100079, 19018, 0, 0, 0, 1, 1, -2646.4091796875, -1246.5653076171875, -14.4196491241455078, 0.069811686873435974, 0, 0, 0.034898757934570312, 0.999390840530395507, 120, 255, 1, "", 49345, NULL),
(100080, 19018, 0, 0, 0, 1, 1, -2517.143310546875, -1307.2694091796875, -42.1596260070800781, 1.239183306694030761, 0, 0, 0.580702781677246093, 0.814115643501281738, 120, 255, 1, "", 50664, NULL),
(14630, 19018, 0, 0, 0, 1, 1, -2506.34912109375, -1474.3740234375, -28.1449832916259765, 1.361356139183044433, 0, 0, 0.629320144653320312, 0.77714616060256958, 120, 255, 1, "", 45854, NULL),
(32609, 19018, 48, 0, 0, 1, 1, -347.47064208984375, 76.08115386962890625, -61.8706207275390625, 5.70722818374633789, 0, 0, -0.28401470184326171, 0.958819925785064697, 7200, 255, 1, "", 52237, NULL),
(32617, 19018, 48, 0, 0, 1, 1, -400.426910400390625, 279.811859130859375, -71.1439132690429687, 2.740161895751953125, 0, 0, 0.979924201965332031, 0.199370384216308593, 7200, 255, 1, "", 52237, NULL),
(32619, 19018, 48, 0, 0, 1, 1, -410.671173095703125, 348.6953125, -71.7385101318359375, 0.558503925800323486, 0, 0, 0.275636672973632812, 0.961261868476867675, 7200, 255, 1, "", 53622, NULL),
(32934, 19018, 48, 0, 0, 1, 1, -781.43231201171875, -165.56109619140625, -47.9077644348144531, 5.829400539398193359, 0, 0, -0.22495079040527343, 0.974370121955871582, 7200, 255, 1, "", 53622, NULL),
(47894, 19018, 1, 0, 0, 1, 1, 4348.44482421875, 851.246337890625, -21.0694580078125, 2.652894020080566406, 0, 0, 0.970294952392578125, 0.241925001144409179, 120, 255, 1, "", 47720, NULL),
(48528, 19018, 1, 0, 0, 1, 1, 4311.09130859375, 949.97003173828125, -22.5520610809326171, 5.253442287445068359, 0, 0, -0.49242305755615234, 0.870355963706970214, 120, 255, 1, "", 50664, NULL);
-- new spawns
DELETE FROM `gameobject` WHERE (`id` IN (19018))
AND (`guid` BETWEEN 3055 AND 3100);
INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`, `Comment`) VALUES
(3055, 19018, 0, 0, 0, 1, 1, -2516.3125, -1265.5015869140625, -47.1902122497558593, 0.314158439636230468, 0, 0, 0.156434059143066406, 0.987688362598419189, 120, 255, 1, "", 46902, NULL),
(3056, 19018, 0, 0, 0, 1, 1, -2526.524658203125, -1371.18505859375, -40.4460182189941406, 0.261798173189163208, 0, 0, 0.130525588989257812, 0.991444945335388183, 120, 255, 1, "", 50664, NULL),
(3057, 19018, 0, 0, 0, 1, 1, -2561.040771484375, -1548.825439453125, -13.6164684295654296, 2.67034769058227539, 0, 0, 0.972369194030761718, 0.233448356389999389, 120, 255, 1, "", 50375, NULL),
(3058, 19018, 0, 0, 0, 1, 1, -2615.08251953125, -1484.8092041015625, -12.9359779357910156, 6.230826377868652343, 0, 0, -0.02617645263671875, 0.999657332897186279, 120, 255, 1, "", 49345, NULL),
(3059, 19018, 0, 0, 0, 1, 1, -2631.943359375, -1345.4796142578125, -12.8757905960083007, 1.48352813720703125, 0, 0, 0.675589561462402343, 0.737277925014495849, 120, 255, 1, "", 49345, NULL),
(3060, 19018, 0, 0, 0, 1, 1, -2652.344482421875, -1172.9991455078125, -14.9990730285644531, 0.506144583225250244, 0, 0, 0.250379562377929687, 0.968147754669189453, 120, 255, 1, "", 50664, NULL),
(3061, 19018, 0, 0, 0, 1, 1, -2693.152587890625, -1125.627197265625, -14.4795026779174804, 2.513273954391479492, 0, 0, 0.951056480407714843, 0.309017121791839599, 120, 255, 1, "", 49345, NULL),
(3062, 19018, 0, 0, 0, 1, 1, -2758.241455078125, -951.86102294921875, -13.6005315780639648, 3.90954136848449707, 0, 0, -0.92718315124511718, 0.37460830807685852, 120, 255, 1, "", 50375, NULL),
(3063, 19018, 0, 0, 0, 1, 1, -2787.666748046875, -1068.8414306640625, -11.7275295257568359, 6.213373661041259765, 0, 0, -0.03489875793457031, 0.999390840530395507, 120, 255, 1, "", 52237, NULL),
(3064, 19018, 0, 0, 0, 1, 1, -2792.83349609375, -851.74847412109375, -13.051919937133789, 5.375615119934082031, 0, 0, -0.4383707046508789, 0.898794233798980712, 120, 255, 1, "", 50375, NULL),
(3065, 19018, 0, 0, 0, 1, 1, -2858.221923828125, -885.32574462890625, -10.7018337249755859, 5.637413978576660156, 0, 0, -0.31730461120605468, 0.948323667049407958, 120, 255, 1, "", 49822, NULL),
(3066, 19018, 0, 0, 0, 1, 1, -2879.617431640625, -975.7791748046875, -13.6781578063964843, 1.186823248863220214, 0, 0, 0.559192657470703125, 0.829037725925445556, 120, 255, 1, "", 50664, NULL),
(3067, 19018, 0, 0, 0, 1, 1, -2973.353515625, -804.2197265625, -12.3123130798339843, 0.226892471313476562, 0, 0, 0.113203048706054687, 0.993571877479553222, 120, 255, 1, "", 48632, NULL),
(3068, 19018, 0, 0, 0, 1, 1, -2994.040283203125, -903.63714599609375, -7.62413215637207031, 1.692969322204589843, 0, 0, 0.748955726623535156, 0.662620067596435546, 120, 255, 1, "", 50664, NULL),
(3069, 19018, 0, 0, 0, 1, 1, -3047.309326171875, -740.7490234375, -13.4887809753417968, 5.969027042388916015, 0, 0, -0.1564340591430664, 0.987688362598419189, 120, 255, 1, "", 50375, NULL),
(3070, 19018, 0, 0, 0, 1, 1, -3053.877197265625, -858.911865234375, -11.5110082626342773, 1.570795774459838867, 0, 0, 0.707106590270996093, 0.707106947898864746, 120, 255, 1, "", 49345, NULL),
(3071, 19018, 0, 0, 0, 1, 1, -3149.630615234375, -691.31689453125, -34.9023246765136718, 5.096362113952636718, 0, 0, -0.55919265747070312, 0.829037725925445556, 120, 255, 1, "", 49345, NULL),
(3072, 19018, 0, 0, 0, 1, 1, -3154.08251953125, -878.17523193359375, -10.8227548599243164, 0.767943859100341796, 0, 0, 0.374606132507324218, 0.927184045314788818, 120, 255, 1, "", 46902, NULL),
(3073, 19018, 0, 0, 0, 1, 1, -3229.396240234375, -774.949462890625, -17.9715137481689453, 2.426007747650146484, 0, 0, 0.936672210693359375, 0.350207358598709106, 120, 255, 1, "", 51943, NULL),
(3074, 19018, 0, 0, 0, 1, 1, -3276.936767578125, -618.36737060546875, -19.3885517120361328, 2.635444164276123046, 0, 0, 0.96814727783203125, 0.250381410121917724, 120, 255, 1, "", 50375, NULL),
(3075, 19018, 0, 0, 0, 1, 1, -3278.245361328125, -873.4765625, -12.4649734497070312, 1.989672422409057617, 0, 0, 0.838669776916503906, 0.544640243053436279, 120, 255, 1, "", 48632, NULL),
(3076, 19018, 0, 0, 0, 1, 1, -3294.763916015625, -725.89404296875, -10.2694530487060546, 1.32644820213317871, 0, 0, 0.615660667419433593, 0.788011372089385986, 120, 255, 1, "", 51943, NULL),
(3077, 19018, 0, 0, 0, 1, 1, -3431.91357421875, -719.76348876953125, -10.6346702575683593, 1.902408957481384277, 0, 0, 0.814115524291992187, 0.580702960491180419, 120, 255, 1, "", 48632, NULL),
(3078, 19018, 0, 0, 0, 1, 1, -3494.998779296875, -614.75115966796875, -15.8588886260986328, 5.6897735595703125, 0, 0, -0.29237174987792968, 0.956304728984832763, 120, 255, 1, "", 48632, NULL),
(3079, 19018, 0, 0, 0, 1, 1, -3772.385986328125, -1127.484375, -32.0519866943359375, 5.480334281921386718, 0, 0, -0.39073085784912109, 0.920504987239837646, 120, 255, 1, "", 50172, NULL),
(3080, 19018, 0, 0, 0, 1, 1, -3818.381103515625, -1027.3331298828125, -32.0284156799316406, 1.937312245368957519, 0, 0, 0.824125289916992187, 0.566407561302185058, 120, 255, 1, "", 50664, NULL),
(3081, 19018, 0, 0, 0, 1, 1, -3889.245361328125, -917.22613525390625, -16.3200283050537109, 1.064649581909179687, 0, 0, 0.507537841796875, 0.861629426479339599, 120, 255, 1, "", 50664, NULL),
(3082, 19018, 0, 0, 0, 1, 1, -3970.02001953125, -825.5369873046875, -15.9225664138793945, 3.071766138076782226, 0, 0, 0.999390602111816406, 0.034906134009361267, 120, 255, 1, "", 52237, NULL),
(3083, 19018, 0, 0, 0, 1, 1, -4033.75, -762.57843017578125, -12.864654541015625, 2.216565132141113281, 0, 0, 0.894933700561523437, 0.44619917869567871, 120, 255, 1, "", 50375, NULL),
(3084, 19018, 1, 0, 0, 1, 1, 4289.03857421875, 988.9013671875, -25.8320999145507812, 4.799657344818115234, 0, 0, -0.67558956146240234, 0.737277925014495849, 120, 255, 1, "", 49345, NULL),
(3085, 19018, 1, 0, 0, 1, 1, 4350.62744140625, 890.24761962890625, -21.13616943359375, 3.874631166458129882, 0, 0, -0.93358039855957031, 0.358368009328842163, 120, 255, 1, "", 46248, NULL),
(3086, 19018, 48, 0, 0, 1, 1, -331.169464111328125, -27.6077117919921875, -72.2552108764648437, 0.471238493919372558, 0, 0, 0.233445167541503906, 0.972369968891143798, 7200, 255, 1, "", 52237, NULL),
(3087, 19018, 48, 0, 0, 1, 1, -346.6336669921875, 291.60455322265625, -70.7872161865234375, 3.106652259826660156, 0, 0, 0.999847412109375, 0.017469281330704689, 7200, 255, 1, "", 52237, NULL),
(3088, 19018, 48, 0, 0, 1, 1, -348.721710205078125, -34.5047073364257812, -68.4577102661132812, 3.45575571060180664, 0, 0, -0.98768806457519531, 0.156436234712600708, 7200, 255, 1, "", 53622, NULL),
(3089, 19018, 48, 0, 0, 1, 1, -354.931182861328125, 308.108734130859375, -69.8227081298828125, 2.984498262405395507, 0, 0, 0.996916770935058593, 0.078466430306434631, 7200, 255, 1, "", 52237, NULL),
(3090, 19018, 48, 0, 0, 1, 1, -421.11395263671875, 121.5354385375976562, -70.3830795288085937, 4.956737518310546875, 0, 0, -0.61566066741943359, 0.788011372089385986, 7200, 255, 1, "", 53622, NULL),
(3091, 19018, 48, 0, 0, 1, 1, -427.4090576171875, 311.43017578125, -65.8169937133789062, 0.139624491333961486, 0, 0, 0.06975555419921875, 0.997564136981964111, 7200, 255, 1, "", 53622, NULL),
(3092, 19018, 48, 0, 0, 1, 1, -489.73443603515625, 144.3833770751953125, -72.4147415161132812, 1.588248729705810546, 0, 0, 0.713250160217285156, 0.700909554958343505, 7200, 255, 1, "", 52237, NULL),
(3093, 19018, 48, 0, 0, 1, 1, -686.755126953125, -34.1224174499511718, -36.9233741760253906, 2.164205789566040039, 0, 0, 0.882946968078613281, 0.469472706317901611, 7200, 255, 1, "", 52237, NULL),
(3094, 19018, 48, 0, 0, 1, 1, -713.4542236328125, -21.8693408966064453, -39.3413848876953125, 2.932138919830322265, 0, 0, 0.994521141052246093, 0.104535527527332305, 7200, 255, 1, "", 52237, NULL),
(3095, 19018, 48, 0, 0, 1, 1, -756.04718017578125, -176.359329223632812, -54.1190109252929687, 1.605701684951782226, 0, 0, 0.719339370727539062, 0.694658815860748291, 7200, 255, 1, "", 52237, NULL),
(3096, 19018, 48, 0, 0, 1, 1, -760.38995361328125, -52.2364158630371093, -41.6094551086425781, 0.977383077144622802, 0, 0, 0.469470977783203125, 0.882947921752929687, 7200, 255, 1, "", 52237, NULL),
(3097, 19018, 48, 0, 0, 1, 1, -760.68328857421875, -155.533584594726562, -51.5061683654785156, 0.471238493919372558, 0, 0, 0.233445167541503906, 0.972369968891143798, 7200, 255, 1, "", 53622, NULL),
(3098, 19018, 48, 0, 0, 1, 1, -770.51202392578125, -189.07220458984375, -48.8139495849609375, 5.777040958404541015, 0, 0, -0.25037956237792968, 0.968147754669189453, 7200, 255, 1, "", 52237, NULL),
(3099, 19018, 48, 0, 0, 1, 1, -835.62677001953125, -47.6639022827148437, -35.6944770812988281, 3.45575571060180664, 0, 0, -0.98768806457519531, 0.156436234712600708, 7200, 255, 1, "", 53622, NULL),
(3100, 19018, 48, 0, 0, 1, 1, -870.4945068359375, -105.115287780761718, -35.4094352722167968, 1.710421562194824218, 0, 0, 0.754709243774414062, 0.656059443950653076, 7200, 255, 1, "", 52237, NULL);
-- remaining spawns (no sniffed values available)
-- map 48 - Blackfathom Deeps
-- (`guid` IN (32607, 32618, 32615, 32687, 32689, 32691, 32685, 32692))
-- pooling
-- the spawn count for each pool has been estimated from the currently available sniffs
DELETE FROM `pool_template` WHERE (`entry` IN (139, 140, 141));
INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES
(139, 10, 'Eastern Kingdoms - Giant Clam - 10/32'),
(140, 2, 'Kalimdor - Giant Clam - 2/4'),
(141, 12, 'Blackfathom Deeps - Giant Clam - 12/27');
DELETE FROM `pool_gameobject` WHERE (`pool_entry` IN (139, 140, 141)) AND (`guid` IN (100079, 100080, 14630, 32609, 32617, 32619, 32934, 47894, 48528, 32607, 32618, 32615, 32687, 32689, 32691, 32685, 32692));
DELETE FROM `pool_gameobject` WHERE (`pool_entry` IN (139, 140, 141)) AND (`guid` BETWEEN 3055 AND 3100);
INSERT INTO `pool_gameobject` (`guid`, `pool_entry`, `chance`, `description`) VALUES
-- map 0 - Eastern Kingdoms
(100079, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(100080, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(14630, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3055, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3056, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3057, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3058, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3059, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3060, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3061, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3062, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3063, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3064, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3065, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3066, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3067, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3068, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3069, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3070, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3071, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3072, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3073, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3074, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3075, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3076, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3077, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3078, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3079, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3080, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3081, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3082, 139, 0, 'Eastern Kingdoms - Giant Clam'),
(3083, 139, 0, 'Eastern Kingdoms - Giant Clam'),
-- map 1 - Kalimdor
(47894, 140, 0, 'Kalimdor - Giant Clam'),
(48528, 140, 0, 'Kalimdor - Giant Clam'),
(3084, 140, 0, 'Kalimdor - Giant Clam'),
(3085, 140, 0, 'Kalimdor - Giant Clam'),
-- map 48 - Blackfathom Deeps
(32609, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32617, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32619, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32934, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32607, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32618, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32615, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32687, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32689, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32691, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32685, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(32692, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3086, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3087, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3088, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3089, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3090, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3091, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3092, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3093, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3094, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3095, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3096, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3097, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3098, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3099, 141, 0, 'Blackfathom Deeps - Giant Clam'),
(3100, 141, 0, 'Blackfathom Deeps - Giant Clam');
@@ -0,0 +1,4 @@
-- DB update 2025_01_18_00 -> 2025_01_18_01
-- Change Unit Flags (IMMUNE_TO_PC, IMMUNE_TO_NPC)
UPDATE `creature_template` SET `unit_flags` = `unit_flags`|768 WHERE `entry` IN (25465);
+183
View File
@@ -0,0 +1,183 @@
-- DB update 2025_01_18_01 -> 2025_01_19_00
-- Update gameobject 'Giant Clam' with sniffed values and add pooling
-- updated spawns
DELETE FROM `gameobject` WHERE (`id` IN (2744))
AND (`guid` IN (11029, 11030, 11686, 11687, 11811, 11818, 32097));
INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`, `Comment`) VALUES
(11029, 2744, 0, 0, 0, 1, 1, -12212.314453125, 429.674102783203125, -101.356117248535156, 4.729844093322753906, 0, 0, -0.70090866088867187, 0.713251054286956787, 300, 255, 1, "", 45613, NULL),
(11030, 2744, 0, 0, 0, 1, 1, -12127.8740234375, 525.8162841796875, -49.4669418334960937, 3.996806621551513671, 0, 0, -0.90996074676513671, 0.414694398641586303, 300, 255, 1, "", 45572, NULL),
(11686, 2744, 0, 0, 0, 1, 1, -12189.05859375, 481.9610595703125, -71.9975967407226562, 4.747295856475830078, 0, 0, -0.69465827941894531, 0.719339847564697265, 300, 255, 1, "", 45613, NULL),
(11687, 2744, 0, 0, 0, 1, 1, -12173.8779296875, 439.629791259765625, -35.3151359558105468, 1.815141916275024414, 0, 0, 0.788010597229003906, 0.615661680698394775, 300, 255, 1, "", 48120, NULL),
(11811, 2744, 0, 0, 0, 1, 1, -12194.5107421875, 597.6055908203125, -66.1562118530273437, 0.925023794174194335, 0, 0, 0.446197509765625, 0.894934535026550292, 300, 255, 1, "", 45572, NULL),
(11818, 2744, 0, 0, 0, 1, 1, -12140.9033203125, 558.23614501953125, -30.8249416351318359, 5.619962215423583984, 0, 0, -0.32556724548339843, 0.945518851280212402, 300, 255, 1, "", 49345, NULL),
(32097, 2744, 0, 0, 0, 1, 1, -12211.3408203125, 689.1170654296875, -72.4632949829101562, 2.775068521499633789, 0, 0, 0.983254432678222656, 0.182238012552261352, 300, 255, 1, "", 49345, NULL);
-- new spawns
DELETE FROM `gameobject` WHERE (`id` IN (2744))
AND (`guid` BETWEEN 3442 AND 3514);
INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`, `Comment`) VALUES
(3442, 2744, 0, 0, 0, 1, 1, -12119.9814453125, 499.054107666015625, -55.3000259399414062, 1.762782454490661621, 0, 0, 0.771624565124511718, 0.636078238487243652, 300, 255, 1, "", 49345, NULL),
(3443, 2744, 0, 0, 0, 1, 1, -12133, 598.65399169921875, -35.3210601806640625, 3.281238555908203125, 0, 0, -0.99756336212158203, 0.069766148924827575, 300, 255, 1, "", 47168, NULL),
(3444, 2744, 0, 0, 0, 1, 1, -12142.7939453125, 466.66937255859375, -30.6373634338378906, 4.1538848876953125, 0, 0, -0.8746194839477539, 0.484810054302215576, 300, 255, 1, "", 45572, NULL),
(3445, 2744, 0, 0, 0, 1, 1, -12144.0556640625, 581.7142333984375, -28.6632328033447265, 1.361356139183044433, 0, 0, 0.629320144653320312, 0.77714616060256958, 300, 255, 1, "", 47168, NULL),
(3446, 2744, 0, 0, 0, 1, 1, -12150.5673828125, 445.523284912109375, -11.8544530868530273, 0.209439441561698913, 0, 0, 0.104528427124023437, 0.994521915912628173, 300, 255, 1, "", 45613, NULL),
(3447, 2744, 0, 0, 0, 1, 1, -12152.19921875, 490.97894287109375, -60.2821731567382812, 0.820303261280059814, 0, 0, 0.398748397827148437, 0.917060375213623046, 300, 255, 1, "", 49345, NULL),
(3448, 2744, 0, 0, 0, 1, 1, -12164.212890625, 477.830902099609375, -38.8802566528320312, 1.396261811256408691, 0, 0, 0.642786979675292968, 0.766044974327087402, 300, 255, 1, "", 45613, NULL),
(3449, 2744, 0, 0, 0, 1, 1, -12166.3798828125, 715.30059814453125, -49.3524208068847656, 0.820303261280059814, 0, 0, 0.398748397827148437, 0.917060375213623046, 300, 255, 1, "", 50375, NULL),
(3450, 2744, 0, 0, 0, 1, 1, -12173.4111328125, 515.21826171875, -66.0793228149414062, 5.550147056579589843, 0, 0, -0.358367919921875, 0.933580458164215087, 300, 255, 1, "", 45572, NULL),
(3451, 2744, 0, 0, 0, 1, 1, -12177.61328125, 575.85736083984375, -28.9876232147216796, 1.466075778007507324, 0, 0, 0.669130325317382812, 0.74314504861831665, 300, 255, 1, "", 47168, NULL),
(3452, 2744, 0, 0, 0, 1, 1, -12197.0478515625, 466.8428955078125, -54.4156036376953125, 0.488691210746765136, 0, 0, 0.241921424865722656, 0.970295846462249755, 300, 255, 1, "", 48632, NULL),
(3453, 2744, 0, 0, 0, 1, 1, -12208.8564453125, 571.423828125, -36.9531364440917968, 3.752462387084960937, 0, 0, -0.95371627807617187, 0.300707906484603881, 300, 255, 1, "", 45572, NULL),
(3454, 2744, 0, 0, 0, 1, 1, -12210.11328125, 714.8321533203125, -58.2952194213867187, 1.32644820213317871, 0, 0, 0.615660667419433593, 0.788011372089385986, 300, 255, 1, "", 49345, NULL),
(3455, 2744, 0, 0, 0, 1, 1, -12210.4990234375, 528.47882080078125, -65.7092056274414062, 3.351046562194824218, 0, 0, -0.99452114105224609, 0.104535527527332305, 300, 255, 1, "", 47168, NULL),
(3456, 2744, 0, 0, 0, 1, 1, -12223.4404296875, 506.735015869140625, -95.9059524536132812, 1.535889506340026855, 0, 0, 0.694658279418945312, 0.719339847564697265, 300, 255, 1, "", 47168, NULL),
(3457, 2744, 0, 0, 0, 1, 1, -12223.8876953125, 441.446685791015625, -88.0880050659179687, 5.829400539398193359, 0, 0, -0.22495079040527343, 0.974370121955871582, 300, 255, 1, "", 45613, NULL),
(3458, 2744, 0, 0, 0, 1, 1, -12234.59375, 604.07232666015625, -65.1342086791992187, 6.248279094696044921, 0, 0, -0.01745223999023437, 0.999847710132598876, 300, 255, 1, "", 45572, NULL),
(3459, 2744, 0, 0, 0, 1, 1, -12244.26171875, 581.7044677734375, -74.9788742065429687, 6.108653545379638671, 0, 0, -0.08715534210205078, 0.996194720268249511, 300, 255, 1, "", 50664, NULL),
(3460, 2744, 0, 0, 0, 1, 1, -12247.6884765625, 688.15435791015625, -71.0500640869140625, 2.583080768585205078, 0, 0, 0.961260795593261718, 0.275640487670898437, 300, 255, 1, "", 47168, NULL),
(3461, 2744, 0, 0, 0, 1, 1, -12248.431640625, 443.0244140625, -32.4327278137207031, 4.712389945983886718, 0, 0, -0.70710659027099609, 0.707106947898864746, 300, 255, 1, "", 48019, NULL),
(3462, 2744, 0, 0, 0, 1, 1, -12249.8251953125, 607.121337890625, -101.612106323242187, 1.570795774459838867, 0, 0, 0.707106590270996093, 0.707106947898864746, 300, 255, 1, "", 47168, NULL),
(3463, 2744, 0, 0, 0, 1, 1, -12252.9453125, 483.68072509765625, -72.6024169921875, 5.602506637573242187, 0, 0, -0.33380699157714843, 0.942641437053680419, 300, 255, 1, "", 47168, NULL),
(3464, 2744, 0, 0, 0, 1, 1, -12257.2880859375, 455.25238037109375, -46.6031379699707031, 1.588248729705810546, 0, 0, 0.713250160217285156, 0.700909554958343505, 300, 255, 1, "", 47168, NULL),
(3465, 2744, 0, 0, 0, 1, 1, -12261.4013671875, 650.3587646484375, -91.6953125, 4.258606910705566406, 0, 0, -0.84804725646972656, 0.529920578002929687, 300, 255, 1, "", 45772, NULL),
(3466, 2744, 0, 0, 0, 1, 1, -12266.814453125, 541.2694091796875, -109.597816467285156, 2.809975385665893554, 0, 0, 0.986285209655761718, 0.165049895644187927, 300, 255, 1, "", 45572, NULL),
(3467, 2744, 0, 0, 0, 1, 1, -12276.982421875, 694.41302490234375, -98.2943572998046875, 4.206246376037597656, 0, 0, -0.86162853240966796, 0.50753939151763916, 300, 255, 1, "", 51831, NULL),
(3468, 2744, 0, 0, 0, 1, 1, -12280.021484375, 598.15081787109375, -102.022453308105468, 0.017452461645007133, 0, 0, 0.008726119995117187, 0.999961912631988525, 300, 255, 1, "", 49345, NULL),
(3469, 2744, 0, 0, 0, 1, 1, -12282.7177734375, 538.59326171875, -84.8114852905273437, 4.939284324645996093, 0, 0, -0.6225137710571289, 0.78260880708694458, 300, 255, 1, "", 45572, NULL),
(3470, 2744, 0, 0, 0, 1, 1, -12287.6552734375, 479.775390625, -58.4963035583496093, 5.148722648620605468, 0, 0, -0.53729915618896484, 0.843391716480255126, 300, 255, 1, "", 45613, NULL),
(3471, 2744, 0, 0, 0, 1, 1, -12293.0048828125, 607.82000732421875, -79.2215652465820312, 4.363324165344238281, 0, 0, -0.81915187835693359, 0.573576688766479492, 300, 255, 1, "", 54261, NULL),
(3472, 2744, 0, 0, 0, 1, 1, -12294.1396484375, 650.81317138671875, -82.8747940063476562, 2.338739633560180664, 0, 0, 0.920504570007324218, 0.3907318115234375, 300, 255, 1, "", 50664, NULL),
(3473, 2744, 0, 0, 0, 1, 1, -12297.1015625, 488.23089599609375, -78.2284469604492187, 4.625123500823974609, 0, 0, -0.73727703094482421, 0.67559051513671875, 300, 255, 1, "", 47168, NULL),
(3474, 2744, 0, 0, 0, 1, 1, -12305.6669921875, 435.504241943359375, -20.5355720520019531, 3.926995515823364257, 0, 0, -0.92387866973876953, 0.38268551230430603, 300, 255, 1, "", 49345, NULL),
(3475, 2744, 0, 0, 0, 1, 1, -12306.8349609375, 527.46429443359375, -83.1399383544921875, 0.104719325900077819, 0, 0, 0.052335739135742187, 0.998629570007324218, 300, 255, 1, "", 49345, NULL),
(3476, 2744, 0, 0, 0, 1, 1, -12313.84375, 601.927490234375, -59.0801734924316406, 1.535889506340026855, 0, 0, 0.694658279418945312, 0.719339847564697265, 300, 255, 1, "", 50664, NULL),
(3477, 2744, 0, 0, 0, 1, 1, -12314.4111328125, 616.9012451171875, -43.5424957275390625, 2.181660413742065429, 0, 0, 0.887010574340820312, 0.461749136447906494, 300, 255, 1, "", 49345, NULL),
(3478, 2744, 0, 0, 0, 1, 1, -12324.0830078125, 535.95367431640625, -65.3733749389648437, 0.663223206996917724, 0, 0, 0.325567245483398437, 0.945518851280212402, 300, 255, 1, "", 45772, NULL),
(3479, 2744, 0, 0, 0, 1, 1, -12328.40625, 709.5440673828125, -45.4184150695800781, 4.502951622009277343, 0, 0, -0.7771453857421875, 0.629321098327636718, 300, 255, 1, "", 45772, NULL),
(3480, 2744, 0, 0, 0, 1, 1, -12328.4462890625, 572.81036376953125, -65.9415054321289062, 3.874631166458129882, 0, 0, -0.93358039855957031, 0.358368009328842163, 300, 255, 1, "", 47168, NULL),
(3481, 2744, 0, 0, 0, 1, 1, -12329.5849609375, 650.5650634765625, -42.0246963500976562, 1.186823248863220214, 0, 0, 0.559192657470703125, 0.829037725925445556, 300, 255, 1, "", 50664, NULL),
(3482, 2744, 0, 0, 0, 1, 1, -12339.1826171875, 605.053955078125, -66.5669021606445312, 0.209439441561698913, 0, 0, 0.104528427124023437, 0.994521915912628173, 300, 255, 1, "", 45772, NULL),
(3483, 2744, 0, 0, 0, 1, 1, -12348.8857421875, 442.909454345703125, -38.4705696105957031, 4.45059061050415039, 0, 0, -0.79335308074951171, 0.608761727809906005, 300, 255, 1, "", 45572, NULL),
(3484, 2744, 0, 0, 0, 1, 1, -12355.35546875, 544.90972900390625, -84.1712570190429687, 2.775068521499633789, 0, 0, 0.983254432678222656, 0.182238012552261352, 300, 255, 1, "", 49345, NULL),
(3485, 2744, 0, 0, 0, 1, 1, -12357.2529296875, 576.179931640625, -71.4578628540039062, 5.235987663269042968, 0, 0, -0.5, 0.866025388240814208, 300, 255, 1, "", 52237, NULL),
(3486, 2744, 0, 0, 0, 1, 1, -12357.548828125, 690.5987548828125, -21.5122146606445312, 3.595378875732421875, 0, 0, -0.97437000274658203, 0.224951311945915222, 300, 255, 1, "", 45772, NULL),
(3487, 2744, 0, 0, 0, 1, 1, -12357.7109375, 475.235626220703125, -90.5011749267578125, 1.623155713081359863, 0, 0, 0.725374221801757812, 0.688354730606079101, 300, 255, 1, "", 48019, NULL),
(3488, 2744, 0, 0, 0, 1, 1, -12359.6318359375, 665.0457763671875, -37.03369140625, 3.543023586273193359, 0, 0, -0.97992420196533203, 0.199370384216308593, 300, 255, 1, "", 45572, NULL),
(3489, 2744, 0, 0, 0, 1, 1, -12372.958984375, 576.60809326171875, -88.2532806396484375, 1.658061861991882324, 0, 0, 0.737277030944824218, 0.67559051513671875, 300, 255, 1, "", 45572, NULL),
(3490, 2744, 0, 0, 0, 1, 1, -12378.8916015625, 647.649658203125, -64.9648818969726562, 5.009094715118408203, 0, 0, -0.59482288360595703, 0.80385679006576538, 300, 255, 1, "", 45572, NULL),
(3491, 2744, 0, 0, 0, 1, 1, -12387.9462890625, 685.329345703125, -53.21832275390625, 0.017452461645007133, 0, 0, 0.008726119995117187, 0.999961912631988525, 300, 255, 1, "", 48120, NULL),
(3492, 2744, 0, 0, 0, 1, 1, -12390.2548828125, 608.60711669921875, -106.115257263183593, 5.270895957946777343, 0, 0, -0.48480892181396484, 0.87462007999420166, 300, 255, 1, "", 45772, NULL),
(3493, 2744, 0, 0, 0, 1, 1, -12406.4111328125, 706.82012939453125, -33.0999336242675781, 1.291541695594787597, 0, 0, 0.60181427001953125, 0.798636078834533691, 300, 255, 1, "", 48019, NULL),
(3494, 2744, 0, 0, 0, 1, 1, -12406.908203125, 440.619537353515625, -41.5363845825195312, 2.70525527000427246, 0, 0, 0.97629547119140625, 0.216442063450813293, 300, 255, 1, "", 45613, NULL),
(3495, 2744, 0, 0, 0, 1, 1, -12407.181640625, 633.13824462890625, -89.5317153930664062, 3.176533222198486328, 0, 0, -0.999847412109375, 0.017469281330704689, 300, 255, 1, "", 50664, NULL),
(3496, 2744, 0, 0, 0, 1, 1, -12409.3525390625, 503.579803466796875, -75.6299819946289062, 3.385940074920654296, 0, 0, -0.99254608154296875, 0.121869951486587524, 300, 255, 1, "", 48019, NULL),
(3497, 2744, 0, 0, 0, 1, 1, -12410.47265625, 455.93707275390625, -63.8843536376953125, 6.021387100219726562, 0, 0, -0.13052558898925781, 0.991444945335388183, 300, 255, 1, "", 48120, NULL),
(3498, 2744, 0, 0, 0, 1, 1, -12415.205078125, 674.24493408203125, -67.7239303588867187, 2.44346022605895996, 0, 0, 0.939692497253417968, 0.34202045202255249, 300, 255, 1, "", 48120, NULL),
(3499, 2744, 0, 0, 0, 1, 1, -12420.8681640625, 564.3009033203125, -96.0813217163085937, 5.654868602752685546, 0, 0, -0.30901622772216796, 0.95105677843093872, 300, 255, 1, "", 45572, NULL),
(3500, 2744, 0, 0, 0, 1, 1, -12422.203125, 529.30615234375, -92.2594985961914062, 0.802850961685180664, 0, 0, 0.390730857849121093, 0.920504987239837646, 300, 255, 1, "", 52237, NULL),
(3501, 2744, 0, 0, 0, 1, 1, -12424.3798828125, 635.39898681640625, -99.6658477783203125, 4.398232460021972656, 0, 0, -0.80901622772216796, 0.587786316871643066, 300, 255, 1, "", 48019, NULL),
(3502, 2744, 0, 0, 0, 1, 1, -12431.9970703125, 487.49945068359375, -69.9343032836914062, 1.972219824790954589, 0, 0, 0.83388519287109375, 0.55193793773651123, 300, 255, 1, "", 48019, NULL),
(3503, 2744, 0, 0, 0, 1, 1, -12433.3994140625, 709.91156005859375, -53.2276840209960937, 0, 0, 0, 0, 1, 300, 255, 1, "", 45572, NULL),
(3504, 2744, 0, 0, 0, 1, 1, -12435.99609375, 582.399169921875, -103.410621643066406, 1.134462952613830566, 0, 0, 0.537299156188964843, 0.843391716480255126, 300, 255, 1, "", 49822, NULL),
(3505, 2744, 0, 0, 0, 1, 1, -12439.669921875, 455.67724609375, -47.6966323852539062, 0.750490784645080566, 0, 0, 0.3665008544921875, 0.93041771650314331, 300, 255, 1, "", 45572, NULL),
(3506, 2744, 0, 0, 0, 1, 1, -12441.2568359375, 545.54913330078125, -81.1741485595703125, 6.021387100219726562, 0, 0, -0.13052558898925781, 0.991444945335388183, 300, 255, 1, "", 45572, NULL),
(3507, 2744, 0, 0, 0, 1, 1, -12446.66015625, 653.4971923828125, -76.8185958862304687, 1.413715124130249023, 0, 0, 0.649447441101074218, 0.760406434535980224, 300, 255, 1, "", 47168, NULL),
(3508, 2744, 0, 0, 0, 1, 1, -12453.314453125, 688.5665283203125, -67.7992324829101562, 2.024578809738159179, 0, 0, 0.848047256469726562, 0.529920578002929687, 300, 255, 1, "", 48019, NULL),
(3509, 2744, 0, 0, 0, 1, 1, -12453.5244140625, 519.727294921875, -72.177520751953125, 5.794494152069091796, 0, 0, -0.24192142486572265, 0.970295846462249755, 300, 255, 1, "", 47168, NULL),
(3510, 2744, 0, 0, 0, 1, 1, -12458.4033203125, 454.407012939453125, -43.0031089782714843, 2.687806606292724609, 0, 0, 0.974370002746582031, 0.224951311945915222, 300, 255, 1, "", 45772, NULL),
(3511, 2744, 0, 0, 0, 1, 1, -12466.10546875, 567.4268798828125, -69.4961624145507812, 0.436331570148468017, 0, 0, 0.216439247131347656, 0.976296067237854003, 300, 255, 1, "", 45613, NULL),
(3512, 2744, 0, 0, 0, 1, 1, -12472.2548828125, 554.970458984375, -60.8499641418457031, 0.069811686873435974, 0, 0, 0.034898757934570312, 0.999390840530395507, 300, 255, 1, "", 48120, NULL),
(3513, 2744, 0, 0, 0, 1, 1, -12472.4443359375, 594.99560546875, -87.6874771118164062, 3.874631166458129882, 0, 0, -0.93358039855957031, 0.358368009328842163, 300, 255, 1, "", 45572, NULL),
(3514, 2744, 0, 0, 0, 1, 1, -12481.4423828125, 505.266510009765625, -61.46136474609375, 1.972219824790954589, 0, 0, 0.83388519287109375, 0.55193793773651123, 300, 255, 1, "", 48019, NULL);
-- remaining spawns (no sniffed values available)
-- (`guid` IN (2134849, 2134854, 2134739, 2134863, 2134862, 2134864, 2134840, 2134848, 2134839, 2134853, 2134851))
-- pooling
DELETE FROM `pool_template` WHERE (`entry` IN (142));
INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES
(142, 20, 'Eastern Kingdoms - Giant Clam - 20/80');
DELETE FROM `pool_gameobject` WHERE (`pool_entry` IN (142)) AND (`guid` IN (11029, 11030, 11686, 11687, 11811, 11818, 32097));
DELETE FROM `pool_gameobject` WHERE (`pool_entry` IN (142)) AND (`guid` BETWEEN 3442 AND 3514);
INSERT INTO `pool_gameobject` (`guid`, `pool_entry`, `chance`, `description`) VALUES
(11029, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(11030, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(11686, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(11687, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(11811, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(11818, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(32097, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3442, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3443, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3444, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3445, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3446, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3447, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3448, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3449, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3450, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3451, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3452, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3453, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3454, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3455, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3456, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3457, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3458, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3459, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3460, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3461, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3462, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3463, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3464, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3465, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3466, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3467, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3468, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3469, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3470, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3471, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3472, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3473, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3474, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3475, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3476, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3477, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3478, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3479, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3480, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3481, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3482, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3483, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3484, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3485, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3486, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3487, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3488, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3489, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3490, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3491, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3492, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3493, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3494, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3495, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3496, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3497, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3498, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3499, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3500, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3501, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3502, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3503, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3504, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3505, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3506, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3507, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3508, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3509, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3510, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3511, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3512, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3513, 142, 0, 'Eastern Kingdoms - Giant Clam'),
(3514, 142, 0, 'Eastern Kingdoms - Giant Clam');
@@ -0,0 +1,11 @@
-- DB update 2025_01_19_00 -> 2025_01_19_01
--
-- Deletes `LANG_PASSWORD_TOO_LONG` and `LANG_ACCOUNT_TOO_LONG`.
DELETE FROM `acore_string` WHERE `entry` IN (55, 1005);
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
-- Added the missing texts (LANG_PASSWORD_TOO_LONG) for "French" and "Russian".
(55, "Your password can't be longer than 16 characters (client limit), password not changed!", NULL, "Le mot de passe ne doit pas dépasser 16 caractères (limitation technique du client), le mot de passe n'a pas été changé!", "Das Passwort kann nicht länger als 16 Zeichen sein (Client Limit). Das Passwort wurde nicht geändert!", "你的新密码不能超过16个字符 (客户端限制), 密码没有修改!", NULL, "Su contraseña no puede tener más de 16 caracteres (límite del cliente), ¡la contraseña no se cambia!", "Su contraseña no puede tener más de 16 caracteres (límite del cliente), ¡la contraseña no se cambia!", "Ваш пароль не может быть длиннее 16 символов (клиентский лимит), пароль не изменен!"),
-- Added the missing texts (LANG_ACCOUNT_TOO_LONG) for "French", "Spain Spanish", "Mexican Spanish" and "Russian.
-- Corrcted ALL the character "client limit" to 17 (from 20).
(1005, "Account name can't be longer than 17 characters (client limit), account not created!", NULL, "Le nom de compte ne doit pas dépasser 17 caractères (limitation technique du client), le compte n'a pas été créé!", "Der Account Name kann nicht länger als 17 Zeichen sein (Client Limit). Account wurde nicht erstellt!", "帐号名长度不能超过17个字符(客户端限制),帐户创建失败!", NULL, "El nombre de la cuenta no puede tener más de 17 caracteres (límite de cliente), ¡cuenta no creada!", "El nombre de la cuenta no puede tener más de 17 caracteres (límite de cliente), ¡cuenta no creada!", "Имя учетной записи не может быть длиннее 17 символов (ограничение для клиента), учетная запись не создана!");
+259
View File
@@ -0,0 +1,259 @@
-- DB update 2025_01_19_01 -> 2025_01_19_02
-- Ashbringer is buff
DELETE
FROM `spell_custom_attr`
WHERE `spell_id` = 28282;
INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (28282, 67108864);
-- It takes time to open the door with a key in Blizzard servers
UPDATE `gameobject_template_addon` SET `flags` = `flags`|2|32
WHERE (`entry` = 104591);
-- Clientside area trigger 4089 smart ai
SET @ENTRY := 4089;
DELETE FROM `areatrigger_scripts` WHERE `entry` = @ENTRY;
INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES (@ENTRY, 'SmartTrigger');
DELETE FROM `smart_scripts` WHERE `source_type` = 2 AND `entryOrGuid` = @ENTRY;
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_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(@ENTRY, 2, 0, 1, 46, 0, 100, 1, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'On trigger - Self: storedTarget[0] = Triggering player'),
(@ENTRY, 2, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 34, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'On trigger - Set instance data #2 to 1'),
(@ENTRY, 2, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 10, 40029, 3976, 0, 0, 0, 0, 0, 'On trigger - Send stored target storedTarget[0] to Creature Scarlet Commander Mograine (3976) with guid 40029 (fetching)'),
(@ENTRY, 2, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 0, 1, 0, 0, 0, 0, 10, 40029, 3976, 0, 0, 0, 0, 0, 'On trigger - Creature Scarlet Commander Mograine (3976) with guid 40029 (fetching): Set creature data #0 to 1');
-- smart conditions
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 22 AND `SourceEntry` = @ENTRY AND `SourceId` = 2;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `Comment`) VALUES
(22, 1, @ENTRY, 2, 0, 1, 0, 28282, 0, 0, 0, 'Action invoker has aura of spell Ashbringer (28282), effect EFFECT_0'),
(22, 1, @ENTRY, 2, 0, 13, 0, 2, 0, 0, 0, 'instance data 2 equals 0');
-- Scarlet Commander Mograine smart ai
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 3976;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 3976);
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
(3976, 0, 0, 0, 38, 0, 100, 0, 0, 1, 0, 0, 0, 0, 1, 6, 0, 1, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Data Set 0 1 - Say Line 6'),
(3976, 0, 1, 0, 0, 0, 100, 1, 0, 0, 0, 0, 0, 0, 11, 8990, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - In Combat - Cast \'Retribution Aura\' (No Repeat)'),
(3976, 0, 2, 0, 0, 0, 100, 1, 1000, 1000, 0, 0, 0, 0, 34, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - In Combat - Set Instance Data 1 to 1 (No Repeat)'),
(3976, 0, 3, 0, 0, 0, 100, 0, 1000, 5000, 10000, 10000, 0, 0, 11, 14518, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - In Combat - Cast \'Crusader Strike\''),
(3976, 0, 4, 0, 0, 0, 100, 0, 6000, 11000, 60000, 60000, 0, 0, 11, 5589, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - In Combat - Cast \'Hammer of Justice\''),
(3976, 0, 5, 6, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Respawn - Set Active Off'),
(3976, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Respawn - Remove Flags Not Selectable'),
(3976, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Respawn - Set Reactstate Aggressive'),
(3976, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Respawn - Remove FlagStandstate Dead'),
(3976, 0, 9, 10, 4, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Aggro - Set Invincibility Hp 1'),
(3976, 0, 10, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Aggro - Say Line 0'),
(3976, 0, 11, 12, 7, 0, 100, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Evade - Stop motion (StopMoving: 0, MovementExpired: 0)'),
(3976, 0, 12, 13, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 96, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Evade - Remove Dynamic Flags Dead'),
(3976, 0, 13, 14, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 34, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Evade - Set Instance Data 1 to 2'),
(3976, 0, 14, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Evade - Remove Flags Not Selectable'),
(3976, 0, 15, 0, 5, 0, 100, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Killed Unit - Say Line 1'),
(3976, 0, 16, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 34, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Just Died - Set Instance Data 1 to 3'),
(3976, 0, 17, 0, 2, 0, 100, 1, 0, 1, 0, 0, 0, 0, 80, 397600, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Between 0-1% Health - Run Script (No Repeat)'),
(3976, 0, 18, 0, 8, 1, 100, 512, 9232, 0, 0, 0, 0, 0, 80, 397601, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Spellhit \'Scarlet Resurrection\' - Run Script (Phase 1)'),
(3976, 0, 19, 20, 34, 0, 100, 0, 8, 1, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Reached Point 1 - Reset Invincibility Hp'),
(3976, 0, 20, 21, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 19, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Reached Point 1 - Remove Flags Not Selectable'),
(3976, 0, 21, 22, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Reached Point 1 - Set Reactstate Aggressive'),
(3976, 0, 22, 23, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 8990, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Reached Point 1 - Cast \'Retribution Aura\''),
(3976, 0, 23, 24, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Reached Point 1 - Start Attacking'),
(3976, 0, 24, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Reached Point 1 - Start Attacking'),
(3976, 0, 25, 0, 8, 0, 100, 1, 28441, 0, 0, 0, 0, 0, 80, 397602, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Spellhit \'AB Effect 000\' - Run Script (No Repeat)'),
(3976, 0, 26, 0, 8, 0, 100, 1, 28441, 0, 0, 0, 0, 0, 67, 1, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Spellhit \'AB Effect 000\' - Create Timed Event (No Repeat)'),
(3976, 0, 27, 0, 59, 0, 100, 0, 1, 0, 0, 0, 0, 0, 12, 16062, 8, 0, 0, 0, 0, 8, 0, 0, 0, 0, 1033.46, 1399.1, 27.3374, 6.25796, 'Scarlet Commander Mograine - On Timed Event 1 Triggered - Summon Creature \'Highlord Mograine\''),
(3976, 0, 28, 0, 8, 0, 100, 0, 28697, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - On Spellhit \'Forgiveness\' - Kill Self');
-- Scarlet Commander Mograine suspended animation
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 397600);
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
(397600, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Stop Attack'),
(397600, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 0, 1, 0, 0, 0, 0, 10, 39946, 3977, 0, 0, 0, 0, 0, 0, 'Creature High Inquisitor Whitemane (3977) with guid 39946 (fetching): Set creature data #0 to 1'),
(397600, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 212, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Stop motion (StopMoving: 0, MovementExpired: 1)'),
(397600, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Start Random Movement'),
(397600, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 4, 1326, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Play Sound 1326'),
(397600, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 28, 8990, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Remove Aura \'Retribution Aura\''),
(397600, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Flag Standstate Dead'),
(397600, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 18, 33554432, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Flags Not Selectable'),
(397600, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Reactstate Passive'),
(397600, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Event Phase 1');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 397601);
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
(397601, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Reactstate Passive'),
(397601, 9, 1, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Remove FlagStandstate Dead'),
(397601, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 9257, 0, 0, 0, 0, 0, 10, 39946, 3977, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Cast \'Lay on Hands\''),
(397601, 9, 3, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 10, 39946, 3977, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Say Line 2'),
(397601, 9, 4, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 0, 10, 39946, 3977, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Move To Closest Creature \'High Inquisitor Whitemane\'');
-- Scarlet Commander Mograine Ashbringer Event
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 397602);
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
(397602, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Active On'),
(397602, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 35, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Faction 35'),
(397602, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Start Random Movement'),
(397602, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Orientation Invoker'),
(397602, 9, 4, 0, 0, 0, 100, 0, 1000, 3000, 0, 0, 0, 0, 90, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Set Flag Standstate Kneel'),
(397602, 9, 5, 0, 0, 0, 100, 0, 1000, 2000, 0, 0, 0, 0, 1, 3, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarlet Commander Mograine - Actionlist - Say Line 3');
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 22 AND `SourceEntry` = 3976 AND `SourceId` = 0;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `Comment`) VALUES
(22, 1, 3976, 0, 0, 21, 1, 16384, 0, 0, 1, 'Object doesn\'t have unit state UNIT_STATE_ATTACK_PLAYER'),
(22, 1, 3976, 0, 0, 36, 1, 0, 0, 0, 0, 'Object is alive'),
(22, 3, 3976, 0, 0, 4, 1, 796, 0, 0, 0, 'Object in zone (796)'),
(22, 18, 3976, 0, 0, 4, 1, 796, 0, 0, 0, 'Object in zone (796)'),
(22, 19, 3976, 0, 0, 4, 1, 796, 0, 0, 0, 'Object in zone (796)'),
(22, 26, 3976, 0, 0, 4, 1, 796, 0, 0, 0, 'Object in zone (796)'),
(22, 26, 3976, 0, 0, 36, 1, 0, 0, 0, 0, 'Object is alive'),
(22, 27, 3976, 0, 0, 4, 1, 796, 0, 0, 0, 'Object in zone (796)'),
(22, 27, 3976, 0, 0, 36, 1, 0, 0, 0, 0, 'Object is alive');
-- Scarlet Commander Mograine say
DELETE FROM `creature_text` WHERE `CreatureID` = 3976;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(3976, 0, 0, 'Infidels! They must be purified!', 14, 0, 100, 0, 0, 5835, 2847, 0, 'Scarlet Commander Mograine // mograine SAY_MO_AGGRO'),
(3976, 1, 0, 'Unworthy.', 14, 0, 100, 0, 0, 5836, 6197, 0, 'Scarlet Commander Mograine // mograine SAY_MO_KILL'),
(3976, 2, 0, 'At your side, milady!', 14, 0, 100, 15, 0, 5837, 18026, 0, 'Scarlet Commander Mograine // mograine SAY_MO_RESSURECTED'),
(3976, 3, 0, 'You hold my father\'s blade, $n. My soldiers are yours TO control, my $g Lord:Lady;. Take them... LEAD them... The impure must be purged. They must be cleansed of their taint.', 12, 0, 100, 1, 0, 0, 12390, 0, 'Scarlet Commander Mograine // mograine SAY_ASHBRINGER_ONE'),
(3976, 4, 0, 'Father... But... How?', 12, 0, 100, 6, 0, 0, 12470, 0, 'Scarlet Commander Mograine // mograine SAY_ASHBRINGER_TWO'),
(3976, 5, 0, 'Forgive me, father! Please...', 12, 0, 100, 20, 0, 0, 12472, 0, 'Scarlet Commander Mograine // mograine SAY_ASHBRINGER_THREE'),
(3976, 6, 0, 'Bow down! Kneel BEFORE the Ashbringer! A NEW dawn approaches, brothers AND sisters! Our message will be delivered TO the filth of this world through the chosen one!', 14, 0, 100, 0, 0, 0, 12389, 3, 'Scarlet Commander Mograine // Ashbringer EVENT intro yell');
-- Highlord Mograine smart_scripts
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 16062;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 16062);
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
(16062, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - On Just Summoned - Set Active On'),
(16062, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 35, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - On Just Summoned - Set Faction 35'),
(16062, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - On Just Summoned - Change Equipment'),
(16062, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 16180, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - On Just Summoned - Morph To Model 16180'),
(16062, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 28688, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - On Just Summoned - Cast \'Mograine Cometh DND\''),
(16062, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 53, 0, 16062, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - On Just Summoned - Start Waypoint Path 16062'),
(16062, 0, 6, 7, 40, 0, 100, 0, 12, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 19, 3976, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - On Point 12 of Path Any Reached - Set Orientation Closest Creature \'Scarlet Commander Mograine\''),
(16062, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 1606200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - On Point 12 of Path Any Reached - Run Script');
-- Highlord Mograine Ashbringer Event
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 1606200);
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
(1606200, 9, 0, 0, 0, 0, 100, 0, 200, 200, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Say Line 0'),
(1606200, 9, 1, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 231, 2, 0, 0, 0, 0, 0, 19, 3976, 5, 0, 0, 0, 0, 0, 0, 'Closest alive creature Scarlet Commander Mograine (3976) in 5 yards: - Actionlist - Set Target Orientation'),
(1606200, 9, 2, 0, 0, 0, 100, 0, 400, 400, 0, 0, 0, 0, 91, 8, 0, 0, 0, 0, 0, 19, 3976, 5, 0, 0, 0, 0, 0, 0, 'Closest alive creature Scarlet Commander Mograine (3976) in 5 yards: - Actionlist - Remove FlagStandstate Kneel'),
(1606200, 9, 3, 0, 0, 0, 100, 0, 1200, 1200, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 19, 3976, 5, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Say Line 4'),
(1606200, 9, 4, 0, 0, 0, 100, 0, 4600, 4600, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Say Line 1'),
(1606200, 9, 5, 0, 0, 0, 100, 0, 3400, 3400, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Play Emote 6'),
(1606200, 9, 6, 0, 0, 0, 100, 0, 3200, 3200, 0, 0, 0, 0, 5, 25, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Play Emote 25'),
(1606200, 9, 7, 0, 0, 0, 100, 0, 3200, 3200, 0, 0, 0, 0, 5, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Play Emote 15'),
(1606200, 9, 8, 0, 0, 0, 100, 0, 3200, 3200, 0, 0, 0, 0, 231, 2, 0, 0, 0, 0, 0, 19, 3976, 5, 0, 0, 0, 0, 0, 0, 'Closest alive creature Scarlet Commander Mograine (3976) in 5 yards: - Actionlist - Set Target Orientation'),
(1606200, 9, 9, 0, 0, 0, 100, 0, 1200, 1200, 0, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 19, 3976, 5, 0, 0, 0, 0, 0, 0, 'Closest alive creature Scarlet Commander Mograine (3976) in 5 yards: - Actionlist - Say Line 5'),
(1606200, 9, 10, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 11, 28697, 0, 0, 0, 0, 0, 19, 3976, 10, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Cast \'Forgiveness\''),
(1606200, 9, 11, 0, 0, 0, 100, 0, 3700, 3700, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Say Line 2'),
(1606200, 9, 12, 0, 0, 0, 100, 0, 3400, 3400, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Highlord Mograine - Actionlist - Despawn Instant');
-- Highlord Mograine Say
DELETE FROM `creature_text` WHERE `CreatureID`=16062;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `Type`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(16062, 0, 0, 'Renault...', 0, 100, 25, 0, 0, 12, 12469, 0, 'mograine MOGRAINE_ONE'),
(16062, 1, 0, 'Did you think that your betrayal would be forgotten? Lost in the carefully planned cover up of my death? Blood of my blood, the blade felt your cruelty long after my heart had stopped beating. And in death, I knew what you had done. But now, the chains of Kel\'thuzad hold me NO more. I come TO serve justice. I AM ASHBRINGER.', 0, 100, 6, 0, 0, 12, 12471, 0, 'mograine MOGRAINE_TWO'),
(16062, 2, 0, 'You are forgiven...', 0, 100, 0, 0, 0, 12, 12473, 0, 'mograine MOGRAINE_THREE');
DELETE
FROM `waypoints`
WHERE `entry`=16062;
INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `point_comment`) VALUES
(16062, 1, 1033.4642, 1399.1022, 27.337427, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 2, 1034.9252, 1399.0653, 27.393204, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 3, 1036.3861, 1399.0284, 27.44898, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 4, 1045.484, 1398.7991, 27.448977, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 5, 1059.524, 1399.0273, 28.271557, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 6, 1068.8096, 1399.2064, 30.7867, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 7, 1086.6564, 1399.2048, 30.44898, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 8, 1101.5681, 1399.3694, 30.485447, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 9, 1116.6019, 1399.4752, 30.485447, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 10, 1129.5881, 1399.2926, 30.524086, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 11, 1149.4045, 1399.0231, 32.528877, NULL, 0, 'Ashbringer Event Move Points'),
(16062, 12, 1150.3911, 1398.723, 32.54613, NULL, 0, 'Ashbringer Event Move Points');
-- Highlord Mograine Condition
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 1) AND (`SourceEntry` = 8990) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 3) AND (`ConditionValue2` = 16062) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 8990, 0, 0, 31, 0, 3, 16062, 0, 1, 0, 0, '', 'Potential target of the spell is not creature, entry is 16062');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 1) AND (`SourceEntry` = 16062) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 4) AND (`ConditionTarget` = 1) AND (`ConditionValue1` = 796) AND (`ConditionValue2` = 0) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(22, 1, 16062, 0, 0, 4, 1, 796, 0, 0, 0, 0, 0, '', 'Object in zone (796)');
-- High Inquisitor Whitemane Smart ai
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 3977;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 3977);
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
(3977, 0, 0, 1, 38, 0, 100, 0, 0, 1, 0, 0, 0, 0, 118, 2, 0, 0, 0, 0, 0, 14, 11877, 104600, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Data Set 0 1 - Set GO State To 2'),
(3977, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Data Set 0 1 - Say Line 0'),
(3977, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 0, 10, 40029, 3976, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Data Set 0 1 - Move To Closest Creature \'Scarlet Commander Mograine\''),
(3977, 0, 3, 4, 4, 0, 100, 0, 0, 0, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Aggro - Set Invincibility Hp 1'),
(3977, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Aggro - Set Event Phase 1'),
(3977, 0, 5, 0, 0, 3, 100, 0, 1000, 1000, 2600, 4000, 0, 0, 11, 9481, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - In Combat - Cast \'Holy Smite\' (Phases 1 & 2)'),
(3977, 0, 6, 0, 16, 3, 100, 0, 22187, 40, 5000, 10000, 1, 0, 11, 22187, 32, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Friendly Unit Missing Buff \'Power Word: Shield\' - Cast \'Power Word: Shield\' (Phases 1 & 2)'),
(3977, 0, 7, 0, 0, 2, 100, 0, 45000, 45000, 20000, 30000, 0, 0, 11, 14515, 64, 0, 0, 0, 0, 6, 20, 1, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - In Combat - Cast \'Dominate Mind\' (Phase 2)'),
(3977, 0, 8, 0, 74, 2, 100, 0, 5000, 15000, 5000, 15000, 75, 40, 11, 12039, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Friendly Below 75% Health - Cast \'Heal\' (Phase 2)'),
(3977, 0, 9, 0, 5, 0, 100, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Killed Unit - Say Line 1'),
(3977, 0, 10, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 118, 1, 0, 0, 0, 0, 0, 14, 11877, 104600, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Respawn - Set GO State To 1'),
(3977, 0, 11, 12, 7, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Evade - Set Reactstate Aggressive'),
(3977, 0, 12, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 34, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Evade - Set Instance Data 1 to 2'),
(3977, 0, 13, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 34, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Just Died - Set Instance Data 1 to 3'),
(3977, 0, 14, 15, 2, 0, 100, 513, 0, 50, 0, 0, 0, 0, 80, 397700, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Between 0-50% Health - Run Script (No Repeat)'),
(3977, 0, 15, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Between 0-50% Health - Set Event Phase 1 (No Repeat)'),
(3977, 0, 16, 0, 38, 0, 100, 0, 1, 1, 0, 0, 0, 0, 67, 1, 200, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Data Set 1 1 - Create Timed Event'),
(3977, 0, 17, 0, 59, 0, 100, 0, 1, 0, 0, 0, 0, 0, 80, 397701, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Timed Event 1 Triggered - Run Script'),
(3977, 0, 18, 0, 38, 0, 100, 0, 1, 1, 0, 0, 0, 0, 69, 2, 0, 0, 2, 0, 0, 10, 40029, 3976, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Data Set 1 1 - Move To Closest Creature \'Scarlet Commander Mograine\''),
(3977, 0, 19, 0, 34, 0, 100, 512, 8, 2, 0, 0, 0, 0, 80, 397701, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - On Reached Point 2 - Run Script');
-- Health less than 50% Hypnotize the player
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 397700);
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
(397700, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Stop Attack'),
(397700, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Set Event Phase 0'),
(397700, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Set Reactstate Passive'),
(397700, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 9256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Cast \'Deep Sleep\''),
(397700, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'After 0 seconds - Self: Set data[1] to 1');
-- Resurrect Mograini
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 397701);
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
(397701, 9, 0, 0, 0, 0, 100, 0, 4500, 4500, 0, 0, 0, 0, 11, 9232, 0, 0, 0, 0, 0, 19, 3976, 50, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Cast \'Scarlet Resurrection\''),
(397701, 9, 1, 0, 0, 0, 100, 0, 1900, 1900, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Say Line 2'),
(397701, 9, 2, 0, 0, 0, 100, 0, 1400, 1400, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Set Sheath Unarmed'),
(397701, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 5, 66, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Play Emote 66'),
(397701, 9, 4, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Reset Invincibility Hp'),
(397701, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Set Reactstate Aggressive'),
(397701, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Set Event Phase 2'),
(397701, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Whitemane - Actionlist - Start Attacking');
-- High Inquisitor Whitemane say
DELETE FROM `creature_text` WHERE `CreatureID` = 3977;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(3977, 0, 0, 'Mograine has fallen! You shall pay for this treachery! Arise, my champion! Arise!', 14, 0, 100, 0, 0, 5838, 18023, 0, 'High Inquisitor Whitemane // whitemane SAY_WH_INTRO'),
(3977, 1, 0, 'The Light has spoken!', 14, 0, 100, 0, 0, 5839, 6198, 0, 'High Inquisitor Whitemane // whitemane SAY_WH_KILL'),
(3977, 2, 0, 'Arise, my champion!', 14, 0, 100, 0, 0, 5840, 6532, 0, 'High Inquisitor Whitemane // whitemane SAY_WH_RESSURECT');
-- High Inquisitor Whitemane Conditions
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 22 AND `SourceEntry` = 3977 AND `SourceId` = 0;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `Comment`) VALUES
(22, 17, 3977, 0, 0, 29, 1, 3976, 5, 0, 0, 'There is creature Scarlet Commander Mograine (3976) within range 5 yards to Object'),
(22, 19, 3977, 0, 0, 29, 1, 3976, 5, 0, 1, 'There is no creature Scarlet Commander Mograine (3976) within range 5 yards to Object');
-- High Inquisitor Fairbanks smart ai
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 4542;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 4542) AND (`source_type` = 0) AND (`id` IN (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
(4542, 0, 11, 0, 8, 0, 100, 1, 28441, 0, 0, 0, 0, 0, 80, 454205, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Fairbanks - On Spellhit \'AB Effect 000\' - Run Script (No Repeat)');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 454205);
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
(454205, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 2, 35, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Fairbanks - Actionlist - Set Faction 35'),
(454205, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Fairbanks - Actionlist - Set Orientation Invoker'),
(454205, 9, 2, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 11, 28443, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Fairbanks - Actionlist - Cast \'Transform Ghost\''),
(454205, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 3, 0, 16179, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Fairbanks - Actionlist - Morph To Model 16179'),
(454205, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 82, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'High Inquisitor Fairbanks - Actionlist - Add Npc Flags Gossip');
@@ -0,0 +1,8 @@
-- DB update 2025_01_19_02 -> 2025_01_22_00
-- Change creature template flags (before: IMMUNE_TO_PC, IMMUNE_TO_NPC, NOT_SELECTABLE. now: STUNNED, NOT_SELECTABLE).
UPDATE `creature_template` SET `unit_flags`=`unit_flags`& ~33555200 WHERE (`entry` = 24722);
UPDATE `creature_template` SET `unit_flags`=`unit_flags`|33816576 WHERE (`entry` = 24722);
-- Add Rooted and Flight (Sniffed Flags).
UPDATE `creature_template_movement` SET `Flight` = 1, `Rooted` = 1 WHERE (`CreatureId` = 24722);
@@ -0,0 +1,45 @@
-- DB update 2025_01_22_00 -> 2025_01_22_01
-- Shoveltusk Stag
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23691;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23691);
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
(23691, 0, 0, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 55860, 32, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shoveltusk Stag - On Aggro - Cast \'Shoveltusk Charge\''),
(23691, 0, 1, 0, 0, 0, 100, 0, 8000, 12000, 20000, 30000, 0, 0, 11, 32019, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shoveltusk Stag - In Combat - Cast \'Gore\'');
-- Shoveltusk Forager
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29479;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29479);
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
(29479, 0, 0, 0, 4, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 55860, 32, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shoveltusk Stag - On Aggro - Cast \'Shoveltusk Charge\''),
(29479, 0, 1, 0, 0, 0, 100, 0, 8000, 12000, 20000, 30000, 0, 0, 11, 32019, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shoveltusk Stag - In Combat - Cast \'Gore\'');
-- Shoveltuck
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23690;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23690);
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
(23690, 0, 0, 0, 0, 0, 100, 0, 8000, 14000, 15000, 24000, 0, 0, 11, 42320, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shoveltusk - In Combat - Cast \'Head Butt\'');
-- Shoveltuck Calf
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24791;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24791);
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
(24791, 0, 0, 0, 0, 0, 100, 0, 8000, 14000, 15000, 24000, 0, 0, 11, 42320, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shoveltusk - In Combat - Cast \'Head Butt\'');
-- Tamed Shoveltusk
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29486;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29486);
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
(29486, 0, 0, 0, 0, 0, 100, 0, 8000, 14000, 15000, 24000, 0, 0, 11, 42320, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shoveltusk - In Combat - Cast \'Head Butt\'');
-- Tamed Shoveltusk
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 29487;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 29487);
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
(29487, 0, 0, 0, 0, 0, 100, 0, 8000, 14000, 15000, 24000, 0, 0, 11, 42320, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Shoveltusk - In Combat - Cast \'Head Butt\'');
@@ -0,0 +1,8 @@
-- DB update 2025_01_22_01 -> 2025_01_22_02
-- Change timers and update comments on SmartAI
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24777;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24777);
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
(24777, 0, 0, 0, 0, 0, 100, 0, 5000, 10000, 4000, 8000, 0, 0, 11, 46479, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Sunblade Sentinel - In Combat - Cast \'Fel Lightning\'');
@@ -0,0 +1,13 @@
-- DB update 2025_01_22_02 -> 2025_01_23_00
-- Phoenix
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24674;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24674);
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
(24674, 0, 0, 0, 37, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44196, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Initialize - Cast \'Rebirth\''),
(24674, 0, 1, 0, 60, 0, 100, 257, 2000, 2000, 0, 0, 0, 0, 11, 44197, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Update - Cast \'Burn\' (No Repeat)'),
(24674, 0, 2, 0, 24, 0, 100, 0, 44226, 1, 5000, 5000, 0, 0, 11, 44202, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Target Buffed With \'Gravity Lapse\' - Cast \'Fireball\''),
(24674, 0, 3, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 21, 40, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Reset - Start Attacking'),
(24674, 0, 4, 5, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 24675, 3, 20000, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Just Died - Summon Creature \'Phoenix Egg\''),
(24674, 0, 5, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 1000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Phoenix - On Just Died - Despawn In 1000 ms');
@@ -0,0 +1,3 @@
-- DB update 2025_01_23_00 -> 2025_01_23_01
--
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|2147483648 WHERE `entry` IN (24664, 24857);
@@ -0,0 +1,5 @@
-- DB update 2025_01_23_01 -> 2025_01_23_02
--
DELETE FROM `creature_text` WHERE `CreatureID` = 24664 AND `GroupID` = 7;
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(24664, 7, 0, 'Oh no, he was merely an instrument, a stepping stone to a much larger plan! It has all led to this... and this time you will not interfere!', 14, 0, 100, 25387, 0, 'kaelthas MT SAY_AGGRO_2');
@@ -0,0 +1,5 @@
-- DB update 2025_01_23_02 -> 2025_01_23_03
--
UPDATE `creature_template` SET `AIName` = '' WHERE `entry` = 24777;
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 24777) AND (`source_type` = 0);
UPDATE `creature_addon` SET `auras` = '44537' WHERE `guid` IN (96944, 96945, 96946);
+2
View File
@@ -189,6 +189,8 @@ services:
AC_LOGIN_DATABASE_INFO: "ac-database;3306;root;${DOCKER_DB_ROOT_PASSWORD:-password};acore_auth" AC_LOGIN_DATABASE_INFO: "ac-database;3306;root;${DOCKER_DB_ROOT_PASSWORD:-password};acore_auth"
AC_WORLD_DATABASE_INFO: "ac-database;3306;root;${DOCKER_DB_ROOT_PASSWORD:-password};acore_world" AC_WORLD_DATABASE_INFO: "ac-database;3306;root;${DOCKER_DB_ROOT_PASSWORD:-password};acore_world"
AC_CHARACTER_DATABASE_INFO: "ac-database;3306;root;${DOCKER_DB_ROOT_PASSWORD:-password};acore_characters" AC_CHARACTER_DATABASE_INFO: "ac-database;3306;root;${DOCKER_DB_ROOT_PASSWORD:-password};acore_characters"
networks:
- ac-network
ports: ports:
- ${DOCKER_AUTH_EXTERNAL_PORT:-3724}:3724 - ${DOCKER_AUTH_EXTERNAL_PORT:-3724}:3724
- ${DOCKER_WORLD_EXTERNAL_PORT:-8085}:8085 - ${DOCKER_WORLD_EXTERNAL_PORT:-8085}:8085
+72 -60
View File
@@ -18,40 +18,49 @@
#ifndef LOCKEDQUEUE_H #ifndef LOCKEDQUEUE_H
#define LOCKEDQUEUE_H #define LOCKEDQUEUE_H
#include <atomic>
#include <deque> #include <deque>
#include <memory>
#include <mutex> #include <mutex>
template <class T, typename StorageType = std::deque<T>> template <class T, typename StorageType = std::deque<T>>
class LockedQueue class LockedQueue
{ {
//! Lock access to the queue. mutable std::mutex _lock; ///< Mutex to protect access to the queue
std::mutex _lock;
//! Storage backing the queue. std::atomic<bool> _canceled{false}; ///< Flag indicating if the queue is canceled
StorageType _queue;
//! Cancellation flag. StorageType _queue; ///< Storage container for the queue
volatile bool _canceled{false};
public: public:
//! Create a LockedQueue. /**
* @brief Default constructor to create an empty LockedQueue.
*/
LockedQueue() = default; LockedQueue() = default;
//! Destroy a LockedQueue. /**
* @brief Destructor for LockedQueue.
*/
virtual ~LockedQueue() = default; virtual ~LockedQueue() = default;
//! Adds an item to the queue. /**
* @brief Adds an item to the back of the queue.
*
* @param item The item to be added to the queue.
*/
void add(const T& item) void add(const T& item)
{ {
lock(); std::lock_guard<std::mutex> lock(_lock);
_queue.push_back(std::move(item));
_queue.push_back(item);
unlock();
} }
//! Adds items back to front of the queue /**
* @brief Adds a range of items to the front of the queue.
*
* @param begin Iterator pointing to the beginning of the range of items to be added.
* @param end Iterator pointing to the end of the range of items to be added.
*/
template<class Iterator> template<class Iterator>
void readd(Iterator begin, Iterator end) void readd(Iterator begin, Iterator end)
{ {
@@ -59,33 +68,42 @@ public:
_queue.insert(_queue.begin(), begin, end); _queue.insert(_queue.begin(), begin, end);
} }
//! Gets the next result in the queue, if any. /**
* @brief Gets the next item in the queue and removes it.
*
* @param result The variable where the next item will be stored.
* @return true if an item was retrieved and removed, false if the queue is empty.
*/
bool next(T& result) bool next(T& result)
{ {
std::lock_guard<std::mutex> lock(_lock); std::lock_guard<std::mutex> lock(_lock);
if (_queue.empty()) if (_queue.empty())
{ {
return false; return false;
} }
result = _queue.front(); result = std::move(_queue.front());
_queue.pop_front(); _queue.pop_front();
return true; return true;
} }
/**
* @brief Retrieves the next item from the queue if it satisfies the provided checker.
*
* @param result The variable where the next item will be stored.
* @param check A checker object that will be used to validate the item.
* @return true if an item was retrieved, checked, and removed; false otherwise.
*/
template<class Checker> template<class Checker>
bool next(T& result, Checker& check) bool next(T& result, Checker& check)
{ {
std::lock_guard<std::mutex> lock(_lock); std::lock_guard<std::mutex> lock(_lock);
if (_queue.empty()) if (_queue.empty())
{ {
return false; return false;
} }
result = _queue.front(); result = std::move(_queue.front());
if (!check.Process(result)) if (!check.Process(result))
{ {
return false; return false;
@@ -95,60 +113,54 @@ public:
return true; return true;
} }
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false. /**
T& peek(bool autoUnlock = false) * @brief Peeks at the top of the queue without removing it.
*
* @return A reference to the item at the front of the queue, assuming there's an item in the queue (as per previous implementation)
*/
T& peek()
{ {
lock(); std::lock_guard<std::mutex> lock(_lock);
return _queue.front();
T& result = _queue.front();
if (autoUnlock)
{
unlock();
}
return result;
} }
//! Cancels the queue. /**
* @brief Cancels the queue, preventing further processing of items.
*/
void cancel() void cancel()
{ {
std::lock_guard<std::mutex> lock(_lock); _canceled.store(true, std::memory_order_release);
_canceled = true;
} }
//! Checks if the queue is cancelled. /**
bool cancelled() * @brief Checks if the queue has been canceled.
*
* @return true if the queue is canceled, false otherwise.
*/
bool cancelled() const
{
return _canceled.load(std::memory_order_acquire);
}
/**
* @brief Checks if the queue is empty.
*
* @return true if the queue is empty, false otherwise.
*/
bool empty() const
{ {
std::lock_guard<std::mutex> lock(_lock); std::lock_guard<std::mutex> lock(_lock);
return _canceled; return _queue.empty();
} }
//! Locks the queue for access. /**
void lock() * @brief Removes the item at the front of the queue.
{ */
this->_lock.lock();
}
//! Unlocks the queue.
void unlock()
{
this->_lock.unlock();
}
///! Calls pop_front of the queue
void pop_front() void pop_front()
{ {
std::lock_guard<std::mutex> lock(_lock); std::lock_guard<std::mutex> lock(_lock);
_queue.pop_front(); _queue.pop_front();
} }
///! Checks if we're empty or not with locks held
bool empty()
{
std::lock_guard<std::mutex> lock(_lock);
return _queue.empty();
}
}; };
#endif #endif
+119 -30
View File
@@ -19,41 +19,81 @@
#define MPSCQueue_h__ #define MPSCQueue_h__
#include <atomic> #include <atomic>
#include <memory>
namespace Acore::Impl namespace Acore::Impl
{ {
// C++ implementation of Dmitry Vyukov's lock free MPSC queue /**
// http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue * @brief C++ implementation of Dmitry Vyukov's lock-free MPSC queue (Non-Intrusive).
*
* This queue allows multiple producers to enqueue items concurrently, but only one consumer
* can dequeue items. The queue is lock-free and non-intrusive, meaning it does not modify
* the data types that are enqueued.
*
* @tparam T The type of data that is being enqueued in the queue.
*/
template<typename T> template<typename T>
class MPSCQueueNonIntrusive class MPSCQueueNonIntrusive
{ {
public: public:
MPSCQueueNonIntrusive() : _head(new Node()), _tail(_head.load(std::memory_order_relaxed)) /**
* @brief Constructs a new MPSCQueueNonIntrusive object.
*
* Initializes the queue with a dummy node and sets up atomic pointers to the head and tail.
*/
MPSCQueueNonIntrusive()
: _head(new Node(nullptr)), _tail(_head.load(std::memory_order_acquire))
{ {
Node* front = _head.load(std::memory_order_relaxed); Node* front = _head.load(std::memory_order_acquire);
front->Next.store(nullptr, std::memory_order_relaxed); front->Next.store(nullptr, std::memory_order_release); ///< Store with release to ensure visibility
} }
/**
* @brief Destroys the MPSCQueueNonIntrusive object.
*
* Dequeues all items and deletes them, followed by proper cleanup of remaining nodes in the queue.
*/
~MPSCQueueNonIntrusive() ~MPSCQueueNonIntrusive()
{ {
T* output; T* output;
while (Dequeue(output)) while (Dequeue(output))
delete output; delete output;
Node* front = _head.load(std::memory_order_relaxed); // Properly delete remaining nodes
delete front; Node* front = _head.load(std::memory_order_acquire);
while (front)
{
Node* next = front->Next.load(std::memory_order_acquire);
delete front;
front = next;
}
} }
/**
* @brief Enqueues a new item in the queue.
*
* This function adds a new item at the head of the queue.
*
* @param input Pointer to the item to be enqueued.
*/
void Enqueue(T* input) void Enqueue(T* input)
{ {
Node* node = new Node(input); Node* node = new Node(input);
Node* prevHead = _head.exchange(node, std::memory_order_acq_rel); Node* prevHead = _head.exchange(node, std::memory_order_acq_rel); ///< Exchange with acquire-release semantics
prevHead->Next.store(node, std::memory_order_release); prevHead->Next.store(node, std::memory_order_release);
} }
/**
* @brief Dequeues an item from the queue.
*
* This function removes the item at the front of the queue and returns it.
*
* @param result Reference to a pointer where the dequeued item will be stored.
* @return True if an item was successfully dequeued, false if the queue was empty.
*/
bool Dequeue(T*& result) bool Dequeue(T*& result)
{ {
Node* tail = _tail.load(std::memory_order_relaxed); Node* tail = _tail.load(std::memory_order_acquire);
Node* next = tail->Next.load(std::memory_order_acquire); Node* next = tail->Next.load(std::memory_order_acquire);
if (!next) if (!next)
return false; return false;
@@ -65,39 +105,63 @@ namespace Acore::Impl
} }
private: private:
/**
* @brief A structure representing a node in the queue.
*
* Each node holds a pointer to data and an atomic pointer to the next node in the queue.
*/
struct Node struct Node
{ {
Node() = default; Node() = default;
explicit Node(T* data) : Data(data) explicit Node(T* data) : Data(data)
{ {
Next.store(nullptr, std::memory_order_relaxed); Next.store(nullptr, std::memory_order_release);
} }
T* Data; T* Data; ///< Data stored in the node
std::atomic<Node*> Next; std::atomic<Node*> Next; ///< Atomic pointer to the next node
}; };
std::atomic<Node*> _head; std::atomic<Node*> _head; ///< Atomic pointer to the head node of the queue
std::atomic<Node*> _tail; std::atomic<Node*> _tail; ///< Atomic pointer to the tail node of the queue
MPSCQueueNonIntrusive(MPSCQueueNonIntrusive const&) = delete; MPSCQueueNonIntrusive(MPSCQueueNonIntrusive const&) = delete; ///< Deleted copy constructor
MPSCQueueNonIntrusive& operator=(MPSCQueueNonIntrusive const&) = delete; MPSCQueueNonIntrusive& operator=(MPSCQueueNonIntrusive const&) = delete; ///< Deleted copy assignment operator
}; };
// C++ implementation of Dmitry Vyukov's lock free MPSC queue /**
// http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue * @brief C++ implementation of Dmitry Vyukov's lock-free MPSC queue (Intrusive).
*
* This queue allows multiple producers to enqueue items concurrently, but only one consumer
* can dequeue items. The queue is lock-free and intrusive, meaning that the enqueued objects
* must have an atomic link to the next item in the queue.
*
* @tparam T The type of data that is being enqueued in the queue.
* @tparam IntrusiveLink A member pointer to the atomic link used for linking the nodes.
*/
template<typename T, std::atomic<T*> T::* IntrusiveLink> template<typename T, std::atomic<T*> T::* IntrusiveLink>
class MPSCQueueIntrusive class MPSCQueueIntrusive
{ {
public: public:
MPSCQueueIntrusive() : _dummyPtr(reinterpret_cast<T*>(std::addressof(_dummy))), _head(_dummyPtr), _tail(_dummyPtr) /**
* @brief Constructs a new MPSCQueueIntrusive object.
*
* Initializes the queue with a dummy node and sets up atomic pointers to the head and tail.
* The dummy node's atomic link is initialized.
*/
MPSCQueueIntrusive()
: _dummyPtr(reinterpret_cast<T*>(std::addressof(_dummy))), _head(_dummyPtr), _tail(_dummyPtr)
{ {
// _dummy is constructed from aligned_storage and is intentionally left uninitialized (it might not be default constructible) // Initialize the intrusive link in the dummy node
// so we init only its IntrusiveLink here
std::atomic<T*>* dummyNext = new (&(_dummyPtr->*IntrusiveLink)) std::atomic<T*>(); std::atomic<T*>* dummyNext = new (&(_dummyPtr->*IntrusiveLink)) std::atomic<T*>();
dummyNext->store(nullptr, std::memory_order_relaxed); dummyNext->store(nullptr, std::memory_order_release);
} }
/**
* @brief Destroys the MPSCQueueIntrusive object.
*
* Dequeues all items and deletes them.
*/
~MPSCQueueIntrusive() ~MPSCQueueIntrusive()
{ {
T* output; T* output;
@@ -105,16 +169,32 @@ namespace Acore::Impl
delete output; delete output;
} }
/**
* @brief Enqueues a new item in the queue.
*
* This function adds a new item at the head of the queue.
*
* @param input Pointer to the item to be enqueued.
*/
void Enqueue(T* input) void Enqueue(T* input)
{ {
// Set the next link to nullptr initially
(input->*IntrusiveLink).store(nullptr, std::memory_order_release); (input->*IntrusiveLink).store(nullptr, std::memory_order_release);
T* prevHead = _head.exchange(input, std::memory_order_acq_rel); T* prevHead = _head.exchange(input, std::memory_order_acq_rel); ///< Exchange with acquire-release semantics
(prevHead->*IntrusiveLink).store(input, std::memory_order_release); (prevHead->*IntrusiveLink).store(input, std::memory_order_release);
} }
/**
* @brief Dequeues an item from the queue.
*
* This function removes the item at the front of the queue and returns it.
*
* @param result Reference to a pointer where the dequeued item will be stored.
* @return True if an item was successfully dequeued, false if the queue was empty.
*/
bool Dequeue(T*& result) bool Dequeue(T*& result)
{ {
T* tail = _tail.load(std::memory_order_relaxed); T* tail = _tail.load(std::memory_order_acquire);
T* next = (tail->*IntrusiveLink).load(std::memory_order_acquire); T* next = (tail->*IntrusiveLink).load(std::memory_order_acquire);
if (tail == _dummyPtr) if (tail == _dummyPtr)
{ {
@@ -149,16 +229,25 @@ namespace Acore::Impl
} }
private: private:
std::aligned_storage_t<sizeof(T), alignof(T)> _dummy; std::aligned_storage_t<sizeof(T), alignof(T)> _dummy; ///< Storage for the dummy object
T* _dummyPtr; T* _dummyPtr; ///< Pointer to the dummy object
std::atomic<T*> _head; std::atomic<T*> _head; ///< Atomic pointer to the head node of the queue
std::atomic<T*> _tail; std::atomic<T*> _tail; ///< Atomic pointer to the tail node of the queue
MPSCQueueIntrusive(MPSCQueueIntrusive const&) = delete; MPSCQueueIntrusive(MPSCQueueIntrusive const&) = delete; ///< Deleted copy constructor
MPSCQueueIntrusive& operator=(MPSCQueueIntrusive const&) = delete; MPSCQueueIntrusive& operator=(MPSCQueueIntrusive const&) = delete; ///< Deleted copy assignment operator
}; };
} }
/**
* @brief Conditional type alias for MPSCQueue.
*
* This alias provides the appropriate type of MPSCQueue based on whether the queue is intrusive
* or non-intrusive.
*
* @tparam T The type of data that is being enqueued in the queue.
* @tparam IntrusiveLink If provided, the queue will be intrusive, otherwise, it will be non-intrusive.
*/
template<typename T, std::atomic<T*> T::* IntrusiveLink = nullptr> template<typename T, std::atomic<T*> T::* IntrusiveLink = nullptr>
using MPSCQueue = std::conditional_t<IntrusiveLink != nullptr, Acore::Impl::MPSCQueueIntrusive<T, IntrusiveLink>, Acore::Impl::MPSCQueueNonIntrusive<T>>; using MPSCQueue = std::conditional_t<IntrusiveLink != nullptr, Acore::Impl::MPSCQueueIntrusive<T, IntrusiveLink>, Acore::Impl::MPSCQueueNonIntrusive<T>>;
@@ -27,14 +27,15 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "SpellMgr.h" #include "SpellMgr.h"
#define AC_SAI_IS_BOOLEAN_VALID(e, value) \ bool SmartAIMgr::IsSAIBoolValid(SmartScriptHolder const& e, SAIBool value)
{ \ {
if (value > 1) \ if (value != 0 && value != 1)
{ \ {
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses param {} of type Boolean with value {}, valid values are 0 or 1, skipped.", \ LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses param {} of type Boolean with value {}, valid values are 0 or 1, skipped.",
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), STRINGIZE(value), value); \ e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), STRINGIZE(value), value);
return false; \ return false;
} \ }
return true;
} }
SmartWaypointMgr* SmartWaypointMgr::instance() SmartWaypointMgr* SmartWaypointMgr::instance()
@@ -513,23 +514,22 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e)
case SMART_TARGET_HOSTILE_LAST_AGGRO: case SMART_TARGET_HOSTILE_LAST_AGGRO:
case SMART_TARGET_HOSTILE_RANDOM: case SMART_TARGET_HOSTILE_RANDOM:
case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP: case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP:
AC_SAI_IS_BOOLEAN_VALID(e, e.target.hostileRandom.playerOnly); return IsSAIBoolValid(e, e.target.hostileRandom.playerOnly);
break;
case SMART_TARGET_FARTHEST: case SMART_TARGET_FARTHEST:
AC_SAI_IS_BOOLEAN_VALID(e, e.target.farthest.playerOnly); return IsSAIBoolValid(e, e.target.farthest.playerOnly) &&
AC_SAI_IS_BOOLEAN_VALID(e, e.target.farthest.isInLos); IsSAIBoolValid(e, e.target.farthest.isInLos);
break; break;
case SMART_TARGET_CLOSEST_CREATURE: case SMART_TARGET_CLOSEST_CREATURE:
AC_SAI_IS_BOOLEAN_VALID(e, e.target.unitClosest.dead); return IsSAIBoolValid(e, e.target.unitClosest.dead);
break; break;
case SMART_TARGET_CLOSEST_ENEMY: case SMART_TARGET_CLOSEST_ENEMY:
AC_SAI_IS_BOOLEAN_VALID(e, e.target.closestAttackable.playerOnly); return IsSAIBoolValid(e, e.target.closestAttackable.playerOnly);
break; break;
case SMART_TARGET_CLOSEST_FRIENDLY: case SMART_TARGET_CLOSEST_FRIENDLY:
AC_SAI_IS_BOOLEAN_VALID(e, e.target.closestFriendly.playerOnly); return IsSAIBoolValid(e, e.target.closestFriendly.playerOnly);
break; break;
case SMART_TARGET_OWNER_OR_SUMMONER: case SMART_TARGET_OWNER_OR_SUMMONER:
AC_SAI_IS_BOOLEAN_VALID(e, e.target.owner.useCharmerOrOwner); return IsSAIBoolValid(e, e.target.owner.useCharmerOrOwner);
break; break;
case SMART_TARGET_STORED: case SMART_TARGET_STORED:
case SMART_TARGET_PLAYER_WITH_AURA: case SMART_TARGET_PLAYER_WITH_AURA:
@@ -1079,9 +1079,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_OOC_LOS: case SMART_EVENT_OOC_LOS:
case SMART_EVENT_IC_LOS: case SMART_EVENT_IC_LOS:
if (!IsMinMaxValid(e, e.event.los.cooldownMin, e.event.los.cooldownMax)) if (!IsMinMaxValid(e, e.event.los.cooldownMin, e.event.los.cooldownMax))
{
return false; return false;
}
if (e.event.los.hostilityMode >= AsUnderlyingType(SmartEvent::LOSHostilityMode::End)) if (e.event.los.hostilityMode >= AsUnderlyingType(SmartEvent::LOSHostilityMode::End))
{ {
@@ -1090,8 +1088,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false; return false;
} }
AC_SAI_IS_BOOLEAN_VALID(e, e.event.los.playerOnly); return IsSAIBoolValid(e, e.event.los.playerOnly);
break;
case SMART_EVENT_RESPAWN: case SMART_EVENT_RESPAWN:
if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && !sMapStore.LookupEntry(e.event.respawn.map)) if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && !sMapStore.LookupEntry(e.event.respawn.map))
{ {
@@ -1134,8 +1131,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
if (e.event.kill.creature && !IsCreatureValid(e, e.event.kill.creature)) if (e.event.kill.creature && !IsCreatureValid(e, e.event.kill.creature))
return false; return false;
AC_SAI_IS_BOOLEAN_VALID(e, e.event.kill.playerOnly); return IsSAIBoolValid(e, e.event.kill.playerOnly);
break;
case SMART_EVENT_VICTIM_CASTING: case SMART_EVENT_VICTIM_CASTING:
if (e.event.targetCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.targetCasting.spellId)) if (e.event.targetCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.targetCasting.spellId))
{ {
@@ -1164,14 +1160,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_ACCEPTED_QUEST: case SMART_EVENT_ACCEPTED_QUEST:
case SMART_EVENT_REWARD_QUEST: case SMART_EVENT_REWARD_QUEST:
if (e.event.quest.quest && !IsQuestValid(e, e.event.quest.quest)) if (e.event.quest.quest && !IsQuestValid(e, e.event.quest.quest))
{
return false; return false;
}
if (!IsMinMaxValid(e, e.event.quest.cooldownMin, e.event.quest.cooldownMax)) if (!IsMinMaxValid(e, e.event.quest.cooldownMin, e.event.quest.cooldownMax))
{
return false; return false;
}
break; break;
case SMART_EVENT_RECEIVE_EMOTE: case SMART_EVENT_RECEIVE_EMOTE:
{ {
@@ -1464,8 +1456,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_SOUND: case SMART_ACTION_SOUND:
if (!IsSoundValid(e, e.action.sound.sound)) if (!IsSoundValid(e, e.action.sound.sound))
return false; return false;
AC_SAI_IS_BOOLEAN_VALID(e, e.action.sound.onlySelf); return IsSAIBoolValid(e, e.action.sound.onlySelf);
break;
case SMART_ACTION_RANDOM_SOUND: case SMART_ACTION_RANDOM_SOUND:
if (e.action.randomSound.sound1 && !IsSoundValid(e, e.action.randomSound.sound1)) if (e.action.randomSound.sound1 && !IsSoundValid(e, e.action.randomSound.sound1))
return false; return false;
@@ -1505,8 +1496,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
if (!IsQuestValid(e, e.action.questOffer.questID)) if (!IsQuestValid(e, e.action.questOffer.questID))
return false; return false;
AC_SAI_IS_BOOLEAN_VALID(e, e.action.questOffer.directAdd); return IsSAIBoolValid(e, e.action.questOffer.directAdd);
break;
case SMART_ACTION_FAIL_QUEST: case SMART_ACTION_FAIL_QUEST:
if (!IsQuestValid(e, e.action.quest.quest)) if (!IsQuestValid(e, e.action.quest.quest))
return false; return false;
@@ -1651,8 +1641,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false; return false;
} }
AC_SAI_IS_BOOLEAN_VALID(e, e.action.summonCreature.attackInvoker); return IsSAIBoolValid(e, e.action.summonCreature.attackInvoker);
break;
case SMART_ACTION_CALL_KILLEDMONSTER: case SMART_ACTION_CALL_KILLEDMONSTER:
if (!IsCreatureValid(e, e.action.killedMonster.creature)) if (!IsCreatureValid(e, e.action.killedMonster.creature))
return false; return false;
@@ -1660,8 +1649,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_UPDATE_TEMPLATE: case SMART_ACTION_UPDATE_TEMPLATE:
if (!IsCreatureValid(e, e.action.updateTemplate.creature)) if (!IsCreatureValid(e, e.action.updateTemplate.creature))
return false; return false;
AC_SAI_IS_BOOLEAN_VALID(e, e.action.updateTemplate.updateLevel); return IsSAIBoolValid(e, e.action.updateTemplate.updateLevel);
break;
case SMART_ACTION_SET_SHEATH: case SMART_ACTION_SET_SHEATH:
if (e.action.setSheath.sheath && e.action.setSheath.sheath >= MAX_SHEATH_STATE) if (e.action.setSheath.sheath && e.action.setSheath.sheath >= MAX_SHEATH_STATE)
{ {
@@ -1707,8 +1695,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_WP_STOP: case SMART_ACTION_WP_STOP:
if (e.action.wpStop.quest && !IsQuestValid(e, e.action.wpStop.quest)) if (e.action.wpStop.quest && !IsQuestValid(e, e.action.wpStop.quest))
return false; return false;
AC_SAI_IS_BOOLEAN_VALID(e, e.action.wpStop.fail); return IsSAIBoolValid(e, e.action.wpStop.fail);
break;
case SMART_ACTION_WP_START: case SMART_ACTION_WP_START:
{ {
if (!sSmartWaypointMgr->GetPath(e.action.wpStart.pathID)) if (!sSmartWaypointMgr->GetPath(e.action.wpStart.pathID))
@@ -1729,9 +1716,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false; return false;
} }
AC_SAI_IS_BOOLEAN_VALID(e, e.action.wpStart.run); return IsSAIBoolValid(e, e.action.wpStart.run) &&
AC_SAI_IS_BOOLEAN_VALID(e, e.action.wpStart.repeat); IsSAIBoolValid(e, e.action.wpStart.repeat);
break;
} }
case SMART_ACTION_CREATE_TIMED_EVENT: case SMART_ACTION_CREATE_TIMED_EVENT:
{ {
@@ -1872,85 +1858,42 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
break; break;
} }
case SMART_ACTION_AUTO_ATTACK: case SMART_ACTION_AUTO_ATTACK:
{ return IsSAIBoolValid(e, e.action.autoAttack.attack);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.autoAttack.attack);
break;
}
case SMART_ACTION_ALLOW_COMBAT_MOVEMENT: case SMART_ACTION_ALLOW_COMBAT_MOVEMENT:
{ return IsSAIBoolValid(e, e.action.combatMove.move);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.combatMove.move);
break;
}
case SMART_ACTION_CALL_FOR_HELP: case SMART_ACTION_CALL_FOR_HELP:
{ return IsSAIBoolValid(e, e.action.callHelp.withEmote);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.callHelp.withEmote);
break;
}
case SMART_ACTION_SET_VISIBILITY: case SMART_ACTION_SET_VISIBILITY:
{ return IsSAIBoolValid(e, e.action.visibility.state);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.visibility.state);
break;
}
case SMART_ACTION_SET_RUN: case SMART_ACTION_SET_RUN:
{ return IsSAIBoolValid(e, e.action.setRun.run);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setRun.run);
break;
}
case SMART_ACTION_SET_CAN_FLY: case SMART_ACTION_SET_CAN_FLY:
{ return IsSAIBoolValid(e, e.action.setFly.fly);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setFly.fly);
break;
}
case SMART_ACTION_SET_SWIM: case SMART_ACTION_SET_SWIM:
{ return IsSAIBoolValid(e, e.action.setSwim.swim);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setSwim.swim);
break;
}
case SMART_ACTION_SET_COUNTER: case SMART_ACTION_SET_COUNTER:
{ return IsSAIBoolValid(e, e.action.setCounter.reset);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setCounter.reset);
break;
}
case SMART_ACTION_INTERRUPT_SPELL: case SMART_ACTION_INTERRUPT_SPELL:
{ return IsSAIBoolValid(e, e.action.interruptSpellCasting.withDelayed) &&
AC_SAI_IS_BOOLEAN_VALID(e, e.action.interruptSpellCasting.withDelayed); IsSAIBoolValid(e, e.action.interruptSpellCasting.withInstant);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.interruptSpellCasting.withInstant);
break;
}
case SMART_ACTION_SET_ROOT: case SMART_ACTION_SET_ROOT:
{ return IsSAIBoolValid(e, e.action.setRoot.root);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setRoot.root);
break;
}
case SMART_ACTION_DISABLE_EVADE: case SMART_ACTION_DISABLE_EVADE:
{ return IsSAIBoolValid(e, e.action.disableEvade.disable);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.disableEvade.disable);
break;
}
case SMART_ACTION_LOAD_EQUIPMENT: case SMART_ACTION_LOAD_EQUIPMENT:
{ return IsSAIBoolValid(e, e.action.loadEquipment.force);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.loadEquipment.force);
break;
}
case SMART_ACTION_TALK: case SMART_ACTION_TALK:
AC_SAI_IS_BOOLEAN_VALID(e, e.action.talk.useTalkTarget);
if (!IsTextValid(e, e.action.talk.textGroupID)) if (!IsTextValid(e, e.action.talk.textGroupID))
return false; return false;
break; return IsSAIBoolValid(e, e.action.talk.useTalkTarget);
case SMART_ACTION_SIMPLE_TALK: case SMART_ACTION_SIMPLE_TALK:
if (!IsTextValid(e, e.action.simpleTalk.textGroupID)) if (!IsTextValid(e, e.action.simpleTalk.textGroupID))
return false; return false;
break; break;
case SMART_ACTION_SET_HEALTH_REGEN: case SMART_ACTION_SET_HEALTH_REGEN:
{ return IsSAIBoolValid(e, e.action.setHealthRegen.regenHealth);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setHealthRegen.regenHealth);
break;
}
case SMART_ACTION_CALL_TIMED_ACTIONLIST: case SMART_ACTION_CALL_TIMED_ACTIONLIST:
{ return IsSAIBoolValid(e, e.action.timedActionList.allowOverride);
AC_SAI_IS_BOOLEAN_VALID(e, e.action.timedActionList.allowOverride);
break;
}
case SMART_ACTION_FLEE_FOR_ASSIST: case SMART_ACTION_FLEE_FOR_ASSIST:
case SMART_ACTION_MOVE_TO_POS: case SMART_ACTION_MOVE_TO_POS:
case SMART_ACTION_EVADE: case SMART_ACTION_EVADE:
@@ -2219,6 +2219,7 @@ private:
return true; return true;
} }
static bool IsSAIBoolValid(SmartScriptHolder const& e, SAIBool value);
static bool IsTextValid(SmartScriptHolder const& e, uint32 id); static bool IsTextValid(SmartScriptHolder const& e, uint32 id);
static bool CheckUnusedEventParams(SmartScriptHolder const& e); static bool CheckUnusedEventParams(SmartScriptHolder const& e);
static bool CheckUnusedActionParams(SmartScriptHolder const& e); static bool CheckUnusedActionParams(SmartScriptHolder const& e);
+1 -1
View File
@@ -32,7 +32,7 @@ enum AccountOpResult
AOR_DB_INTERNAL_ERROR AOR_DB_INTERNAL_ERROR
}; };
#define MAX_ACCOUNT_STR 20 #define MAX_ACCOUNT_STR 17
#define MAX_PASS_STR 16 #define MAX_PASS_STR 16
#define MAX_EMAIL_STR 255 #define MAX_EMAIL_STR 255
@@ -85,7 +85,7 @@ bool ArenaSpectator::HandleSpectatorSpectateCommand(ChatHandler* handler, std::s
if (player->IsInCombat()) if (player->IsInCombat())
errors.push_back("Can't be in combat."); errors.push_back("Can't be in combat.");
if (player->isUsingLfg()) if (player->IsUsingLfg())
errors.push_back("Can't spectate while using LFG system."); errors.push_back("Can't spectate while using LFG system.");
if (player->InBattlegroundQueue()) if (player->InBattlegroundQueue())
+1 -4
View File
@@ -185,10 +185,7 @@ void Channel::JoinChannel(Player* player, std::string const& pass)
return; return;
} }
if (HasFlag(CHANNEL_FLAG_LFG) && if (IsLFG() && sWorld->getBoolConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && !player->IsUsingLfg())
sWorld->getBoolConfig(CONFIG_RESTRICTED_LFG_CHANNEL) &&
AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) &&
player->GetGroup())
{ {
WorldPacket data; WorldPacket data;
MakeNotInLfg(&data); MakeNotInLfg(&data);
+1 -1
View File
@@ -181,7 +181,7 @@ public:
[[nodiscard]] uint32 GetChannelDBId() const { return _channelDBId; } [[nodiscard]] uint32 GetChannelDBId() const { return _channelDBId; }
[[nodiscard]] bool IsConstant() const { return _channelId != 0; } [[nodiscard]] bool IsConstant() const { return _channelId != 0; }
[[nodiscard]] bool IsAnnounce() const { return _announce; } [[nodiscard]] bool IsAnnounce() const { return _announce; }
[[nodiscard]] bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; } [[nodiscard]] bool IsLFG() const { return HasFlag(CHANNEL_FLAG_LFG); }
[[nodiscard]] std::string const& GetPassword() const { return _password; } [[nodiscard]] std::string const& GetPassword() const { return _password; }
void SetPassword(std::string const& npassword) { _password = npassword; } void SetPassword(std::string const& npassword) { _password = npassword; }
[[nodiscard]] uint32 GetNumPlayers() const { return playersStore.size(); } [[nodiscard]] uint32 GetNumPlayers() const { return playersStore.size(); }
@@ -1001,43 +1001,25 @@ void GameObject::Delete()
AddObjectToRemoveList(); AddObjectToRemoveList();
} }
void GameObject::GetFishLoot(Loot* fishloot, Player* loot_owner) void GameObject::GetFishLoot(Loot* fishLoot, Player* lootOwner, bool junk /*= false*/)
{ {
fishloot->clear(); fishLoot->clear();
uint32 zone, subzone; uint32 zone, area;
uint32 defaultzone = 1; uint32 defaultZone = 1;
GetZoneAndAreaId(zone, subzone); GetZoneAndAreaId(zone, area);
// if subzone loot exist use it uint16 lootMode = junk ? LOOT_MODE_JUNK_FISH : LOOT_MODE_DEFAULT;
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true); // Check to fill loot in the order area - zone - defaultZone.
if (fishloot->empty()) //use this becase if zone or subzone has set LOOT_MODE_JUNK_FISH,Even if no normal drop, fishloot->FillLoot return true. it wrong. // This is because area and zone is not set in some places, like Off the coast of Storm Peaks.
uint32 lootZones[] = { area, zone, defaultZone };
for (uint32 fillZone : lootZones)
{ {
//subzone no result,use zone loot fishLoot->FillLoot(fillZone, LootTemplates_Fishing, lootOwner, true, true, lootMode);
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true);
//use zone 1 as default, somewhere fishing got nothing,becase subzone and zone not set, like Off the coast of Storm Peaks.
if (fishloot->empty())
fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true);
}
}
void GameObject::GetFishLootJunk(Loot* fishloot, Player* loot_owner) // If the loot is filled and the loot is eligible, then we break out of the loop.
{ if (!fishLoot->empty() && !fishLoot->isLooted())
fishloot->clear(); break;
uint32 zone, subzone;
uint32 defaultzone = 1;
GetZoneAndAreaId(zone, subzone);
// if subzone loot exist use it
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
if (fishloot->empty()) //use this becase if zone or subzone has normal mask drop, then fishloot->FillLoot return true.
{
//use zone loot
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
if (fishloot->empty())
//use zone 1 as default
fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
} }
} }
@@ -198,8 +198,7 @@ public:
void Refresh(); void Refresh();
void DespawnOrUnsummon(Milliseconds delay = 0ms, Seconds forcedRespawnTime = 0s); void DespawnOrUnsummon(Milliseconds delay = 0ms, Seconds forcedRespawnTime = 0s);
void Delete(); void Delete();
void GetFishLoot(Loot* loot, Player* loot_owner); void GetFishLoot(Loot* fishLoot, Player* lootOwner, bool junk = false);
void GetFishLootJunk(Loot* loot, Player* loot_owner);
[[nodiscard]] GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } [[nodiscard]] GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); }
void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); }
[[nodiscard]] GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); } [[nodiscard]] GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); }
+2 -2
View File
@@ -7896,7 +7896,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
if (loot_type == LOOT_FISHING) if (loot_type == LOOT_FISHING)
go->GetFishLoot(loot, this); go->GetFishLoot(loot, this);
else if (loot_type == LOOT_FISHING_JUNK) else if (loot_type == LOOT_FISHING_JUNK)
go->GetFishLootJunk(loot, this); go->GetFishLoot(loot, this, true);
if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules) if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules)
{ {
@@ -13111,7 +13111,7 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid targetPlayerGUID) const
return ERR_PARTY_RESULT_OK; return ERR_PARTY_RESULT_OK;
} }
bool Player::isUsingLfg() bool Player::IsUsingLfg()
{ {
return sLFGMgr->GetState(GetGUID()) != lfg::LFG_STATE_NONE; return sLFGMgr->GetState(GetGUID()) != lfg::LFG_STATE_NONE;
} }
+2 -1
View File
@@ -2062,6 +2062,7 @@ public:
bool IsInChannel(const Channel* c); bool IsInChannel(const Channel* c);
void CleanupChannels(); void CleanupChannels();
void ClearChannelWatch(); void ClearChannelWatch();
void UpdateLFGChannel();
void UpdateLocalChannels(uint32 newZone); void UpdateLocalChannels(uint32 newZone);
void UpdateDefense(); void UpdateDefense();
@@ -2397,7 +2398,7 @@ public:
void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; } void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; }
void RemoveAtLoginFlag(AtLoginFlags flags, bool persist = false); void RemoveAtLoginFlag(AtLoginFlags flags, bool persist = false);
bool isUsingLfg(); bool IsUsingLfg();
bool inRandomLfgDungeon(); bool inRandomLfgDungeon();
typedef std::set<uint32> DFQuestsDoneList; typedef std::set<uint32> DFQuestsDoneList;
@@ -5687,7 +5687,8 @@ void Player::_LoadActions(PreparedQueryResult result)
ab->uState = ACTIONBUTTON_UNCHANGED; ab->uState = ACTIONBUTTON_UNCHANGED;
else else
{ {
LOG_ERROR("entities.player", "ActionButton loading problem, will be deleted from db...");
LOG_ERROR("entities.player", "ActionButton loading problem, will be deleted from db. player: {}, guid: {}, button: {}, action: {}, type: {}", GetName(), GetGUID().GetCounter(), button, action, type);
// Will deleted in DB at next save (it can create data until save but marked as deleted) // Will deleted in DB at next save (it can create data until save but marked as deleted)
m_actionButtons[button].uState = ACTIONBUTTON_DELETED; m_actionButtons[button].uState = ACTIONBUTTON_DELETED;
@@ -462,6 +462,44 @@ void Player::UpdateNextMailTimeAndUnreads()
} }
} }
void Player::UpdateLFGChannel()
{
if (!sWorld->getBoolConfig(CONFIG_RESTRICTED_LFG_CHANNEL))
return;
ChannelMgr* cMgr = ChannelMgr::forTeam(GetTeamId());
if (!cMgr)
return;
ChatChannelsEntry const* cce = sChatChannelsStore.LookupEntry(26); /*LookingForGroup*/
Channel* cLFG = cMgr->GetJoinChannel(cce->pattern[m_session->GetSessionDbcLocale()], cce->ChannelID);
if (!cLFG)
return;
Channel* cUsed = nullptr;
for (Channel* channel : m_channels)
if (channel && channel->GetChannelId() == cce->ChannelID)
{
cUsed = cLFG;
break;
}
if (IsUsingLfg())
{
if (cUsed == cLFG)
return;
cLFG->JoinChannel(this, "");
}
else
{
if (cLFG != cUsed)
return;
cLFG->LeaveChannel(this, true);
}
}
void Player::UpdateLocalChannels(uint32 newZone) void Player::UpdateLocalChannels(uint32 newZone)
{ {
// pussywizard: mutex needed (tc changed opcode to THREAD UNSAFE) // pussywizard: mutex needed (tc changed opcode to THREAD UNSAFE)
+15 -3
View File
@@ -10401,6 +10401,10 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (meleeAttack) if (meleeAttack)
AddUnitState(UNIT_STATE_MELEE_ATTACKING); AddUnitState(UNIT_STATE_MELEE_ATTACKING);
// Update leash timer when attacking creatures
if (victim->IsCreature())
victim->ToCreature()->UpdateLeashExtensionTime();
// set position before any AI calls/assistance // set position before any AI calls/assistance
//if (IsCreature()) //if (IsCreature())
// ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ()); // ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
@@ -10410,6 +10414,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
SetInCombatWith(victim); SetInCombatWith(victim);
if (victim->IsPlayer()) if (victim->IsPlayer())
victim->SetInCombatWith(this); victim->SetInCombatWith(this);
AddThreat(victim, 0.0f); AddThreat(victim, 0.0f);
creature->SendAIReaction(AI_REACTION_HOSTILE); creature->SendAIReaction(AI_REACTION_HOSTILE);
@@ -13640,9 +13645,6 @@ void Unit::SetInCombatWith(Unit* enemy, uint32 duration)
} }
} }
if (Creature* pCreature = ToCreature())
pCreature->UpdateLeashExtensionTime();
SetInCombatState(false, enemy, duration); SetInCombatState(false, enemy, duration);
} }
@@ -13717,6 +13719,10 @@ void Unit::CombatStart(Unit* victim, bool initialAggro)
SetInCombatWith(victim); SetInCombatWith(victim);
victim->SetInCombatWith(this); victim->SetInCombatWith(this);
// Update leash timer when attacking creatures
if (victim->IsCreature())
victim->ToCreature()->UpdateLeashExtensionTime();
// Xinef: If pet started combat - put owner in combat // Xinef: If pet started combat - put owner in combat
if (!alreadyInCombat && IsInCombat()) if (!alreadyInCombat && IsInCombat())
{ {
@@ -13753,6 +13759,12 @@ void Unit::CombatStartOnCast(Unit* target, bool initialAggro, uint32 duration)
// Xinef: If pet started combat - put owner in combat // Xinef: If pet started combat - put owner in combat
if (Unit* owner = GetOwner()) if (Unit* owner = GetOwner())
owner->SetInCombatWith(target, duration); owner->SetInCombatWith(target, duration);
// Update leash timer when attacking creatures
if (target->IsCreature())
target->ToCreature()->UpdateLeashExtensionTime();
else if (ToCreature()) // Reset leash if it is a spell caster, else it may evade inbetween casts
ToCreature()->UpdateLeashExtensionTime();
} }
Unit* who = target->GetCharmerOrOwnerOrSelf(); Unit* who = target->GetCharmerOrOwnerOrSelf();
+1 -1
View File
@@ -8688,7 +8688,7 @@ bool ObjectMgr::LoadModuleStringsLocale()
std::string const* ObjectMgr::GetModuleString(std::string module, uint32 id, LocaleConstant locale) const std::string const* ObjectMgr::GetModuleString(std::string module, uint32 id, LocaleConstant locale) const
{ {
ModuleString const* ms = GetModuleString(module, id); ModuleString const* ms = GetModuleString(module, id);
if (ms->Content.size()) if (ms && !ms->Content.empty())
{ {
if (ms->Content.size() > size_t(locale) && !ms->Content[locale].empty()) if (ms->Content.size() > size_t(locale) && !ms->Content[locale].empty())
return &ms->Content[locale]; return &ms->Content[locale];
@@ -47,15 +47,11 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
return; return;
if (channelName.size() >= 100 || !DisallowHyperlinksAndMaybeKick(channelName)) if (channelName.size() >= 100 || !DisallowHyperlinksAndMaybeKick(channelName))
{
return; return;
}
if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeamId())) if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeamId()))
{
if (Channel* channel = cMgr->GetJoinChannel(channelName, channelId)) if (Channel* channel = cMgr->GetJoinChannel(channelName, channelId))
channel->JoinChannel(GetPlayer(), password); channel->JoinChannel(GetPlayer(), password);
}
} }
void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket) void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket)
@@ -70,10 +66,8 @@ void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket)
return; return;
if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeamId())) if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeamId()))
{
if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer()))
channel->LeaveChannel(GetPlayer(), true); channel->LeaveChannel(GetPlayer(), true);
}
} }
void WorldSession::HandleChannelList(WorldPacket& recvPacket) void WorldSession::HandleChannelList(WorldPacket& recvPacket)
+2
View File
@@ -71,6 +71,7 @@ void WorldSession::HandleLfgJoinOpcode(WorldPackets::LFG::LFGJoin& packet)
GetPlayerInfo(), packet.Roles, newDungeons.size(), packet.Comment); GetPlayerInfo(), packet.Roles, newDungeons.size(), packet.Comment);
sLFGMgr->JoinLfg(GetPlayer(), uint8(packet.Roles), newDungeons, packet.Comment); sLFGMgr->JoinLfg(GetPlayer(), uint8(packet.Roles), newDungeons, packet.Comment);
GetPlayer()->UpdateLFGChannel();
} }
void WorldSession::HandleLfgLeaveOpcode(WorldPackets::LFG::LFGLeave& /*packet*/) void WorldSession::HandleLfgLeaveOpcode(WorldPackets::LFG::LFGLeave& /*packet*/)
@@ -87,6 +88,7 @@ void WorldSession::HandleLfgLeaveOpcode(WorldPackets::LFG::LFGLeave& /*packet*/)
sLFGMgr->LeaveLfg(sLFGMgr->GetState(guid) == lfg::LFG_STATE_RAIDBROWSER ? guid : gguid); sLFGMgr->LeaveLfg(sLFGMgr->GetState(guid) == lfg::LFG_STATE_RAIDBROWSER ? guid : gguid);
sLFGMgr->LeaveAllLfgQueues(guid, true, group ? group->GetGUID() : ObjectGuid::Empty); sLFGMgr->LeaveAllLfgQueues(guid, true, group ? group->GetGUID() : ObjectGuid::Empty);
} }
GetPlayer()->UpdateLFGChannel();
} }
void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recvData) void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recvData)
@@ -55,6 +55,18 @@ void InstanceScript::SaveToDB()
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
void InstanceScript::OnPlayerEnter(Player* player)
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsTwoFactionInstance())
player->SetFaction((_teamIdInInstance == TEAM_HORDE) ? 1610 /*FACTION_HORDE*/ : 1 /*FACTION_ALLIANCE*/);
}
void InstanceScript::OnPlayerLeave(Player* player)
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsTwoFactionInstance())
player->SetFactionForRace(player->getRace());
}
void InstanceScript::OnCreatureCreate(Creature* creature) void InstanceScript::OnCreatureCreate(Creature* creature)
{ {
AddObject(creature); AddObject(creature);
@@ -584,6 +596,12 @@ void InstanceScript::DoRespawnGameObject(ObjectGuid uiGuid, uint32 uiTimeToDespa
LOG_DEBUG("scripts", "InstanceScript: DoRespawnGameObject failed"); LOG_DEBUG("scripts", "InstanceScript: DoRespawnGameObject failed");
} }
void InstanceScript::DoRespawnGameObject(uint32 type)
{
if (GameObject* go = instance->GetGameObject(GetObjectGuid(type)))
go->Respawn();
}
void InstanceScript::DoRespawnCreature(ObjectGuid guid, bool force) void InstanceScript::DoRespawnCreature(ObjectGuid guid, bool force)
{ {
if (Creature* creature = instance->GetCreature(guid)) if (Creature* creature = instance->GetCreature(guid))
@@ -848,3 +866,21 @@ bool InstanceHasScript(WorldObject const* obj, char const* scriptName)
return false; return false;
} }
bool InstanceScript::IsTwoFactionInstance() const
{
switch (instance->GetId())
{
case 540: // Shattered Halls
case 576: // Nexus
case 631: // Icecrown Citadel
case 632: // Forge of Souls
case 649: // Trial of the Champion
case 650: // Trial of the Crusader
case 658: // Pit of Saron
case 668: // Halls of Reflection
return true;
}
return false;
}
+11 -3
View File
@@ -141,7 +141,7 @@ typedef std::map<ObjectGuid::LowType /*spawnId*/, uint8 /*state*/> ObjectStateMa
class InstanceScript : public ZoneScript class InstanceScript : public ZoneScript
{ {
public: public:
explicit InstanceScript(Map* map) : instance(map), completedEncounters(0) {} explicit InstanceScript(Map* map) : instance(map), completedEncounters(0), _teamIdInInstance(TEAM_NEUTRAL) {}
~InstanceScript() override {} ~InstanceScript() override {}
@@ -182,10 +182,10 @@ public:
GameObject* GetGameObject(uint32 type); GameObject* GetGameObject(uint32 type);
//Called when a player successfully enters the instance. //Called when a player successfully enters the instance.
virtual void OnPlayerEnter(Player* /*player*/) {} virtual void OnPlayerEnter(Player* /*player*/);
//Called when a player successfully leaves the instance. //Called when a player successfully leaves the instance.
virtual void OnPlayerLeave(Player* /*player*/) {} virtual void OnPlayerLeave(Player* /*player*/);
virtual void OnPlayerAreaUpdate(Player* /*player*/, uint32 /*oldArea*/, uint32 /*newArea*/) {} virtual void OnPlayerAreaUpdate(Player* /*player*/, uint32 /*oldArea*/, uint32 /*newArea*/) {}
@@ -203,6 +203,9 @@ public:
//Respawns a GO having negative spawntimesecs in gameobject-table //Respawns a GO having negative spawntimesecs in gameobject-table
void DoRespawnGameObject(ObjectGuid guid, uint32 timeToDespawn = MINUTE); void DoRespawnGameObject(ObjectGuid guid, uint32 timeToDespawn = MINUTE);
// Respawns a GO by instance storage index
void DoRespawnGameObject(uint32 type);
// Respawns a creature. // Respawns a creature.
void DoRespawnCreature(ObjectGuid guid, bool force = false); void DoRespawnCreature(ObjectGuid guid, bool force = false);
@@ -282,6 +285,10 @@ public:
[[nodiscard]] bool AllBossesDone() const; [[nodiscard]] bool AllBossesDone() const;
[[nodiscard]] bool AllBossesDone(std::initializer_list<uint32> bossIds) const; [[nodiscard]] bool AllBossesDone(std::initializer_list<uint32> bossIds) const;
TeamId GetTeamIdInInstance() const { return _teamIdInInstance; }
void SetTeamIdInInstance(TeamId teamId) { _teamIdInInstance = teamId; }
bool IsTwoFactionInstance() const;
TaskScheduler scheduler; TaskScheduler scheduler;
protected: protected:
void SetHeaders(std::string const& dataHeaders); void SetHeaders(std::string const& dataHeaders);
@@ -336,6 +343,7 @@ private:
ObjectGuidMap _objectGuids; ObjectGuidMap _objectGuids;
ObjectStateMap _objectStateMap; ObjectStateMap _objectStateMap;
uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets
TeamId _teamIdInInstance;
std::unordered_set<uint32> _activatedAreaTriggers; std::unordered_set<uint32> _activatedAreaTriggers;
}; };
+10 -1
View File
@@ -103,7 +103,7 @@ bool Map::ExistMap(uint32 mapid, int gx, int gy)
{ {
if (header.mapMagic != MapMagic.asUInt || header.versionMagic != MapVersionMagic) if (header.mapMagic != MapMagic.asUInt || header.versionMagic != MapVersionMagic)
{ {
LOG_ERROR("maps", "Map file '{}' is from an incompatible map version (%.*u v{}), %.*s v{} is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files.", LOG_ERROR("maps", "Map file '{}' is from an incompatible map version ({:.4u} v{}), {:.4s} v{} is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files.",
tmp, 4, header.mapMagic, header.versionMagic, 4, MapMagic.asChar, MapVersionMagic); tmp, 4, header.mapMagic, header.versionMagic, 4, MapMagic.asChar, MapVersionMagic);
} }
@@ -3026,6 +3026,15 @@ bool InstanceMap::AddPlayerToMap(Player* player)
m_resetAfterUnload = false; m_resetAfterUnload = false;
m_unloadWhenEmpty = false; m_unloadWhenEmpty = false;
if (instance_data && instance_data->IsTwoFactionInstance()
&& instance_data->GetTeamIdInInstance() == TEAM_NEUTRAL)
{
instance_data->SetTeamIdInInstance(player->GetTeamId());
if (Group* group = player->GetGroup())
if (Player* leader = ObjectAccessor::FindConnectedPlayer(group->GetLeaderGUID()))
instance_data->SetTeamIdInInstance(leader->GetTeamId());
}
// this will acquire the same mutex so it cannot be in the previous block // this will acquire the same mutex so it cannot be in the previous block
Map::AddPlayerToMap(player); Map::AddPlayerToMap(player);
@@ -84,6 +84,21 @@ void ScriptMgr::OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_DUMMY_EFFECT_ITEM, script->OnDummyEffect(caster, spellID, effIndex, itemTarget)); CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_DUMMY_EFFECT_ITEM, script->OnDummyEffect(caster, spellID, effIndex, itemTarget));
} }
void ScriptMgr::OnSpellCastCancel(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool bySelf)
{
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_CAST_CANCEL, script->OnSpellCastCancel(spell, caster, spellInfo, bySelf));
}
void ScriptMgr::OnSpellCast(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool skipCheck)
{
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_CAST, script->OnSpellCast(spell, caster, spellInfo, skipCheck));
}
void ScriptMgr::OnSpellPrepare(Spell* spell, Unit* caster, SpellInfo const* spellInfo)
{
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_PREPARE, script->OnSpellPrepare(spell, caster, spellInfo));
}
AllSpellScript::AllSpellScript(char const* name, std::vector<uint16> enabledHooks) AllSpellScript::AllSpellScript(char const* name, std::vector<uint16> enabledHooks)
: ScriptObject(name, ALLSPELLHOOK_END) : ScriptObject(name, ALLSPELLHOOK_END)
{ {
@@ -36,6 +36,9 @@ enum AllSpellHook
ALLSPELLHOOK_ON_DUMMY_EFFECT_GAMEOBJECT, ALLSPELLHOOK_ON_DUMMY_EFFECT_GAMEOBJECT,
ALLSPELLHOOK_ON_DUMMY_EFFECT_CREATURE, ALLSPELLHOOK_ON_DUMMY_EFFECT_CREATURE,
ALLSPELLHOOK_ON_DUMMY_EFFECT_ITEM, ALLSPELLHOOK_ON_DUMMY_EFFECT_ITEM,
ALLSPELLHOOK_ON_CAST_CANCEL,
ALLSPELLHOOK_ON_CAST,
ALLSPELLHOOK_ON_PREPARE,
ALLSPELLHOOK_END ALLSPELLHOOK_END
}; };
@@ -100,6 +103,12 @@ public:
* @param itemTarget Contains information about the Item * @param itemTarget Contains information about the Item
*/ */
virtual void OnDummyEffect(WorldObject* /*caster*/, uint32 /*spellID*/, SpellEffIndex /*effIndex*/, Item* /*itemTarget*/) { } virtual void OnDummyEffect(WorldObject* /*caster*/, uint32 /*spellID*/, SpellEffIndex /*effIndex*/, Item* /*itemTarget*/) { }
virtual void OnSpellCastCancel(Spell* /*spell*/, Unit* /*caster*/, SpellInfo const* /*spellInfo*/, bool /*bySelf*/) { }
virtual void OnSpellCast(Spell* /*spell*/, Unit* /*caster*/, SpellInfo const* /*spellInfo*/, bool /*skipCheck*/) { }
virtual void OnSpellPrepare(Spell* /*spell*/, Unit* /*caster*/, SpellInfo const* /*spellInfo*/) { }
}; };
// Compatibility for old scripts // Compatibility for old scripts
+3
View File
@@ -648,6 +648,9 @@ public: /* SpellSC */
void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, GameObject* gameObjTarget); void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, GameObject* gameObjTarget);
void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Creature* creatureTarget); void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Creature* creatureTarget);
void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Item* itemTarget); void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Item* itemTarget);
void OnSpellCastCancel(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool bySelf);
void OnSpellCast(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool skipCheck);
void OnSpellPrepare(Spell* spell, Unit* caster, SpellInfo const* spellInfo);
public: /* GameEventScript */ public: /* GameEventScript */
void OnGameEventStart(uint16 EventID); void OnGameEventStart(uint16 EventID);
+6
View File
@@ -3717,6 +3717,8 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const
TriggerGlobalCooldown(); TriggerGlobalCooldown();
} }
sScriptMgr->OnSpellPrepare(this, m_caster, m_spellInfo);
return SPELL_CAST_OK; return SPELL_CAST_OK;
} }
@@ -3788,6 +3790,8 @@ void Spell::cancel(bool bySelf)
//set state back so finish will be processed //set state back so finish will be processed
m_spellState = oldState; m_spellState = oldState;
sScriptMgr->OnSpellCastCancel(this, m_caster, m_spellInfo, bySelf);
finish(false); finish(false);
} }
@@ -4114,6 +4118,8 @@ void Spell::_cast(bool skipCheck)
if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN)) if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN))
m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
sScriptMgr->OnSpellCast(this, m_caster, m_spellInfo, skipCheck);
SetExecutedCurrently(false); SetExecutedCurrently(false);
} }
-2
View File
@@ -2644,8 +2644,6 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
// some explicitly required dummy effect sets // some explicitly required dummy effect sets
switch (Id) switch (Id)
{ {
case 28441:
return false; // AB Effect 000
default: default:
break; break;
} }
+12 -12
View File
@@ -207,14 +207,14 @@ public:
switch (mode) switch (mode)
{ {
case BAN_ACCOUNT: case BAN_ACCOUNT:
banReturn = sBan->BanAccount(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : ""); banReturn = sBan->BanAccount(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "Console");
break; break;
case BAN_CHARACTER: case BAN_CHARACTER:
banReturn = sBan->BanAccountByPlayerName(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : ""); banReturn = sBan->BanAccountByPlayerName(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "Console");
break; break;
case BAN_IP: case BAN_IP:
default: default:
banReturn = sBan->BanIP(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : ""); banReturn = sBan->BanIP(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "Console");
break; break;
} }
@@ -444,7 +444,7 @@ public:
if (banResult) if (banResult)
{ {
Field* fields2 = banResult->Fetch(); Field* fields2 = banResult->Fetch();
handler->PSendSysMessage("%s", fields2[0].Get<std::string>()); handler->PSendSysMessage("{}", fields2[0].Get<std::string>());
} }
} while (result->NextRow()); } while (result->NextRow());
} }
@@ -480,14 +480,14 @@ public:
if (fields2[0].Get<uint32>() == fields2[1].Get<uint32>()) if (fields2[0].Get<uint32>() == fields2[1].Get<uint32>())
{ {
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}| permanent |{:<15.15}|{:<15.15}|",
accountName, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, accountName, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
fields2[2].Get<std::string>(), fields2[3].Get<std::string>()); fields2[2].Get<std::string>(), fields2[3].Get<std::string>());
} }
else else
{ {
tm tmUnban = Acore::Time::TimeBreakdown(fields2[1].Get<uint32>()); tm tmUnban = Acore::Time::TimeBreakdown(fields2[1].Get<uint32>());
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}|{:02}-{:02}-{:02} {:02}:{:02}|{:<15.15}|{:<15.15}|",
accountName, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, accountName, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min, tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min,
fields2[2].Get<std::string>(), fields2[3].Get<std::string>()); fields2[2].Get<std::string>(), fields2[3].Get<std::string>());
@@ -534,7 +534,7 @@ public:
PreparedQueryResult banResult = CharacterDatabase.Query(stmt2); PreparedQueryResult banResult = CharacterDatabase.Query(stmt2);
if (banResult) if (banResult)
handler->PSendSysMessage("%s", (*banResult)[0].Get<std::string>()); handler->PSendSysMessage("{}", (*banResult)[0].Get<std::string>());
} while (result->NextRow()); } while (result->NextRow());
} }
// Console wide output // Console wide output
@@ -564,14 +564,14 @@ public:
if (banFields[0].Get<uint32>() == banFields[1].Get<uint32>()) if (banFields[0].Get<uint32>() == banFields[1].Get<uint32>())
{ {
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}| permanent |{:<15.15}|{:<15.15}|",
char_name, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, char_name, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
banFields[2].Get<std::string>(), banFields[3].Get<std::string>()); banFields[2].Get<std::string>(), banFields[3].Get<std::string>());
} }
else else
{ {
tm tmUnban = Acore::Time::TimeBreakdown(banFields[1].Get<uint32>()); tm tmUnban = Acore::Time::TimeBreakdown(banFields[1].Get<uint32>());
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}|{:02}-{:02}-{:02} {:02}:{:02}|{:<15.15}|{:<15.15}|",
char_name, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, char_name, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min, tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min,
banFields[2].Get<std::string>(), banFields[3].Get<std::string>()); banFields[2].Get<std::string>(), banFields[3].Get<std::string>());
@@ -621,7 +621,7 @@ public:
do do
{ {
Field* fields = result->Fetch(); Field* fields = result->Fetch();
handler->PSendSysMessage("%s", fields[0].Get<std::string>()); handler->PSendSysMessage("{}", fields[0].Get<std::string>());
} while (result->NextRow()); } while (result->NextRow());
} }
// Console wide output // Console wide output
@@ -637,14 +637,14 @@ public:
tm tmBan = Acore::Time::TimeBreakdown(fields[1].Get<uint32>()); tm tmBan = Acore::Time::TimeBreakdown(fields[1].Get<uint32>());
if (fields[1].Get<uint32>() == fields[2].Get<uint32>()) if (fields[1].Get<uint32>() == fields[2].Get<uint32>())
{ {
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", handler->PSendSysMessage("{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}| permanent |{:<15.15}|{:<15.15}|",
fields[0].Get<std::string>(), tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, fields[0].Get<std::string>(), tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
fields[3].Get<std::string>(), fields[4].Get<std::string>()); fields[3].Get<std::string>(), fields[4].Get<std::string>());
} }
else else
{ {
tm tmUnban = Acore::Time::TimeBreakdown(fields[2].Get<uint32>()); tm tmUnban = Acore::Time::TimeBreakdown(fields[2].Get<uint32>());
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}|{:02}-{:02}-{:02} {:02}:{:02}|{:<15.15}|{:<15.15}|",
fields[0].Get<std::string>(), tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, fields[0].Get<std::string>(), tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min, tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min,
fields[3].Get<std::string>(), fields[4].Get<std::string>()); fields[3].Get<std::string>(), fields[4].Get<std::string>());
+1 -1
View File
@@ -924,7 +924,7 @@ public:
passenger->EnterVehicle(target, *seatId); passenger->EnterVehicle(target, *seatId);
} }
handler->PSendSysMessage("Unit {} entered vehicle %hhd", entry, *seatId); handler->PSendSysMessage("Unit {} entered vehicle {:d}", entry, *seatId);
return true; return true;
} }
+1 -1
View File
@@ -280,7 +280,7 @@ public:
break; break;
} }
if (plr->isUsingLfg()) if (plr->IsUsingLfg())
{ {
error = 4; error = 4;
break; break;
+1 -1
View File
@@ -217,7 +217,7 @@ public:
static bool HandleMmapStatsCommand(ChatHandler* handler) static bool HandleMmapStatsCommand(ChatHandler* handler)
{ {
handler->PSendSysMessage("mmap stats:"); handler->PSendSysMessage("mmap stats:");
//handler->PSendSysMessage(" global mmap pathfinding is %sabled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis"); //handler->PSendSysMessage(" global mmap pathfinding is {}abled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis");
MMAP::MMapMgr* manager = MMAP::MMapFactory::createOrGetMMapMgr(); MMAP::MMapMgr* manager = MMAP::MMapFactory::createOrGetMMapMgr();
handler->PSendSysMessage(" {} maps loaded with {} tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); handler->PSendSysMessage(" {} maps loaded with {} tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount());
+5 -4
View File
@@ -807,8 +807,8 @@ public:
if (!result) if (!result)
{ {
handler->SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM); handler->SendErrorMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetSpawnId());
return true; return false;
} }
handler->SendSysMessage("|cff00ffffDEBUG: wp show info:|r"); handler->SendSysMessage("|cff00ffffDEBUG: wp show info:|r");
@@ -912,15 +912,16 @@ public:
return false; return false;
} }
wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
// Set "wpguid" column to the visual waypoint // Set "wpguid" column to the visual waypoint
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID); WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID);
stmt->SetData(0, int32(wpCreature->GetSpawnId())); stmt->SetData(0, wpCreature->GetSpawnId());
stmt->SetData(1, pathid); stmt->SetData(1, pathid);
stmt->SetData(2, point); stmt->SetData(2, point);
WorldDatabase.Execute(stmt); WorldDatabase.Execute(stmt);
wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map, true, true)) if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map, true, true))
{ {
@@ -31,7 +31,8 @@ enum Says
SAY_GRAVITY_LAPSE = 3, SAY_GRAVITY_LAPSE = 3,
SAY_TIRED = 4, SAY_TIRED = 4,
SAY_RECAST_GRAVITY = 5, SAY_RECAST_GRAVITY = 5,
SAY_DEATH = 6 SAY_DEATH = 6,
SAY_AGGRO_2 = 7
}; };
enum Spells enum Spells
@@ -78,6 +79,8 @@ struct boss_felblood_kaelthas : public BossAI
_gravityLapseCounter = 0; _gravityLapseCounter = 0;
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
me->SetImmuneToAll(false); me->SetImmuneToAll(false);
summons.DespawnAll();
ScheduleHealthCheckEvent(50, [&]{ ScheduleHealthCheckEvent(50, [&]{
me->CastStop(); me->CastStop();
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
@@ -170,6 +173,7 @@ struct boss_felblood_kaelthas : public BossAI
if (!_hasDoneIntro && me->IsWithinDistInMap(who, 40.0f) && who->IsPlayer()) if (!_hasDoneIntro && me->IsWithinDistInMap(who, 40.0f) && who->IsPlayer())
{ {
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
Talk(SAY_AGGRO_2, 20s);
_hasDoneIntro = true; _hasDoneIntro = true;
_OOCScheduler.Schedule(35s, [this](TaskContext){ _OOCScheduler.Schedule(35s, [this](TaskContext){
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
@@ -161,7 +161,7 @@ struct boss_selin_fireheart : public BossAI
if (Creature* crystal = SelectNearestCrystal(false)) if (Creature* crystal = SelectNearestCrystal(false))
{ {
Talk(EMOTE_CRYSTAL); Talk(EMOTE_CRYSTAL);
crystal->ReplaceAllUnitFlags(UNIT_FLAG_NONE); crystal->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
crystal->SetInCombatWithZone(); crystal->SetInCombatWithZone();
crystal->AI()->DoCast(me, SPELL_MANA_RAGE, true); crystal->AI()->DoCast(me, SPELL_MANA_RAGE, true);
DoCast(crystal, SPELL_FEL_CRYSTAL_COSMETIC, true); DoCast(crystal, SPELL_FEL_CRYSTAL_COSMETIC, true);
@@ -51,24 +51,34 @@ enum Misc
struct boss_vexallus : public BossAI struct boss_vexallus : public BossAI
{ {
boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS) { } boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS), _energyCooldown(false) { }
void Reset() override void Reset() override
{ {
_Reset(); _Reset();
_energyCooldown = false;
ScheduleHealthCheckEvent({ 85, 70, 55, 40 }, [&] ScheduleHealthCheckEvent({ 85, 70, 55, 40, 25 }, [&]
{ {
Talk(SAY_ENERGY); if (!_energyCooldown)
Talk(EMOTE_DISCHARGE_ENERGY);
if (IsHeroic())
{ {
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1); Talk(SAY_ENERGY);
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2); Talk(EMOTE_DISCHARGE_ENERGY);
if (IsHeroic())
{
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1);
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2);
}
else
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N);
_energyCooldown = true;
scheduler.Schedule(5s, [this](TaskContext)
{
_energyCooldown = false;
});
} }
else
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N);
}); });
ScheduleHealthCheckEvent(20, [&] ScheduleHealthCheckEvent(20, [&]
@@ -117,6 +127,9 @@ struct boss_vexallus : public BossAI
if (killer) if (killer)
killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true, 0, 0, summon->GetGUID()); killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true, 0, 0, summon->GetGUID());
} }
private:
bool _energyCooldown;
}; };
void AddSC_boss_vexallus() void AddSC_boss_vexallus()
@@ -15,50 +15,63 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "CreatureScript.h"
#include "InstanceMapScript.h" #include "InstanceMapScript.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "SmartAI.h"
#include "scarletmonastery.h" #include "scarletmonastery.h"
#include "ScriptedCreature.h"
enum AshbringerEventMisc enum AshbringerEventMisc
{ {
AURA_OF_ASHBRINGER = 28282, NPC_COMMANDER_MOGRAINE = 3976,
NPC_SCARLET_MYRIDON = 4295, NPC_INQUISITOR_WHITEMANE = 3977,
NPC_SCARLET_DEFENDER = 4298, NPC_SCARLET_SORCERER = 4294,
NPC_SCARLET_CENTURION = 4301, NPC_SCARLET_MYRIDON = 4295,
NPC_SCARLET_SORCERER = 4294, NPC_SCARLET_DEFENDER = 4298,
NPC_SCARLET_WIZARD = 4300, NPC_SCARLET_CHAPLAIN = 4299,
NPC_SCARLET_ABBOT = 4303, NPC_SCARLET_WIZARD = 4300,
NPC_SCARLET_MONK = 4540, NPC_SCARLET_CENTURION = 4301,
NPC_SCARLET_CHAMPION = 4302, NPC_SCARLET_CHAMPION = 4302,
NPC_SCARLET_CHAPLAIN = 4299, NPC_SCARLET_ABBOT = 4303,
NPC_FAIRBANKS = 4542, NPC_SCARLET_MONK = 4540,
NPC_COMMANDER_MOGRAINE = 3976, NPC_FAIRBANKS = 4542,
NPC_INQUISITOR_WHITEMANE = 3977, NPC_HIGHLORD_MOGRAINE = 16062,
DOOR_HIGH_INQUISITOR_ID = 104600,
GO_CHAPEL_DOOR = 104591,
GO_HIGH_INQUISITOR_DOOR = 104600
};
enum AshbringerSpell
{
//Highlord Mograine Spells
//Needs Fix: Increased the visual effect of spells on hit
SPELL_FORGIVENESS = 28697,
//High Inquisitor Fairbanks
//Needs Fix: Increased the visual effect of spells on hit
SPELL_TRANSFORM_GHOST = 28443
}; };
enum DataTypes enum DataTypes
{ {
TYPE_MOGRAINE_AND_WHITE_EVENT = 1, TYPE_MOGRAINE_AND_WHITE_EVENT = 1,
TYPE_ASHBRINGER_EVENT = 2,
DATA_MOGRAINE = 2, DATA_MOGRAINE = 3,
DATA_WHITEMANE = 3, DATA_WHITEMANE = 4,
DATA_DOOR_WHITEMANE = 4, DATA_DOOR_WHITEMANE = 5,
DATA_HORSEMAN_EVENT = 6,
DATA_VORREL = 7,
DATA_ARCANIST_DOAN = 8,
DATA_DOOR_CHAPEL = 9,
DATA_HORSEMAN_EVENT = 5, GAMEOBJECT_PUMPKIN_SHRINE = 10
GAMEOBJECT_PUMPKIN_SHRINE = 6,
DATA_VORREL = 7,
DATA_ARCANIST_DOAN = 8
}; };
float const CATHEDRAL_PULL_RANGE = 80.0f; // Distance from the Cathedral doors to where Mograine is standing
class instance_scarlet_monastery : public InstanceMapScript class instance_scarlet_monastery : public InstanceMapScript
{ {
public: public:
instance_scarlet_monastery() : InstanceMapScript("instance_scarlet_monastery", 189) { } instance_scarlet_monastery() : InstanceMapScript("instance_scarlet_monastery", 189) {}
InstanceScript* GetInstanceScript(InstanceMap* map) const override InstanceScript* GetInstanceScript(InstanceMap* map) const override
{ {
@@ -72,55 +85,18 @@ public:
SetHeaders(DataHeader); SetHeaders(DataHeader);
} }
void OnPlayerEnter(Player* player) override
{
if (player->HasAura(AURA_OF_ASHBRINGER))
{
std::list<Creature*> ScarletList;
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_MYRIDON, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_DEFENDER, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CENTURION, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_SORCERER, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_WIZARD, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_ABBOT, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_MONK, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CHAMPION, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CHAPLAIN, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_COMMANDER_MOGRAINE, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_FAIRBANKS, 4000.0f);
if (!ScarletList.empty())
for (std::list<Creature*>::iterator itr = ScarletList.begin(); itr != ScarletList.end(); itr++) (*itr)->SetFaction(FACTION_FRIENDLY);
}
}
void OnPlayerAreaUpdate(Player* player, uint32 /*oldArea*/, uint32 /*newArea*/) override
{
if (player->HasAura(AURA_OF_ASHBRINGER))
{
std::list<Creature*> ScarletList;
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_MYRIDON, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_DEFENDER, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CENTURION, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_SORCERER, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_WIZARD, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_ABBOT, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_MONK, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CHAMPION, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CHAPLAIN, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_COMMANDER_MOGRAINE, 4000.0f);
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_FAIRBANKS, 4000.0f);
if (!ScarletList.empty())
for (std::list<Creature*>::iterator itr = ScarletList.begin(); itr != ScarletList.end(); itr++) (*itr)->SetFaction(FACTION_FRIENDLY);
}
}
void OnGameObjectCreate(GameObject* go) override void OnGameObjectCreate(GameObject* go) override
{ {
switch (go->GetEntry()) switch (go->GetEntry())
{ {
//case ENTRY_PUMPKIN_SHRINE: PumpkinShrineGUID = go->GetGUID(); break; // case ENTRY_PUMPKIN_SHRINE: PumpkinShrineGUID = go->GetGUID(); break;
case DOOR_HIGH_INQUISITOR_ID: case GO_HIGH_INQUISITOR_DOOR:
DoorHighInquisitorGUID = go->GetGUID(); _doorHighInquisitorGUID = go->GetGUID();
break;
case GO_CHAPEL_DOOR:
_doorChapelGUID = go->GetGUID();
break;
default:
break; break;
} }
} }
@@ -129,11 +105,26 @@ public:
{ {
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_SCARLET_MYRIDON:
case NPC_SCARLET_DEFENDER:
case NPC_SCARLET_CENTURION:
case NPC_SCARLET_SORCERER:
case NPC_SCARLET_WIZARD:
case NPC_SCARLET_ABBOT:
case NPC_SCARLET_MONK:
case NPC_SCARLET_CHAMPION:
case NPC_SCARLET_CHAPLAIN:
case NPC_FAIRBANKS:
_ashbringerNpcGUID.emplace(creature->GetGUID());
break;
case NPC_COMMANDER_MOGRAINE: case NPC_COMMANDER_MOGRAINE:
MograineGUID = creature->GetGUID(); _mograineGUID = creature->GetGUID();
_ashbringerNpcGUID.emplace(creature->GetGUID());
break; break;
case NPC_INQUISITOR_WHITEMANE: case NPC_INQUISITOR_WHITEMANE:
WhitemaneGUID = creature->GetGUID(); _whitemaneGUID = creature->GetGUID();
break;
default:
break; break;
} }
} }
@@ -145,19 +136,90 @@ public:
case TYPE_MOGRAINE_AND_WHITE_EVENT: case TYPE_MOGRAINE_AND_WHITE_EVENT:
if (data == IN_PROGRESS) if (data == IN_PROGRESS)
{ {
DoUseDoorOrButton(DoorHighInquisitorGUID); if (Creature* mograine = instance->GetCreature(_mograineGUID))
encounter = IN_PROGRESS; {
std::list<Creature*> creatureList;
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_MONK, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_ABBOT, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_CHAMPION, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_CENTURION, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_WIZARD, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_CHAPLAIN, CATHEDRAL_PULL_RANGE);
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
{
if (Creature* creature = *itr)
creature->AI()->AttackStart(mograine->GetVictim());
}
}
_encounter = IN_PROGRESS;
} }
if (data == FAIL) if (data == FAIL)
{ {
DoUseDoorOrButton(DoorHighInquisitorGUID); Creature* whitemane = instance->GetCreature(_whitemaneGUID);
encounter = FAIL; if (!whitemane)
return;
Creature* mograine = instance->GetCreature(_mograineGUID);
if (!mograine)
return;
if (whitemane->IsAlive() && mograine->IsAlive())
{
// When Whitemane emerges from the main gate, Whitemane will stand next to Mograine's corpse and will not reset Whitemane
if (whitemane->IsEngaged()||whitemane->IsInEvadeMode())
whitemane->DespawnOnEvade(20s);
mograine->DespawnOnEvade(20s);
_encounter = NOT_STARTED;
return;
}
// Whitemane will not be able to fight Mograine again when he dies
if (!whitemane->IsAlive())
{
mograine->DespawnOrUnsummon();
_encounter = data;
return;
}
if (whitemane->IsAlive() && !mograine->IsAlive())
{
whitemane->DespawnOnEvade(20s);
_encounter = data;
return;
}
_encounter = data;
} }
if (data == SPECIAL) if (data == DONE)
encounter = SPECIAL; _encounter = DONE;
break;
case TYPE_ASHBRINGER_EVENT:
if (data == IN_PROGRESS)
{
// the ashbringer incident did not sniff out any data from whitemane
if (Creature* whitemane = instance->GetCreature(_whitemaneGUID))
if (whitemane->IsAlive() && !whitemane->IsEngaged())
whitemane->DespawnOrUnsummon();
if (GameObject* go = instance->GetGameObject(_doorChapelGUID))
{
go->SetGoState(GO_STATE_ACTIVE);
go->SetLootState(GO_ACTIVATED);
go->SetGameObjectFlag(GO_FLAG_IN_USE);
}
for (auto const& scarletCathedralNpcGuid : _ashbringerNpcGUID)
if (Creature* scarletNpc = instance->GetCreature(scarletCathedralNpcGuid))
if (scarletNpc->IsAlive() && !scarletNpc->IsEngaged())
scarletNpc->SetFaction(FACTION_FRIENDLY);
}
_ashencounter = data;
break; break;
case DATA_HORSEMAN_EVENT: case DATA_HORSEMAN_EVENT:
encounter = data; _encounter = data;
break;
default:
break; break;
} }
} }
@@ -167,528 +229,49 @@ public:
switch (type) switch (type)
{ {
case DATA_MOGRAINE: case DATA_MOGRAINE:
return MograineGUID; return _mograineGUID;
case DATA_WHITEMANE: case DATA_WHITEMANE:
return WhitemaneGUID; return _whitemaneGUID;
case DATA_DOOR_WHITEMANE: case DATA_DOOR_WHITEMANE:
return DoorHighInquisitorGUID; return _doorHighInquisitorGUID;
case DATA_DOOR_CHAPEL:
return _doorChapelGUID;
default:
return ObjectGuid::Empty;
break;
} }
return ObjectGuid::Empty;
} }
uint32 GetData(uint32 type) const override uint32 GetData(uint32 type) const override
{ {
if (type == TYPE_MOGRAINE_AND_WHITE_EVENT) switch (type)
return encounter;
else if (type == DATA_HORSEMAN_EVENT)
return encounter;
return 0;
}
private:
ObjectGuid DoorHighInquisitorGUID;
ObjectGuid MograineGUID;
ObjectGuid WhitemaneGUID;
uint32 encounter;
};
};
enum ScarletMonasteryTrashMisc
{
SAY_WELCOME = 0,
AURA_ASHBRINGER = 28282,
//FACTION_FRIENDLY_TO_ALL = 35,
NPC_HIGHLORD_MOGRAINE = 16440,
SPELL_COSMETIC_CHAIN = 45537,
SPELL_COSMETIC_EXPLODE = 45935,
SPELL_FORGIVENESS = 28697,
};
enum MograineEvents
{
EVENT_SPELL_CRUSADER_STRIKE = 1,
EVENT_SPELL_HAMMER_OF_JUSTICE = 2,
EVENT_PULL_CATHEDRAL = 3
};
enum WhitemaneEvents
{
EVENT_SPELL_HOLY_SMITE = 1,
EVENT_SPELL_POWER_WORLD_SHIELD = 2,
EVENT_SPELL_HEAL = 3
};
enum Spells
{
//Mograine Spells
SPELL_CRUSADER_STRIKE = 14518,
SPELL_HAMMER_OF_JUSTICE = 5589,
SPELL_LAY_ON_HANDS = 9257,
SPELL_RETRIBUTION_AURA = 8990,
SPELL_PERMANENT_FEIGN_DEATH = 29266,
//Whitemanes Spells
SPELL_SCARLET_RESURRECTION = 9232,
SPELL_DEEP_SLEEP = 9256,
SPELL_DOMINATE_MIND = 14515,
SPELL_HOLY_SMITE = 9481,
SPELL_HEAL = 12039,
SPELL_POWER_WORD_SHIELD = 22187
};
enum Says
{
//Mograine says
SAY_MO_AGGRO = 0,
SAY_MO_KILL = 1,
SAY_MO_RESURRECTED = 2,
//Whitemane says
SAY_WH_INTRO = 0,
SAY_WH_KILL = 1,
SAY_WH_RESURRECT = 2,
};
float const CATHEDRAL_PULL_RANGE = 80.0f; // Distance from the Cathedral doors to where Mograine is standing
class npc_mograine : public CreatureScript
{
public:
npc_mograine() : CreatureScript("npc_scarlet_commander_mograine") { }
struct npc_mograineAI : public ScriptedAI
{
npc_mograineAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
uint32 AshbringerEvent(uint32 uiSteps)
{
Creature* mograine = me->FindNearestCreature(NPC_HIGHLORD_MOGRAINE, 200.0f);
switch (uiSteps)
{ {
case 1: case TYPE_MOGRAINE_AND_WHITE_EVENT:
me->GetMotionMaster()->MovePoint(0, 1152.039795f, 1398.405518f, 32.527878f); return _encounter;
return 2 * IN_MILLISECONDS; break;
case 2: case DATA_HORSEMAN_EVENT:
me->SetSheath(SHEATH_STATE_UNARMED); return _encounter;
me->SetStandState(UNIT_STAND_STATE_KNEEL); break;
return 2 * IN_MILLISECONDS; case TYPE_ASHBRINGER_EVENT:
case 3: return _ashencounter;
Talk(3); break;
return 10 * IN_MILLISECONDS;
case 4:
me->SummonCreature(NPC_HIGHLORD_MOGRAINE, 1065.130737f, 1399.350586f, 30.763723f, 6.282961f, TEMPSUMMON_TIMED_DESPAWN, 400000)->SetName("Highlord Mograine");
me->FindNearestCreature(NPC_HIGHLORD_MOGRAINE, 200.0f)->SetFaction(FACTION_FRIENDLY);
return 30 * IN_MILLISECONDS;
case 5:
mograine->StopMovingOnCurrentPos();
mograine->AI()->Talk(0);
mograine->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
return 4 * IN_MILLISECONDS;
case 6:
me->SetStandState(UNIT_STAND_STATE_STAND);
return 2 * IN_MILLISECONDS;
case 7:
Talk(4);
return 4 * IN_MILLISECONDS;
case 8:
mograine->AI()->Talk(1);
return 11 * IN_MILLISECONDS;
case 9:
mograine->HandleEmoteCommand(EMOTE_ONESHOT_BATTLE_ROAR);
return 4 * IN_MILLISECONDS;
case 10:
me->SetSheath(SHEATH_STATE_UNARMED);
me->SetStandState(UNIT_STAND_STATE_KNEEL);
Talk(5);
return 2 * IN_MILLISECONDS;
case 11:
mograine->CastSpell(me, SPELL_FORGIVENESS, false);
return 1 * IN_MILLISECONDS;
case 12:
mograine->CastSpell(me, SPELL_COSMETIC_CHAIN, true);
return 0.5 * IN_MILLISECONDS;
case 13:
mograine->AI()->Talk(2);
mograine->DespawnOrUnsummon(3 * IN_MILLISECONDS);
mograine->Kill(me, me, true);
return 0;
default: default:
if (mograine)
mograine->DespawnOrUnsummon(0);
return 0; return 0;
break;
} }
} }
void PullCathedral() // CallForHelp will ignore any npcs without LOS
{
std::list<Creature*> creatureList;
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_MONK, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_ABBOT, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_CHAMPION, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_CENTURION, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_WIZARD, CATHEDRAL_PULL_RANGE);
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_CHAPLAIN, CATHEDRAL_PULL_RANGE);
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
{
if (Creature* creature = *itr)
creature->AI()->AttackStart(me->GetVictim());
}
}
void Reset() override
{
//Incase wipe during phase that mograine fake death
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
SayAshbringer = false;
timer = 0;
step = 1;
hasDied = false;
heal = false;
fakeDeath = false;
events.Reset();
}
void MoveInLineOfSight(Unit* who) override
{
if (who && who->GetDistance2d(me) < 15.0f)
if (Player* player = who->ToPlayer())
if (player->HasAura(AURA_ASHBRINGER) && !SayAshbringer)
{
me->SetFaction(FACTION_FRIENDLY);
me->SetSheath(SHEATH_STATE_UNARMED);
me->SetStandState(UNIT_STAND_STATE_KNEEL);
me->SetFacingToObject(player);
// me->Yell(12389, LANG_UNIVERSAL, player); // Doesn't exist
SayAshbringer = true;
}
ScriptedAI::MoveInLineOfSight(who);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_MO_AGGRO);
me->CastSpell(me, SPELL_RETRIBUTION_AURA, true);
events.ScheduleEvent(EVENT_PULL_CATHEDRAL, 1s); // Has to be done via event, otherwise mob aggroing Mograine DOES NOT aggro the room
events.ScheduleEvent(EVENT_SPELL_CRUSADER_STRIKE, 1s, 5s);
events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 6s, 11s);
}
void DamageTaken(Unit* /*doneBy*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (damage < me->GetHealth() || hasDied || fakeDeath)
return;
//On first death, fake death and open door, as well as initiate whitemane if exist
if (Unit* Whitemane = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_WHITEMANE)))
{
instance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS);
Whitemane->GetMotionMaster()->MovePoint(1, 1163.113370f, 1398.856812f, 32.527786f);
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->MoveIdle();
me->SetHealth(0);
if (me->IsNonMeleeSpellCast(false))
me->InterruptNonMeleeSpells(false);
me->ClearComboPointHolders();
me->RemoveAllAuras();
me->ClearAllReactives();
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->CastSpell(me, SPELL_PERMANENT_FEIGN_DEATH, true);
hasDied = true;
fakeDeath = true;
damage = 0;
ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_WHITEMANE))->SetInCombatWithZone();
}
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_MO_KILL);
}
void SpellHit(Unit* /*who*/, SpellInfo const* spell) override
{
//When hit with resurrection say text
if (spell->Id == SPELL_SCARLET_RESURRECTION)
{
Talk(SAY_MO_RESURRECTED);
fakeDeath = false;
instance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, SPECIAL);
}
}
void UpdateAI(uint32 diff) override
{
timer = timer - diff;
if (SayAshbringer && step < 15)
{
if (timer <= 0)
{
timer = AshbringerEvent(step);
step++;
}
}
if (!UpdateVictim())
return;
if (hasDied && !heal && instance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL)
{
//On resurrection, stop fake death and heal whitemane and resume fight
if (Unit* Whitemane = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_WHITEMANE)))
{
//Incase wipe during phase that mograine fake death
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->CastSpell(me, SPELL_RETRIBUTION_AURA, true);
me->CastSpell(Whitemane, SPELL_LAY_ON_HANDS, true);
events.ScheduleEvent(EVENT_SPELL_CRUSADER_STRIKE, 1s, 5s);
events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 6s, 11s);
if (me->GetVictim())
me->GetMotionMaster()->MoveChase(me->GetVictim());
heal = true;
}
}
//This if-check to make sure mograine does not attack while fake death
if (fakeDeath)
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SPELL_CRUSADER_STRIKE:
me->CastSpell(me->GetVictim(), SPELL_CRUSADER_STRIKE, true);
events.ScheduleEvent(EVENT_SPELL_CRUSADER_STRIKE, 10s);
break;
case EVENT_SPELL_HAMMER_OF_JUSTICE:
me->CastSpell(me->GetVictim(), SPELL_HAMMER_OF_JUSTICE, true);
events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 60s);
break;
case EVENT_PULL_CATHEDRAL:
PullCathedral();
break;
}
}
DoMeleeAttackIfReady();
}
private:
bool SayAshbringer = false;
int timer = 0;
int step = 1;
bool hasDied;
bool heal;
bool fakeDeath;
EventMap events;
InstanceScript* instance;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetScarletMonasteryAI<npc_mograineAI>(creature);
}
};
class boss_high_inquisitor_whitemane : public CreatureScript
{
public:
boss_high_inquisitor_whitemane() : CreatureScript("boss_high_inquisitor_whitemane") { }
struct boss_high_inquisitor_whitemaneAI : public ScriptedAI
{
boss_high_inquisitor_whitemaneAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
void Reset() override
{
canResurrectCheck = false;
canResurrect = false;
Wait_Timer = 7000;
Heal_Timer = 10000;
}
void JustReachedHome() override
{
instance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, FAIL);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_WH_INTRO);
events.ScheduleEvent(EVENT_SPELL_HOLY_SMITE, 1s, 3s);
events.ScheduleEvent(EVENT_SPELL_POWER_WORLD_SHIELD, 6s);
events.ScheduleEvent(EVENT_SPELL_HEAL, 9s);
}
void DamageTaken(Unit* /*doneBy*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if ((!canResurrectCheck || canResurrect) && damage >= me->GetHealth())
damage = me->GetHealth() - 1;
}
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_WH_KILL);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (canResurrect)
{
//When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out
if (Wait_Timer <= diff)
{
if (ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
{
DoCast(SPELL_SCARLET_RESURRECTION);
Talk(SAY_WH_RESURRECT);
canResurrect = false;
}
}
else Wait_Timer -= diff;
}
//Cast Deep sleep when health is less than 50%
if (!canResurrectCheck && !HealthAbovePct(50))
{
if (me->IsNonMeleeSpellCast(false))
me->InterruptNonMeleeSpells(false);
me->CastSpell(me->GetVictim(), SPELL_DEEP_SLEEP, true);
canResurrectCheck = true;
canResurrect = true;
return;
}
//while in "resurrect-mode", don't do anything
if (canResurrect)
return;
//If we are <75% hp cast healing spells at self or Mograine
if (Heal_Timer <= diff)
{
Creature* target = nullptr;
if (!HealthAbovePct(75))
target = me;
if (Creature* mograine = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
{
// checking canResurrectCheck prevents her healing Mograine while he is "faking death"
if (canResurrectCheck && mograine->IsAlive() && !mograine->HealthAbovePct(75))
target = mograine;
}
if (target)
me->CastSpell(target, SPELL_HEAL, false);
Heal_Timer = 13000;
}
else Heal_Timer -= diff;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SPELL_POWER_WORLD_SHIELD:
me->CastSpell(me, SPELL_POWER_WORD_SHIELD, false);
events.ScheduleEvent(EVENT_SPELL_POWER_WORLD_SHIELD, 15s);
break;
case EVENT_SPELL_HOLY_SMITE:
me->CastSpell(me->GetVictim(), SPELL_HOLY_SMITE, false);
events.ScheduleEvent(EVENT_SPELL_HOLY_SMITE, 6s);
break;
case EVENT_SPELL_HEAL:
me->CastSpell(me, SPELL_HEAL, false);
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* instance;
uint32 Heal_Timer;
uint32 Wait_Timer;
bool canResurrectCheck;
bool canResurrect;
EventMap events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetScarletMonasteryAI<boss_high_inquisitor_whitemaneAI>(creature);
}
};
class npc_fairbanks : public CreatureScript
{
public:
npc_fairbanks() : CreatureScript("npc_fairbanks") { }
struct npc_fairbanksAI : public SmartAI
{
npc_fairbanksAI(Creature* creature) : SmartAI(creature) { }
void Reset() override
{
SayAshbringer = false;
}
void MoveInLineOfSight(Unit* who) override
{
if (who && who->GetDistance2d(me) < 2.0f)
if (Player* player = who->ToPlayer())
if (player->HasAura(AURA_ASHBRINGER) && !SayAshbringer)
{
me->SetFaction(FACTION_FRIENDLY);
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->CastSpell(me, 57767, true);
me->SetDisplayId(16179);
me->SetFacingToObject(player);
SayAshbringer = true;
}
SmartAI::MoveInLineOfSight(who);
}
private: private:
bool SayAshbringer = false; ObjectGuid _doorHighInquisitorGUID;
ObjectGuid _doorChapelGUID;
ObjectGuid _mograineGUID;
ObjectGuid _whitemaneGUID;
uint32 _encounter{};
uint32 _ashencounter{};
GuidSet _ashbringerNpcGUID;
}; };
CreatureAI* GetAI(Creature* creature) const override
{
return GetScarletMonasteryAI<npc_fairbanksAI>(creature);
}
}; };
void AddSC_instance_scarlet_monastery() void AddSC_instance_scarlet_monastery()
{ {
new instance_scarlet_monastery(); new instance_scarlet_monastery();
new npc_fairbanks();
new npc_mograine();
new boss_high_inquisitor_whitemane();
} }
@@ -65,7 +65,7 @@ ObjectData const creatureData[] =
{ NPC_JANALAI, DATA_JANALAI }, { NPC_JANALAI, DATA_JANALAI },
{ NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX }, { NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX },
{ NPC_HARRISON_JONES, DATA_HARRISON_JONES }, { NPC_HARRISON_JONES, DATA_HARRISON_JONES },
{ NPC_AMINISHI_LOOKOUT, DATA_LOOKOUT }, { NPC_AMANISHI_LOOKOUT, DATA_LOOKOUT },
{ 0, 0 } { 0, 0 }
}; };
@@ -127,13 +127,18 @@ public:
{ {
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_AMANISHI_GUARDIAN:
case NPC_AMANISHI_SAVAGE:
if (creature->GetPositionY() >= 1500.0f) // gate
creature->SetImmuneToAll(true);
break;
// Akil'zon gauntlet // Akil'zon gauntlet
case NPC_AMINISHI_TEMPEST: case NPC_AMANISHI_TEMPEST:
if (creature->GetPositionZ() >= 50.0f) // excludes Tempest in Hexlord Malacrass' trash if (creature->GetPositionZ() >= 50.0f) // excludes Tempest in Hexlord Malacrass' trash
AkilzonTrash.insert(creature->GetGUID()); AkilzonTrash.insert(creature->GetGUID());
break; break;
case NPC_AMINISHI_LOOKOUT: case NPC_AMANISHI_LOOKOUT:
case NPC_AMINISHI_PROTECTOR: case NPC_AMANISHI_PROTECTOR:
case NPC_EAGLE_TRASH_AGGRO_TRIGGER: case NPC_EAGLE_TRASH_AGGRO_TRIGGER:
AkilzonTrash.insert(creature->GetGUID()); AkilzonTrash.insert(creature->GetGUID());
break; break;
@@ -226,8 +231,8 @@ public:
case NPC_EAGLE_TRASH_AGGRO_TRIGGER: case NPC_EAGLE_TRASH_AGGRO_TRIGGER:
creature->DisappearAndDie(); creature->DisappearAndDie();
break; break;
case NPC_AMINISHI_LOOKOUT: case NPC_AMANISHI_LOOKOUT:
case NPC_AMINISHI_TEMPEST: case NPC_AMANISHI_TEMPEST:
creature->AI()->DoAction(ACTION_START_AKILZON_GAUNTLET); creature->AI()->DoAction(ACTION_START_AKILZON_GAUNTLET);
break; break;
default: default:
@@ -243,7 +248,7 @@ public:
{ {
if (!creature->IsAlive()) if (!creature->IsAlive())
creature->Respawn(); creature->Respawn();
else if (creature->GetEntry() == NPC_AMINISHI_TEMPEST) else if (creature->GetEntry() == NPC_AMANISHI_TEMPEST)
creature->AI()->DoAction(ACTION_RESET_AKILZON_GAUNTLET); creature->AI()->DoAction(ACTION_RESET_AKILZON_GAUNTLET);
} }
if (Creature* creature = GetCreature(DATA_LOOKOUT)) if (Creature* creature = GetCreature(DATA_LOOKOUT))
@@ -259,7 +264,7 @@ public:
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_AMINISHI_PROTECTOR: case NPC_AMANISHI_PROTECTOR:
case NPC_AMANISHI_WIND_WALKER: case NPC_AMANISHI_WIND_WALKER:
if (_akilzonGauntlet == NOT_STARTED && AkilzonTrash.contains(creature->GetGUID())) if (_akilzonGauntlet == NOT_STARTED && AkilzonTrash.contains(creature->GetGUID()))
creature->DespawnOrUnsummon(30s, 1s); creature->DespawnOrUnsummon(30s, 1s);
@@ -272,8 +277,8 @@ public:
{ {
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_AMINISHI_TEMPEST: case NPC_AMANISHI_TEMPEST:
case NPC_AMINISHI_PROTECTOR: case NPC_AMANISHI_PROTECTOR:
case NPC_AMANISHI_WIND_WALKER: case NPC_AMANISHI_WIND_WALKER:
if (AkilzonTrash.contains(creature->GetGUID())) if (AkilzonTrash.contains(creature->GetGUID()))
ResetAkilzonGauntlet(); ResetAkilzonGauntlet();
@@ -358,8 +358,7 @@ enum DisplayIds
enum EntryIds enum EntryIds
{ {
NPC_HARRISON_JONES_1 = 24375, NPC_HARRISON_JONES_1 = 24375,
NPC_HARRISON_JONES_2 = 24365, NPC_HARRISON_JONES_2 = 24365
NPC_AMANISHI_GUARDIAN = 23597,
}; };
enum Weapons enum Weapons
@@ -417,7 +416,10 @@ struct npc_harrison_jones : public ScriptedAI
std::list<Creature*> creatures; std::list<Creature*> creatures;
me->GetCreatureListWithEntryInGrid(creatures, NPC_AMANISHI_SAVAGE, 100.0f); me->GetCreatureListWithEntryInGrid(creatures, NPC_AMANISHI_SAVAGE, 100.0f);
for (Creature* creature : creatures) for (Creature* creature : creatures)
{
creature->SetImmuneToAll(false);
creature->SetInCombatWithZone(); creature->SetInCombatWithZone();
}
}); });
_instance->StorePersistentData(DATA_TIMED_RUN, 21); _instance->StorePersistentData(DATA_TIMED_RUN, 21);
_instance->DoAction(ACTION_START_TIMED_RUN); _instance->DoAction(ACTION_START_TIMED_RUN);
@@ -60,11 +60,12 @@ enum CreatureIds
NPC_AMANISHI_MEDICINE_MAN = 23581, NPC_AMANISHI_MEDICINE_MAN = 23581,
NPC_AMANISHI_AXE_THROWER = 23542, NPC_AMANISHI_AXE_THROWER = 23542,
NPC_AMANI_HATCHLING = 23598, // 42493 NPC_AMANI_HATCHLING = 23598, // 42493
NPC_AMANISHI_GUARDIAN = 23597,
// Akil'zon gauntlet // Akil'zon gauntlet
NPC_AMANISHI_WIND_WALKER = 24179, NPC_AMANISHI_WIND_WALKER = 24179,
NPC_AMINISHI_LOOKOUT = 24175, NPC_AMANISHI_LOOKOUT = 24175,
NPC_AMINISHI_PROTECTOR = 24180, NPC_AMANISHI_PROTECTOR = 24180,
NPC_AMINISHI_TEMPEST = 24549, NPC_AMANISHI_TEMPEST = 24549,
NPC_EAGLE_TRASH_AGGRO_TRIGGER = 24223 NPC_EAGLE_TRASH_AGGRO_TRIGGER = 24223
}; };
@@ -161,136 +161,37 @@ static float PyrewoodSpawnPoints[3][4] =
{-397.018219f, 1510.208740f, 18.868748f, 4.731330f}, {-397.018219f, 1510.208740f, 18.868748f, 4.731330f},
}; };
#define WAIT_SECS 6000 struct npc_deathstalker_fearleia : public ScriptedAI
class pyrewood_ambush : public CreatureScript
{ {
public: npc_deathstalker_fearleia(Creature* creature) : ScriptedAI(creature), _summons(me)
pyrewood_ambush() : CreatureScript("pyrewood_ambush") { }
bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest) override
{ {
if (quest->GetQuestId() == QUEST_PYREWOOD_AMBUSH && !CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->QuestInProgress) _questInProgress = false;
{
CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->QuestInProgress = true;
CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->Phase = 0;
CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->KillCount = 0;
CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->PlayerGUID = player->GetGUID();
}
return true;
} }
CreatureAI* GetAI(Creature* creature) const override void Reset() override
{ {
return new pyrewood_ambushAI(creature); if (!_questInProgress)
{
_playerGUID.Clear();
_summons.DespawnAll();
}
} }
struct pyrewood_ambushAI : public ScriptedAI void sQuestAccept(Player* player, Quest const* quest) override
{ {
pyrewood_ambushAI(Creature* creature) : ScriptedAI(creature), Summons(me) if (quest->GetQuestId() == QUEST_PYREWOOD_AMBUSH && !_questInProgress)
{ {
QuestInProgress = false; _questInProgress = true;
_playerGUID = player->GetGUID();
} }
uint32 Phase; Talk(NPCSAY_INIT, player);
int8 KillCount;
uint32 WaitTimer;
ObjectGuid PlayerGUID;
SummonList Summons;
bool QuestInProgress; scheduler.Schedule(6s, [this](TaskContext context)
void Reset() override
{ {
WaitTimer = WAIT_SECS; switch (context.GetRepeatCounter())
if (!QuestInProgress) //fix reset values (see UpdateVictim)
{
Phase = 0;
KillCount = 0;
PlayerGUID.Clear();
Summons.DespawnAll();
}
}
void JustEngagedWith(Unit* /*who*/) override { }
void JustSummoned(Creature* summoned) override
{
Summons.Summon(summoned);
++KillCount;
}
void SummonedCreatureDespawn(Creature* summoned) override
{
Summons.Despawn(summoned);
--KillCount;
}
void SummonCreatureWithRandomTarget(uint32 creatureId, int position)
{
if (Creature* summoned = me->SummonCreature(creatureId, PyrewoodSpawnPoints[position][0], PyrewoodSpawnPoints[position][1], PyrewoodSpawnPoints[position][2], PyrewoodSpawnPoints[position][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000))
{
Unit* target = nullptr;
if (PlayerGUID)
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
if (player->IsAlive() && RAND(0, 1))
target = player;
if (!target)
target = me;
summoned->SetFaction(FACTION_STORMWIND);
summoned->AddThreat(target, 32.0f);
summoned->AI()->AttackStart(target);
}
}
void JustDied(Unit* /*killer*/) override
{
if (PlayerGUID)
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
if (player->GetQuestStatus(QUEST_PYREWOOD_AMBUSH) == QUEST_STATUS_INCOMPLETE)
player->FailQuest(QUEST_PYREWOOD_AMBUSH);
}
void UpdateAI(uint32 diff) override
{
//LOG_INFO("scripts", "DEBUG: p({}) k({}) d({}) W({})", Phase, KillCount, diff, WaitTimer);
if (!QuestInProgress)
return;
if (KillCount && Phase < 6)
{
if (!UpdateVictim()) //reset() on target Despawn...
return;
DoMeleeAttackIfReady();
return;
}
switch (Phase)
{ {
case 0: case 0:
if (WaitTimer == WAIT_SECS)
{
if (PlayerGUID)
{
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
{
me->AI()->Talk(NPCSAY_INIT, player);
}
}
}
if (WaitTimer <= diff)
{
WaitTimer -= diff;
return;
}
break;
case 1:
SummonCreatureWithRandomTarget(2060, 1); SummonCreatureWithRandomTarget(2060, 1);
break; break;
case 2: case 2:
@@ -309,21 +210,73 @@ public:
SummonCreatureWithRandomTarget(2068, 2); SummonCreatureWithRandomTarget(2068, 2);
break; break;
case 5: //end case 5: //end
if (PlayerGUID) if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
{ {
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) Talk(NPCSAY_END, player);
{ player->GroupEventHappens(QUEST_PYREWOOD_AMBUSH, me);
me->AI()->Talk(NPCSAY_END, player);
player->GroupEventHappens(QUEST_PYREWOOD_AMBUSH, me);
}
} }
QuestInProgress = false; _questInProgress = false;
Reset(); Reset();
break; break;
} }
++Phase; //prepare next phase
if (context.GetRepeatCounter() < 5)
context.Repeat();
});
}
void JustEngagedWith(Unit* /*who*/) override {}
void JustSummoned(Creature* summoned) override
{
_summons.Summon(summoned);
}
void SummonedCreatureDespawn(Creature* summoned) override
{
_summons.Despawn(summoned);
}
void SummonCreatureWithRandomTarget(uint32 creatureId, int position)
{
if (Creature* summoned = me->SummonCreature(creatureId, PyrewoodSpawnPoints[position][0], PyrewoodSpawnPoints[position][1], PyrewoodSpawnPoints[position][2], PyrewoodSpawnPoints[position][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000))
{
Unit* target = nullptr;
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
if (player->IsAlive() && RAND(0, 1))
target = player;
if (!target)
target = me;
summoned->SetFaction(FACTION_STORMWIND);
summoned->AddThreat(target, 32.0f);
summoned->AI()->AttackStart(target);
} }
}; }
void JustDied(Unit* /*killer*/) override
{
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
if (player->GetQuestStatus(QUEST_PYREWOOD_AMBUSH) == QUEST_STATUS_INCOMPLETE)
player->FailQuest(QUEST_PYREWOOD_AMBUSH);
}
void UpdateAI(uint32 diff) override
{
if (_questInProgress && !_summons.IsAnyCreatureAlive())
scheduler.Update(diff);
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
ObjectGuid _playerGUID;
SummonList _summons;
bool _questInProgress;
}; };
/** /**
@@ -485,6 +438,6 @@ public:
void AddSC_silverpine_forest() void AddSC_silverpine_forest()
{ {
new npc_deathstalker_erland(); new npc_deathstalker_erland();
new pyrewood_ambush(); RegisterCreatureAI(npc_deathstalker_fearleia);
new npc_ravenclaw_apparition(); new npc_ravenclaw_apparition();
} }
@@ -57,7 +57,6 @@ public:
} }
bool CLEANED; bool CLEANED;
TeamId TeamIdInInstance;
uint32 InstanceProgress; uint32 InstanceProgress;
uint32 m_auiEncounter[MAX_ENCOUNTER]; uint32 m_auiEncounter[MAX_ENCOUNTER];
std::string str_data; std::string str_data;
@@ -83,7 +82,6 @@ public:
void Initialize() override void Initialize() override
{ {
TeamIdInInstance = TEAM_NEUTRAL;
InstanceProgress = 0; InstanceProgress = 0;
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
@@ -109,67 +107,49 @@ public:
void OnCreatureCreate(Creature* creature) override void OnCreatureCreate(Creature* creature) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* pPlayer = players.begin()->GetSource())
{
if (Group* group = pPlayer->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = pPlayer->GetTeamId();
}
else
TeamIdInInstance = pPlayer->GetTeamId();
}
}
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
// Grand Champions: // Grand Champions:
case NPC_MOKRA: case NPC_MOKRA:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_JACOB); creature->UpdateEntry(NPC_JACOB);
break; break;
case NPC_ERESSEA: case NPC_ERESSEA:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_AMBROSE); creature->UpdateEntry(NPC_AMBROSE);
break; break;
case NPC_RUNOK: case NPC_RUNOK:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_COLOSOS); creature->UpdateEntry(NPC_COLOSOS);
break; break;
case NPC_ZULTORE: case NPC_ZULTORE:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_JAELYNE); creature->UpdateEntry(NPC_JAELYNE);
break; break;
case NPC_VISCERI: case NPC_VISCERI:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_LANA); creature->UpdateEntry(NPC_LANA);
break; break;
// Grand Champion Minions: // Grand Champion Minions:
case NPC_ORGRIMMAR_MINION: case NPC_ORGRIMMAR_MINION:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_STORMWIND_MINION); creature->UpdateEntry(NPC_STORMWIND_MINION);
break; break;
case NPC_SILVERMOON_MINION: case NPC_SILVERMOON_MINION:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_GNOMEREGAN_MINION); creature->UpdateEntry(NPC_GNOMEREGAN_MINION);
break; break;
case NPC_THUNDER_BLUFF_MINION: case NPC_THUNDER_BLUFF_MINION:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_EXODAR_MINION); creature->UpdateEntry(NPC_EXODAR_MINION);
break; break;
case NPC_SENJIN_MINION: case NPC_SENJIN_MINION:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_DARNASSUS_MINION); creature->UpdateEntry(NPC_DARNASSUS_MINION);
break; break;
case NPC_UNDERCITY_MINION: case NPC_UNDERCITY_MINION:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_IRONFORGE_MINION); creature->UpdateEntry(NPC_IRONFORGE_MINION);
break; break;
@@ -183,7 +163,7 @@ public:
case NPC_JAEREN: case NPC_JAEREN:
case NPC_ARELAS: case NPC_ARELAS:
NPC_AnnouncerGUID = creature->GetGUID(); NPC_AnnouncerGUID = creature->GetGUID();
//if (TeamIdInInstance == TEAM_ALLIANCE) //if (GetTeamIdInInstance() == TEAM_ALLIANCE)
// creature->UpdateEntry(NPC_ARELAS); // creature->UpdateEntry(NPC_ARELAS);
creature->SetReactState(REACT_PASSIVE); creature->SetReactState(REACT_PASSIVE);
break; break;
@@ -283,36 +263,14 @@ public:
void OnPlayerEnter(Player* player) override void OnPlayerEnter(Player* player) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL) InstanceScript::OnPlayerEnter(player);
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
if (DoNeedCleanup(player)) if (DoNeedCleanup(player))
{
InstanceCleanup(); InstanceCleanup();
}
events.RescheduleEvent(EVENT_CHECK_PLAYERS, CLEANUP_CHECK_INTERVAL); events.RescheduleEvent(EVENT_CHECK_PLAYERS, CLEANUP_CHECK_INTERVAL);
} }
void OnPlayerLeave(Player* player) override
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFactionForRace(player->getRace());
}
bool DoNeedCleanup(Player* ignoredPlayer = nullptr) bool DoNeedCleanup(Player* ignoredPlayer = nullptr)
{ {
uint8 aliveCount = 0; uint8 aliveCount = 0;
@@ -497,7 +455,7 @@ public:
case DATA_INSTANCE_PROGRESS: case DATA_INSTANCE_PROGRESS:
return InstanceProgress; return InstanceProgress;
case DATA_TEAMID_IN_INSTANCE: case DATA_TEAMID_IN_INSTANCE:
return TeamIdInInstance; return GetTeamIdInInstance();
} }
return 0; return 0;
@@ -41,7 +41,6 @@ public:
uint32 EncounterStatus; uint32 EncounterStatus;
uint32 InstanceProgress; uint32 InstanceProgress;
uint32 AttemptsLeft; uint32 AttemptsLeft;
TeamId TeamIdInInstance;
uint8 Counter; uint8 Counter;
uint8 northrendBeastsMask; uint8 northrendBeastsMask;
uint32 AchievementTimer; uint32 AchievementTimer;
@@ -168,7 +167,6 @@ public:
EncounterStatus = NOT_STARTED; EncounterStatus = NOT_STARTED;
InstanceProgress = INSTANCE_PROGRESS_INITIAL; InstanceProgress = INSTANCE_PROGRESS_INITIAL;
AttemptsLeft = 50; AttemptsLeft = 50;
TeamIdInInstance = TEAM_NEUTRAL;
Counter = 0; Counter = 0;
northrendBeastsMask = 0; northrendBeastsMask = 0;
AchievementTimer = 0; AchievementTimer = 0;
@@ -475,7 +473,7 @@ public:
case TYPE_FACTION_CHAMPIONS_PLAYER_DIED: case TYPE_FACTION_CHAMPIONS_PLAYER_DIED:
if (urand(0, 2) == 0 ) if (urand(0, 2) == 0 )
{ {
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
{ {
if (Creature* pTemp = instance->GetCreature(NPC_VarianGUID)) if (Creature* pTemp = instance->GetCreature(NPC_VarianGUID))
pTemp->AI()->Talk(SAY_VARIAN_KILL_HORDE_PLAYER_1); pTemp->AI()->Talk(SAY_VARIAN_KILL_HORDE_PLAYER_1);
@@ -971,16 +969,7 @@ public:
} }
case EVENT_SCENE_202: case EVENT_SCENE_202:
{ {
Map::PlayerList const& pl = instance->GetPlayers(); if (GetTeamIdInInstance() == TEAM_ALLIANCE)
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
if (Player* plr = itr->GetSource())
if (!plr->IsGameMaster())
{
TeamIdInInstance = plr->GetTeamId();
break;
}
if (TeamIdInInstance == TEAM_ALLIANCE)
{ {
if (Creature* c = instance->GetCreature(NPC_GarroshGUID)) if (Creature* c = instance->GetCreature(NPC_GarroshGUID))
c->AI()->Talk(SAY_STAGE_2_02h); c->AI()->Talk(SAY_STAGE_2_02h);
@@ -1004,7 +993,7 @@ public:
} }
case EVENT_SCENE_204: case EVENT_SCENE_204:
{ {
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
{ {
if (Creature* c = instance->GetCreature(NPC_GarroshGUID)) if (Creature* c = instance->GetCreature(NPC_GarroshGUID))
c->AI()->Talk(SAY_STAGE_2_04h); c->AI()->Talk(SAY_STAGE_2_04h);
@@ -1022,26 +1011,26 @@ public:
} }
case EVENT_SCENE_205: case EVENT_SCENE_205:
{ {
if (Creature* c = instance->GetCreature(TeamIdInInstance == TEAM_ALLIANCE ? NPC_VarianGUID : NPC_GarroshGUID)) if (Creature* c = instance->GetCreature(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_VarianGUID : NPC_GarroshGUID))
c->AI()->Talk(TeamIdInInstance == TEAM_ALLIANCE ? SAY_STAGE_2_05a : SAY_STAGE_2_05h); c->AI()->Talk(GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_STAGE_2_05a : SAY_STAGE_2_05h);
break; break;
} }
case EVENT_SUMMON_CHAMPIONS: case EVENT_SUMMON_CHAMPIONS:
{ {
std::vector<uint32> vHealerEntries; std::vector<uint32> vHealerEntries;
vHealerEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_DRUID_RESTORATION : NPC_ALLIANCE_DRUID_RESTORATION); vHealerEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_DRUID_RESTORATION : NPC_ALLIANCE_DRUID_RESTORATION);
vHealerEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_PALADIN_HOLY : NPC_ALLIANCE_PALADIN_HOLY); vHealerEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_PALADIN_HOLY : NPC_ALLIANCE_PALADIN_HOLY);
vHealerEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_PRIEST_DISCIPLINE : NPC_ALLIANCE_PRIEST_DISCIPLINE); vHealerEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_PRIEST_DISCIPLINE : NPC_ALLIANCE_PRIEST_DISCIPLINE);
vHealerEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_SHAMAN_RESTORATION : NPC_ALLIANCE_SHAMAN_RESTORATION); vHealerEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_SHAMAN_RESTORATION : NPC_ALLIANCE_SHAMAN_RESTORATION);
std::vector<uint32> vOtherEntries; std::vector<uint32> vOtherEntries;
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_DEATH_KNIGHT : NPC_ALLIANCE_DEATH_KNIGHT); vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_DEATH_KNIGHT : NPC_ALLIANCE_DEATH_KNIGHT);
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_HUNTER : NPC_ALLIANCE_HUNTER); vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_HUNTER : NPC_ALLIANCE_HUNTER);
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_MAGE : NPC_ALLIANCE_MAGE); vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_MAGE : NPC_ALLIANCE_MAGE);
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_ROGUE : NPC_ALLIANCE_ROGUE); vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_ROGUE : NPC_ALLIANCE_ROGUE);
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_WARLOCK : NPC_ALLIANCE_WARLOCK); vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_WARLOCK : NPC_ALLIANCE_WARLOCK);
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_WARRIOR : NPC_ALLIANCE_WARRIOR); vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_WARRIOR : NPC_ALLIANCE_WARRIOR);
uint8 healersSubtracted = 2; uint8 healersSubtracted = 2;
if (instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL || instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC ) if (instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL || instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC )
@@ -1089,11 +1078,11 @@ public:
uint8 pos2 = 10; uint8 pos2 = 10;
for( std::vector<uint32>::iterator itr = vOtherEntries.begin(); itr != vOtherEntries.end(); ++itr ) for( std::vector<uint32>::iterator itr = vOtherEntries.begin(); itr != vOtherEntries.end(); ++itr )
{ {
if (Creature* pTemp = instance->SummonCreature(*itr, FactionChampionLoc[urand(0, 4) + (TeamIdInInstance == TEAM_ALLIANCE ? 0 : 5)])) if (Creature* pTemp = instance->SummonCreature(*itr, FactionChampionLoc[urand(0, 4) + (GetTeamIdInInstance() == TEAM_ALLIANCE ? 0 : 5)]))
{ {
NPC_ChampionGUIDs.push_back(pTemp->GetGUID()); NPC_ChampionGUIDs.push_back(pTemp->GetGUID());
pTemp->SetHomePosition((TeamIdInInstance == TEAM_ALLIANCE ? FactionChampionLoc[pos2].GetPositionX() : (Locs[LOC_CENTER].GetPositionX() * 2 - FactionChampionLoc[pos2].GetPositionX())), FactionChampionLoc[pos2].GetPositionY(), FactionChampionLoc[pos2].GetPositionZ(), 0.0f); pTemp->SetHomePosition((GetTeamIdInInstance() == TEAM_ALLIANCE ? FactionChampionLoc[pos2].GetPositionX() : (Locs[LOC_CENTER].GetPositionX() * 2 - FactionChampionLoc[pos2].GetPositionX())), FactionChampionLoc[pos2].GetPositionY(), FactionChampionLoc[pos2].GetPositionZ(), 0.0f);
pTemp->GetMotionMaster()->MoveJump((TeamIdInInstance == TEAM_ALLIANCE ? FactionChampionLoc[pos2].GetPositionX() : (Locs[LOC_CENTER].GetPositionX() * 2 - FactionChampionLoc[pos2].GetPositionX())), FactionChampionLoc[pos2].GetPositionY(), FactionChampionLoc[pos2].GetPositionZ(), 20.0f, 20.0f); pTemp->GetMotionMaster()->MoveJump((GetTeamIdInInstance() == TEAM_ALLIANCE ? FactionChampionLoc[pos2].GetPositionX() : (Locs[LOC_CENTER].GetPositionX() * 2 - FactionChampionLoc[pos2].GetPositionX())), FactionChampionLoc[pos2].GetPositionY(), FactionChampionLoc[pos2].GetPositionZ(), 20.0f, 20.0f);
} }
++pos2; ++pos2;
} }
@@ -1196,35 +1185,8 @@ public:
} }
case EVENT_SCENE_VALKYR_DEAD: case EVENT_SCENE_VALKYR_DEAD:
{ {
if (TeamIdInInstance == TEAM_NEUTRAL) if (Creature* c = instance->GetCreature(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_VarianGUID : NPC_GarroshGUID))
{ c->AI()->Talk((GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_STAGE_3_03a : SAY_STAGE_3_03h));
Map::PlayerList const& pl = instance->GetPlayers();
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
if (Player* plr = itr->GetSource())
if (!plr->IsGameMaster())
{
if (Group* group = plr->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
{
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
break;
}
else
{
TeamIdInInstance = plr->GetTeamId();
break;
}
}
else
{
TeamIdInInstance = plr->GetTeamId();
break;
}
}
}
if (Creature* c = instance->GetCreature(TeamIdInInstance == TEAM_ALLIANCE ? NPC_VarianGUID : NPC_GarroshGUID))
c->AI()->Talk((TeamIdInInstance == TEAM_ALLIANCE ? SAY_STAGE_3_03a : SAY_STAGE_3_03h));
events.RescheduleEvent(EVENT_SCENE_401, 60000); events.RescheduleEvent(EVENT_SCENE_401, 60000);
break; break;
@@ -1413,21 +1375,7 @@ public:
void OnPlayerEnter(Player* plr) override void OnPlayerEnter(Player* plr) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL) InstanceScript::OnPlayerEnter(plr);
{
if (Group* group = plr->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = plr->GetTeamId();
}
else
TeamIdInInstance = plr->GetTeamId();
}
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
plr->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
if (instance->IsHeroic()) if (instance->IsHeroic())
{ {
@@ -1448,12 +1396,6 @@ public:
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s); events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
} }
void OnPlayerLeave(Player* player) override
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFactionForRace(player->getRace());
}
bool DoNeedCleanup(Player* ignoredPlayer = nullptr) bool DoNeedCleanup(Player* ignoredPlayer = nullptr)
{ {
uint8 aliveCount = 0; uint8 aliveCount = 0;
@@ -96,12 +96,6 @@ public:
} }
} }
void OnPlayerLeave(Player* player) override
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFactionForRace(player->getRace());
}
void OnCreatureCreate(Creature* creature) override void OnCreatureCreate(Creature* creature) override
{ {
if (teamIdInInstance == TEAM_NEUTRAL) if (teamIdInInstance == TEAM_NEUTRAL)
@@ -144,7 +144,6 @@ public:
}; };
uint32 EncounterMask; uint32 EncounterMask;
TeamId TeamIdInInstance;
ObjectGuid NPC_FalricGUID; ObjectGuid NPC_FalricGUID;
ObjectGuid NPC_MarwynGUID; ObjectGuid NPC_MarwynGUID;
ObjectGuid NPC_LichKingIntroGUID; ObjectGuid NPC_LichKingIntroGUID;
@@ -190,7 +189,6 @@ public:
void Initialize() override void Initialize() override
{ {
EncounterMask = 0; EncounterMask = 0;
TeamIdInInstance = TEAM_NEUTRAL;
memset(&TrashActive, 0, sizeof(TrashActive)); memset(&TrashActive, 0, sizeof(TrashActive));
TrashCounter = 0; TrashCounter = 0;
memset(&chosenComposition, 0, sizeof(chosenComposition)); memset(&chosenComposition, 0, sizeof(chosenComposition));
@@ -214,69 +212,15 @@ public:
return (instance->HavePlayers() && WaveNumber) || IsDuringLKFight; // during LK fight npcs are active and will unset this variable return (instance->HavePlayers() && WaveNumber) || IsDuringLKFight; // during LK fight npcs are active and will unset this variable
} }
void OnPlayerEnter(Player* player) override
{
if (TeamIdInInstance == TEAM_NEUTRAL)
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
}
void OnPlayerLeave(Player* player) override
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFactionForRace(player->getRace());
}
void OnCreatureCreate(Creature* creature) override void OnCreatureCreate(Creature* creature) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* p = itr->GetSource())
if (!p->IsGameMaster())
{
if (Group* group = p->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
{
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
break;
}
else
{
TeamIdInInstance = p->GetTeamId();
break;
}
}
else
{
TeamIdInInstance = p->GetTeamId();
break;
}
}
}
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_SYLVANAS_PART1: case NPC_SYLVANAS_PART1:
creature->SetVisible(false); creature->SetVisible(false);
creature->SetSpeed(MOVE_RUN, 1.1); creature->SetSpeed(MOVE_RUN, 1.1);
NPC_LeaderIntroGUID = creature->GetGUID(); NPC_LeaderIntroGUID = creature->GetGUID();
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_JAINA_PART1); creature->UpdateEntry(NPC_JAINA_PART1);
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER); creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
@@ -284,7 +228,7 @@ public:
case NPC_DARK_RANGER_LORALEN: case NPC_DARK_RANGER_LORALEN:
creature->SetVisible(false); creature->SetVisible(false);
NPC_GuardGUID = creature->GetGUID(); NPC_GuardGUID = creature->GetGUID();
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_ARCHMAGE_KORELN); creature->UpdateEntry(NPC_ARCHMAGE_KORELN);
break; break;
case NPC_UTHER: case NPC_UTHER:
@@ -345,7 +289,7 @@ public:
creature->CastSpell(creature, SPELL_SOUL_REAPER, true); creature->CastSpell(creature, SPELL_SOUL_REAPER, true);
} }
else if (!(EncounterMask & (1 << DATA_LICH_KING))) else if (!(EncounterMask & (1 << DATA_LICH_KING)))
creature->AddAura(TeamIdInInstance == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, creature); creature->AddAura(GetTeamIdInInstance() == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, creature);
else else
creature->SetVisible(false); creature->SetVisible(false);
@@ -359,7 +303,7 @@ public:
NPC_LeaderGUID = creature->GetGUID(); NPC_LeaderGUID = creature->GetGUID();
creature->SetWalk(false); creature->SetWalk(false);
creature->SetSheath(SHEATH_STATE_MELEE); creature->SetSheath(SHEATH_STATE_MELEE);
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_JAINA_PART2); creature->UpdateEntry(NPC_JAINA_PART2);
creature->SetWalk(false); creature->SetWalk(false);
creature->SetHealth(creature->GetMaxHealth() / 20); creature->SetHealth(creature->GetMaxHealth() / 20);
@@ -368,9 +312,9 @@ public:
if (!(EncounterMask & (1 << DATA_LK_INTRO))) if (!(EncounterMask & (1 << DATA_LK_INTRO)))
{ {
creature->SetSheath(SHEATH_STATE_MELEE); creature->SetSheath(SHEATH_STATE_MELEE);
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, TeamIdInInstance == TEAM_ALLIANCE ? EMOTE_ONESHOT_ATTACK2HTIGHT : EMOTE_ONESHOT_ATTACK1H); //the fight cannot be in the form of an emote, it is causing bugs. creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, GetTeamIdInInstance() == TEAM_ALLIANCE ? EMOTE_ONESHOT_ATTACK2HTIGHT : EMOTE_ONESHOT_ATTACK1H); //the fight cannot be in the form of an emote, it is causing bugs.
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER); creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
creature->CastSpell(creature, TeamIdInInstance == TEAM_ALLIANCE ? SPELL_JAINA_ICE_BARRIER : SPELL_SYLVANAS_CLOAK_OF_DARKNESS, true); creature->CastSpell(creature, GetTeamIdInInstance() == TEAM_ALLIANCE ? SPELL_JAINA_ICE_BARRIER : SPELL_SYLVANAS_CLOAK_OF_DARKNESS, true);
} }
else if (!(EncounterMask & (1 << DATA_LICH_KING))) else if (!(EncounterMask & (1 << DATA_LICH_KING)))
{ {
@@ -577,7 +521,7 @@ public:
if (!c->IsAlive()) if (!c->IsAlive())
{ {
c->Respawn(); c->Respawn();
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
c->UpdateEntry(NPC_JAINA_PART2); c->UpdateEntry(NPC_JAINA_PART2);
} }
c->GetThreatMgr().ClearAllThreat(); c->GetThreatMgr().ClearAllThreat();
@@ -605,7 +549,7 @@ public:
c->UpdatePosition(c->GetHomePosition(), true); c->UpdatePosition(c->GetHomePosition(), true);
c->StopMovingOnCurrentPos(); c->StopMovingOnCurrentPos();
c->RemoveAllAuras(); c->RemoveAllAuras();
c->AddAura(TeamIdInInstance == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, c); c->AddAura(GetTeamIdInInstance() == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, c);
c->AI()->Reset(); c->AI()->Reset();
c->setActive(false); c->setActive(false);
c->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); c->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
@@ -1126,18 +1070,18 @@ public:
break; break;
case 2: case 2:
{ {
uint32 entry = TeamIdInInstance == TEAM_ALLIANCE ? GO_THE_SKYBREAKER : GO_ORGRIMS_HAMMER; uint32 entry = GetTeamIdInInstance() == TEAM_ALLIANCE ? GO_THE_SKYBREAKER : GO_ORGRIMS_HAMMER;
T1 = sTransportMgr->CreateTransport(entry, 0, instance); T1 = sTransportMgr->CreateTransport(entry, 0, instance);
++outroStep; ++outroStep;
outroTimer = TeamIdInInstance == TEAM_ALLIANCE ? 10000 : 10500; outroTimer = GetTeamIdInInstance() == TEAM_ALLIANCE ? 10000 : 10500;
} }
break; break;
case 3: case 3:
if (T1) if (T1)
T1->EnableMovement(false); T1->EnableMovement(false);
if (Creature* c = instance->GetCreature(NPC_ShipCaptainGUID)) if (Creature* c = instance->GetCreature(NPC_ShipCaptainGUID))
c->AI()->Talk(TeamIdInInstance == TEAM_ALLIANCE ? SAY_FIRE_ALLY : SAY_FIRE_HORDE); c->AI()->Talk(GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_FIRE_ALLY : SAY_FIRE_HORDE);
if (Creature* c = instance->GetCreature(NPC_LeaderGUID)) if (Creature* c = instance->GetCreature(NPC_LeaderGUID))
{ {
c->RemoveAllAuras(); c->RemoveAllAuras();
@@ -1185,10 +1129,10 @@ public:
T1->EnableMovement(false); T1->EnableMovement(false);
if (Creature* leader = instance->GetCreature(NPC_LeaderGUID)) if (Creature* leader = instance->GetCreature(NPC_LeaderGUID))
{ {
uint8 index = TeamIdInInstance == TEAM_ALLIANCE ? 0 : 1; uint8 index = GetTeamIdInInstance() == TEAM_ALLIANCE ? 0 : 1;
for (uint8 i = 0; i < 3; ++i) for (uint8 i = 0; i < 3; ++i)
if (StairsPos[index][i].GetPositionX()) if (StairsPos[index][i].GetPositionX())
if (GameObject* go = leader->SummonGameObject(TeamIdInInstance == TEAM_ALLIANCE ? GO_STAIRS_ALLIANCE : GO_STAIRS_HORDE, StairsPos[index][i].GetPositionX(), StairsPos[index][i].GetPositionY(), StairsPos[index][i].GetPositionZ(), StairsPos[index][i].GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400, false)) if (GameObject* go = leader->SummonGameObject(GetTeamIdInInstance() == TEAM_ALLIANCE ? GO_STAIRS_ALLIANCE : GO_STAIRS_HORDE, StairsPos[index][i].GetPositionX(), StairsPos[index][i].GetPositionY(), StairsPos[index][i].GetPositionZ(), StairsPos[index][i].GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400, false))
go->SetGameObjectFlag(GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE); go->SetGameObjectFlag(GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE);
//Position pos = TeamIdInInstance == TEAM_ALLIANCE ? AllyPortalPos : HordePortalPos; //Position pos = TeamIdInInstance == TEAM_ALLIANCE ? AllyPortalPos : HordePortalPos;
//leader->SummonGameObject(GO_PORTAL_TO_DALARAN, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400); //leader->SummonGameObject(GO_PORTAL_TO_DALARAN, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400);
@@ -1200,7 +1144,7 @@ public:
break; break;
case 8: case 8:
if (Creature* c = instance->GetCreature(NPC_ShipCaptainGUID)) if (Creature* c = instance->GetCreature(NPC_ShipCaptainGUID))
c->AI()->Talk(TeamIdInInstance == TEAM_ALLIANCE ? SAY_ONBOARD_ALLY : SAY_ONBOARD_HORDE); c->AI()->Talk(GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_ONBOARD_ALLY : SAY_ONBOARD_HORDE);
if (Creature* c = instance->GetCreature(NPC_LeaderGUID)) if (Creature* c = instance->GetCreature(NPC_LeaderGUID))
{ {
c->AddUnitMovementFlag(MOVEMENTFLAG_WALKING); c->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
@@ -1212,7 +1156,7 @@ public:
break; break;
case 9: case 9:
if (Creature* c = instance->GetCreature(NPC_LeaderGUID)) if (Creature* c = instance->GetCreature(NPC_LeaderGUID))
c->AI()->Talk(TeamIdInInstance == TEAM_ALLIANCE ? SAY_JAINA_FINAL_1 : SAY_SYLVANA_FINAL); c->AI()->Talk(GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_JAINA_FINAL_1 : SAY_SYLVANA_FINAL);
HandleGameObject(GO_CaveInGUID, true); HandleGameObject(GO_CaveInGUID, true);
++outroStep; ++outroStep;
outroTimer = 11000; outroTimer = 11000;
@@ -1223,7 +1167,7 @@ public:
for (Map::PlayerList::const_iterator itr = instance->GetPlayers().begin(); itr != instance->GetPlayers().end(); ++itr) for (Map::PlayerList::const_iterator itr = instance->GetPlayers().begin(); itr != instance->GetPlayers().end(); ++itr)
if (Player* p = itr->GetSource()) if (Player* p = itr->GetSource())
p->KilledMonsterCredit(NPC_WRATH_OF_THE_LICH_KING_CREDIT); p->KilledMonsterCredit(NPC_WRATH_OF_THE_LICH_KING_CREDIT);
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
if (Creature* c = instance->GetCreature(NPC_LeaderGUID)) if (Creature* c = instance->GetCreature(NPC_LeaderGUID))
{ {
c->AI()->Talk(SAY_JAINA_FINAL_2); c->AI()->Talk(SAY_JAINA_FINAL_2);
@@ -35,7 +35,6 @@ public:
} }
uint32 m_auiEncounter[MAX_ENCOUNTER]; uint32 m_auiEncounter[MAX_ENCOUNTER];
TeamId teamIdInInstance;
uint32 InstanceProgress; uint32 InstanceProgress;
std::string str_data; std::string str_data;
@@ -61,7 +60,6 @@ public:
void Initialize() override void Initialize() override
{ {
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
teamIdInInstance = TEAM_NEUTRAL;
InstanceProgress = INSTANCE_PROGRESS_NONE; InstanceProgress = INSTANCE_PROGRESS_NONE;
bAchievEleven = true; bAchievEleven = true;
@@ -78,62 +76,24 @@ public:
void OnPlayerEnter(Player* player) override void OnPlayerEnter(Player* player) override
{ {
if (teamIdInInstance == TEAM_NEUTRAL) InstanceScript::OnPlayerEnter(player);
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
teamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
teamIdInInstance = player->GetTeamId();
}
else
teamIdInInstance = player->GetTeamId();
}
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFaction((teamIdInInstance == TEAM_HORDE) ? 1610 : 1);
instance->LoadGrid(LeaderIntroPos.GetPositionX(), LeaderIntroPos.GetPositionY()); instance->LoadGrid(LeaderIntroPos.GetPositionX(), LeaderIntroPos.GetPositionY());
if (Creature* c = instance->GetCreature(GetGuidData(DATA_LEADER_FIRST_GUID))) if (Creature* c = instance->GetCreature(GetGuidData(DATA_LEADER_FIRST_GUID)))
c->AI()->SetData(DATA_START_INTRO, 0); c->AI()->SetData(DATA_START_INTRO, 0);
} }
void OnPlayerLeave(Player* player) override
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFactionForRace(player->getRace());
}
uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
{ {
if (teamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* player = players.begin()->GetSource())
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
teamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
teamIdInInstance = player->GetTeamId();
}
else
teamIdInInstance = player->GetTeamId();
}
}
uint32 entry = data->id1; uint32 entry = data->id1;
switch (entry) switch (entry)
{ {
case NPC_RESCUED_ALLIANCE_SLAVE: case NPC_RESCUED_ALLIANCE_SLAVE:
if (teamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
return 0; return 0;
break; break;
case NPC_RESCUED_HORDE_SLAVE: case NPC_RESCUED_HORDE_SLAVE:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
return 0; return 0;
break; break;
} }
@@ -143,28 +103,10 @@ public:
void OnCreatureCreate(Creature* creature) override void OnCreatureCreate(Creature* creature) override
{ {
if (teamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* player = players.begin()->GetSource())
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
teamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
teamIdInInstance = player->GetTeamId();
}
else
teamIdInInstance = player->GetTeamId();
}
}
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_SYLVANAS_PART1: case NPC_SYLVANAS_PART1:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_JAINA_PART1); creature->UpdateEntry(NPC_JAINA_PART1);
NPC_LeaderFirstGUID = creature->GetGUID(); NPC_LeaderFirstGUID = creature->GetGUID();
@@ -183,7 +125,7 @@ public:
} }
break; break;
case NPC_SYLVANAS_PART2: case NPC_SYLVANAS_PART2:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_JAINA_PART2); creature->UpdateEntry(NPC_JAINA_PART2);
NPC_LeaderSecondGUID = creature->GetGUID(); NPC_LeaderSecondGUID = creature->GetGUID();
break; break;
@@ -213,50 +155,50 @@ public:
} }
break; break;
case NPC_LORALEN: case NPC_LORALEN:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_ELANDRA); creature->UpdateEntry(NPC_ELANDRA);
if (!NPC_GuardFirstGUID) if (!NPC_GuardFirstGUID)
NPC_GuardFirstGUID = creature->GetGUID(); NPC_GuardFirstGUID = creature->GetGUID();
break; break;
case NPC_KALIRA: case NPC_KALIRA:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_KORELN); creature->UpdateEntry(NPC_KORELN);
if (!NPC_GuardSecondGUID) if (!NPC_GuardSecondGUID)
NPC_GuardSecondGUID = creature->GetGUID(); NPC_GuardSecondGUID = creature->GetGUID();
break; break;
case NPC_HORDE_SLAVE_1: case NPC_HORDE_SLAVE_1:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_ALLIANCE_SLAVE_1); creature->UpdateEntry(NPC_ALLIANCE_SLAVE_1);
break; break;
case NPC_HORDE_SLAVE_2: case NPC_HORDE_SLAVE_2:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_ALLIANCE_SLAVE_2); creature->UpdateEntry(NPC_ALLIANCE_SLAVE_2);
break; break;
case NPC_HORDE_SLAVE_3: case NPC_HORDE_SLAVE_3:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_ALLIANCE_SLAVE_3); creature->UpdateEntry(NPC_ALLIANCE_SLAVE_3);
break; break;
case NPC_HORDE_SLAVE_4: case NPC_HORDE_SLAVE_4:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_ALLIANCE_SLAVE_4); creature->UpdateEntry(NPC_ALLIANCE_SLAVE_4);
break; break;
case NPC_GORKUN_IRONSKULL_1: case NPC_GORKUN_IRONSKULL_1:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_MARTIN_VICTUS_1); creature->UpdateEntry(NPC_MARTIN_VICTUS_1);
break; break;
case NPC_GARFROST: case NPC_GARFROST:
NPC_GarfrostGUID = creature->GetGUID(); NPC_GarfrostGUID = creature->GetGUID();
break; break;
case NPC_FREED_SLAVE_1_HORDE: case NPC_FREED_SLAVE_1_HORDE:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_FREED_SLAVE_1_ALLIANCE); creature->UpdateEntry(NPC_FREED_SLAVE_1_ALLIANCE);
break; break;
case NPC_FREED_SLAVE_2_HORDE: case NPC_FREED_SLAVE_2_HORDE:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_FREED_SLAVE_2_ALLIANCE); creature->UpdateEntry(NPC_FREED_SLAVE_2_ALLIANCE);
break; break;
case NPC_FREED_SLAVE_3_HORDE: case NPC_FREED_SLAVE_3_HORDE:
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_FREED_SLAVE_3_ALLIANCE); creature->UpdateEntry(NPC_FREED_SLAVE_3_ALLIANCE);
break; break;
case NPC_GORKUN_IRONSKULL_2: case NPC_GORKUN_IRONSKULL_2:
@@ -266,7 +208,7 @@ public:
c->AI()->DoAction(1); // despawn summons c->AI()->DoAction(1); // despawn summons
c->DespawnOrUnsummon(); c->DespawnOrUnsummon();
} }
if (teamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_MARTIN_VICTUS_2); creature->UpdateEntry(NPC_MARTIN_VICTUS_2);
NPC_MartinOrGorkunGUID = creature->GetGUID(); NPC_MartinOrGorkunGUID = creature->GetGUID();
break; break;
@@ -370,7 +312,7 @@ public:
case DATA_INSTANCE_PROGRESS: case DATA_INSTANCE_PROGRESS:
return InstanceProgress; return InstanceProgress;
case DATA_TEAMID_IN_INSTANCE: case DATA_TEAMID_IN_INSTANCE:
return teamIdInInstance; return GetTeamIdInInstance();
case DATA_GARFROST: case DATA_GARFROST:
return m_auiEncounter[0]; return m_auiEncounter[0];
case DATA_ICK: case DATA_ICK:
@@ -218,7 +218,6 @@ public:
LoadBossBoundaries(boundaries); LoadBossBoundaries(boundaries);
LoadObjectData(creatureData, nullptr); LoadObjectData(creatureData, nullptr);
LoadDoorData(doorData); LoadDoorData(doorData);
TeamIdInInstance = TEAM_NEUTRAL;
HeroicAttempts = MaxHeroicAttempts; HeroicAttempts = MaxHeroicAttempts;
IsBonedEligible = true; IsBonedEligible = true;
IsOozeDanceEligible = true; IsOozeDanceEligible = true;
@@ -261,22 +260,7 @@ public:
void OnPlayerEnter(Player* player) override void OnPlayerEnter(Player* player) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL) InstanceScript::OnPlayerEnter(player);
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
// for professor putricide hc // for professor putricide hc
DoRemoveAurasDueToSpellOnPlayers(SPELL_GAS_VARIABLE); DoRemoveAurasDueToSpellOnPlayers(SPELL_GAS_VARIABLE);
DoRemoveAurasDueToSpellOnPlayers(SPELL_OOZE_VARIABLE); DoRemoveAurasDueToSpellOnPlayers(SPELL_OOZE_VARIABLE);
@@ -306,32 +290,8 @@ public:
} }
} }
void OnPlayerLeave(Player* player) override
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFactionForRace(player->getRace());
}
void OnCreatureCreate(Creature* creature) override void OnCreatureCreate(Creature* creature) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* player = players.begin()->GetSource())
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
}
// apply ICC buff to pets/summons // apply ICC buff to pets/summons
if (GetData(DATA_BUFF_AVAILABLE) && creature->GetOwnerGUID().IsPlayer() && creature->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && creature->CanHaveThreatList()) if (GetData(DATA_BUFF_AVAILABLE) && creature->GetOwnerGUID().IsPlayer() && creature->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && creature->CanHaveThreatList())
if (Unit* owner = creature->GetOwner()) if (Unit* owner = creature->GetOwner())
@@ -377,39 +337,39 @@ public:
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_KOR_KRON_GENERAL: case NPC_KOR_KRON_GENERAL:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_ALLIANCE_COMMANDER); creature->UpdateEntry(NPC_ALLIANCE_COMMANDER);
break; break;
case NPC_KOR_KRON_LIEUTENANT: case NPC_KOR_KRON_LIEUTENANT:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_SKYBREAKER_LIEUTENANT); creature->UpdateEntry(NPC_SKYBREAKER_LIEUTENANT);
break; break;
case NPC_TORTUNOK: case NPC_TORTUNOK:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_ALANA_MOONSTRIKE); creature->UpdateEntry(NPC_ALANA_MOONSTRIKE);
break; break;
case NPC_GERARDO_THE_SUAVE: case NPC_GERARDO_THE_SUAVE:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_TALAN_MOONSTRIKE); creature->UpdateEntry(NPC_TALAN_MOONSTRIKE);
break; break;
case NPC_UVLUS_BANEFIRE: case NPC_UVLUS_BANEFIRE:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_MALFUS_GRIMFROST); creature->UpdateEntry(NPC_MALFUS_GRIMFROST);
break; break;
case NPC_IKFIRUS_THE_VILE: case NPC_IKFIRUS_THE_VILE:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_YILI); creature->UpdateEntry(NPC_YILI);
break; break;
case NPC_VOL_GUK: case NPC_VOL_GUK:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_JEDEBIA); creature->UpdateEntry(NPC_JEDEBIA);
break; break;
case NPC_HARAGG_THE_UNSEEN: case NPC_HARAGG_THE_UNSEEN:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_NIBY_THE_ALMIGHTY); creature->UpdateEntry(NPC_NIBY_THE_ALMIGHTY);
break; break;
case NPC_GARROSH_HELLSCREAM: case NPC_GARROSH_HELLSCREAM:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_KING_VARIAN_WRYNN); creature->UpdateEntry(NPC_KING_VARIAN_WRYNN);
// Xinef: summon in case of instance unload // Xinef: summon in case of instance unload
@@ -428,7 +388,7 @@ public:
DeathbringerSaurfangGUID = creature->GetGUID(); DeathbringerSaurfangGUID = creature->GetGUID();
break; break;
case NPC_SE_HIGH_OVERLORD_SAURFANG: case NPC_SE_HIGH_OVERLORD_SAURFANG:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
{ {
creature->UpdateEntry(NPC_SE_MURADIN_BRONZEBEARD, true); creature->UpdateEntry(NPC_SE_MURADIN_BRONZEBEARD, true);
creature->LoadEquipment(); creature->LoadEquipment();
@@ -440,14 +400,14 @@ public:
DeathbringerSaurfangEventGUID = creature->GetGUID(); DeathbringerSaurfangEventGUID = creature->GetGUID();
break; break;
case NPC_HIGH_OVERLORD_SAURFANG_DUMMY: case NPC_HIGH_OVERLORD_SAURFANG_DUMMY:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
{ {
creature->UpdateEntry(NPC_MURADIN_BRONZEBEARD_DUMMY, creature->GetCreatureData()); creature->UpdateEntry(NPC_MURADIN_BRONZEBEARD_DUMMY, creature->GetCreatureData());
creature->LoadEquipment(); creature->LoadEquipment();
} }
break; break;
case NPC_SE_KOR_KRON_REAVER: case NPC_SE_KOR_KRON_REAVER:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_SE_SKYBREAKER_MARINE); creature->UpdateEntry(NPC_SE_SKYBREAKER_MARINE);
break; break;
case NPC_FESTERGUT: case NPC_FESTERGUT:
@@ -579,52 +539,34 @@ public:
uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* player = players.begin()->GetSource())
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
}
uint32 entry = data->id1; uint32 entry = data->id1;
switch (entry) switch (entry)
{ {
case NPC_HORDE_GUNSHIP_CANNON: case NPC_HORDE_GUNSHIP_CANNON:
case NPC_ORGRIMS_HAMMER_CREW: case NPC_ORGRIMS_HAMMER_CREW:
case NPC_SKY_REAVER_KORM_BLACKSCAR: case NPC_SKY_REAVER_KORM_BLACKSCAR:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
return 0; return 0;
break; break;
case NPC_ALLIANCE_GUNSHIP_CANNON: case NPC_ALLIANCE_GUNSHIP_CANNON:
case NPC_SKYBREAKER_DECKHAND: case NPC_SKYBREAKER_DECKHAND:
case NPC_HIGH_CAPTAIN_JUSTIN_BARTLETT: case NPC_HIGH_CAPTAIN_JUSTIN_BARTLETT:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
return 0; return 0;
break; break;
case NPC_ZAFOD_BOOMBOX: case NPC_ZAFOD_BOOMBOX:
if (GameObjectTemplate const* go = sObjectMgr->GetGameObjectTemplate(GO_THE_SKYBREAKER_A)) if (GameObjectTemplate const* go = sObjectMgr->GetGameObjectTemplate(GO_THE_SKYBREAKER_A))
if ((TeamIdInInstance == TEAM_ALLIANCE && data->mapid == go->moTransport.mapID) || if ((GetTeamIdInInstance() == TEAM_ALLIANCE && data->mapid == go->moTransport.mapID) ||
(TeamIdInInstance == TEAM_HORDE && data->mapid != go->moTransport.mapID)) (GetTeamIdInInstance() == TEAM_HORDE && data->mapid != go->moTransport.mapID))
return entry; return entry;
return 0; return 0;
case NPC_IGB_MURADIN_BRONZEBEARD: case NPC_IGB_MURADIN_BRONZEBEARD:
if ((TeamIdInInstance == TEAM_ALLIANCE && data->posX > 10.0f) || if ((GetTeamIdInInstance() == TEAM_ALLIANCE && data->posX > 10.0f) ||
(TeamIdInInstance == TEAM_HORDE && data->posX < 10.0f)) (GetTeamIdInInstance() == TEAM_HORDE && data->posX < 10.0f))
return entry; return entry;
return 0; return 0;
case NPC_SPIRE_FROSTWYRM: case NPC_SPIRE_FROSTWYRM:
if ((TeamIdInInstance == TEAM_ALLIANCE && data->posY < 2200.0f) || (TeamIdInInstance == TEAM_HORDE && data->posY > 2200.0f)) if ((GetTeamIdInInstance() == TEAM_ALLIANCE && data->posY < 2200.0f) || (GetTeamIdInInstance() == TEAM_HORDE && data->posY > 2200.0f))
return 0; return 0;
break; break;
} }
@@ -634,38 +576,20 @@ public:
uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* player = players.begin()->GetSource())
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
}
switch (entry) switch (entry)
{ {
case GO_GUNSHIP_ARMORY_H_10N: case GO_GUNSHIP_ARMORY_H_10N:
case GO_GUNSHIP_ARMORY_H_25N: case GO_GUNSHIP_ARMORY_H_25N:
case GO_GUNSHIP_ARMORY_H_10H: case GO_GUNSHIP_ARMORY_H_10H:
case GO_GUNSHIP_ARMORY_H_25H: case GO_GUNSHIP_ARMORY_H_25H:
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
return 0; return 0;
break; break;
case GO_GUNSHIP_ARMORY_A_10N: case GO_GUNSHIP_ARMORY_A_10N:
case GO_GUNSHIP_ARMORY_A_25N: case GO_GUNSHIP_ARMORY_A_25N:
case GO_GUNSHIP_ARMORY_A_10H: case GO_GUNSHIP_ARMORY_A_10H:
case GO_GUNSHIP_ARMORY_A_25H: case GO_GUNSHIP_ARMORY_A_25H:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
return 0; return 0;
break; break;
} }
@@ -748,24 +672,6 @@ public:
void OnGameObjectCreate(GameObject* go) override void OnGameObjectCreate(GameObject* go) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* player = players.begin()->GetSource())
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
}
switch (go->GetEntry()) switch (go->GetEntry())
{ {
case GO_SPIRIT_ALARM_1: case GO_SPIRIT_ALARM_1:
@@ -1021,7 +927,7 @@ public:
case DATA_COLDFLAME_JETS: case DATA_COLDFLAME_JETS:
return ColdflameJetsState; return ColdflameJetsState;
case DATA_TEAMID_IN_INSTANCE: case DATA_TEAMID_IN_INSTANCE:
return TeamIdInInstance; return GetTeamIdInInstance();
case DATA_BLOOD_QUICKENING_STATE: case DATA_BLOOD_QUICKENING_STATE:
return BloodQuickeningState; return BloodQuickeningState;
case DATA_HEROIC_ATTEMPTS: case DATA_HEROIC_ATTEMPTS:
@@ -1315,7 +1221,7 @@ public:
if (!GunshipGUID && instance->HavePlayers()) if (!GunshipGUID && instance->HavePlayers())
{ {
SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, NOT_STARTED); SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, NOT_STARTED);
uint32 gunshipEntry = TeamIdInInstance == TEAM_HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A; uint32 gunshipEntry = GetTeamIdInInstance() == TEAM_HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A;
if (MotionTransport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance)) if (MotionTransport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance))
{ {
GunshipGUID = gunship->GetGUID(); GunshipGUID = gunship->GetGUID();
@@ -1880,7 +1786,7 @@ public:
} }
break; break;
case EVENT_ENEMY_GUNSHIP_COMBAT: case EVENT_ENEMY_GUNSHIP_COMBAT:
if (Creature* captain = source->FindNearestCreature(TeamIdInInstance == TEAM_HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 200.0f)) if (Creature* captain = source->FindNearestCreature(GetTeamIdInInstance() == TEAM_HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 200.0f))
{ {
captain->AI()->DoAction(ACTION_ENEMY_GUNSHIP_TALK); captain->AI()->DoAction(ACTION_ENEMY_GUNSHIP_TALK);
} }
@@ -1900,7 +1806,7 @@ public:
//After movement is stopped remove the backpack //After movement is stopped remove the backpack
RemoveBackPack(); RemoveBackPack();
} }
if (Creature* captain = source->FindNearestCreature(TeamIdInInstance == TEAM_HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 200.0f)) if (Creature* captain = source->FindNearestCreature(GetTeamIdInInstance() == TEAM_HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 200.0f))
captain->AI()->DoAction(ACTION_EXIT_SHIP); captain->AI()->DoAction(ACTION_EXIT_SHIP);
break; break;
@@ -2066,7 +1972,6 @@ public:
ObjectGuid FrozenBolvarGUID; ObjectGuid FrozenBolvarGUID;
ObjectGuid PillarsChainedGUID; ObjectGuid PillarsChainedGUID;
ObjectGuid PillarsUnchainedGUID; ObjectGuid PillarsUnchainedGUID;
TeamId TeamIdInInstance;
uint32 ColdflameJetsState; uint32 ColdflameJetsState;
std::set<ObjectGuid::LowType> FrostwyrmGUIDs; std::set<ObjectGuid::LowType> FrostwyrmGUIDs;
std::set<ObjectGuid::LowType> SpinestalkerTrash; std::set<ObjectGuid::LowType> SpinestalkerTrash;
@@ -25,6 +25,8 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "naxxramas.h" #include "naxxramas.h"
static constexpr uint8 HorsemanCount = 4;
const float HeiganPos[2] = {2796, -3707}; const float HeiganPos[2] = {2796, -3707};
const float HeiganEruptionSlope[3] = const float HeiganEruptionSlope[3] =
{ {
@@ -94,13 +96,12 @@ public:
PatchwerkRoomTrash.clear(); PatchwerkRoomTrash.clear();
// Controls // Controls
_horsemanKilled = 0;
_speakTimer = 0; _speakTimer = 0;
_horsemanTimer = 0; _horsemanTimer = 0;
_screamTimer = 2 * MINUTE * IN_MILLISECONDS; _screamTimer = 2 * MINUTE * IN_MILLISECONDS;
_hadThaddiusGreet = false; _hadThaddiusGreet = false;
_currentWingTaunt = SAY_FIRST_WING_TAUNT; _currentWingTaunt = SAY_FIRST_WING_TAUNT;
_horsemanLoadDoneState = false; _horsemanLoaded = 0;
// Achievements // Achievements
abominationsKilled = 0; abominationsKilled = 0;
@@ -167,14 +168,13 @@ public:
ObjectGuid _lichkingGUID; ObjectGuid _lichkingGUID;
// Controls // Controls
uint8 _horsemanKilled;
uint32 _speakTimer; uint32 _speakTimer;
uint32 _horsemanTimer; uint32 _horsemanTimer;
uint32 _screamTimer; uint32 _screamTimer;
bool _hadThaddiusGreet; bool _hadThaddiusGreet;
EventMap events; EventMap events;
uint8 _currentWingTaunt; uint8 _currentWingTaunt;
bool _horsemanLoadDoneState; uint8 _horsemanLoaded;
// Achievements // Achievements
uint8 abominationsKilled; uint8 abominationsKilled;
@@ -251,15 +251,19 @@ public:
return; return;
case NPC_LADY_BLAUMEUX: case NPC_LADY_BLAUMEUX:
_blaumeuxGUID = creature->GetGUID(); _blaumeuxGUID = creature->GetGUID();
++_horsemanLoaded;
return; return;
case NPC_SIR_ZELIEK: case NPC_SIR_ZELIEK:
_zeliekGUID = creature->GetGUID(); _zeliekGUID = creature->GetGUID();
++_horsemanLoaded;
return; return;
case NPC_BARON_RIVENDARE: case NPC_BARON_RIVENDARE:
_rivendareGUID = creature->GetGUID(); _rivendareGUID = creature->GetGUID();
++_horsemanLoaded;
return; return;
case NPC_THANE_KORTHAZZ: case NPC_THANE_KORTHAZZ:
_korthazzGUID = creature->GetGUID(); _korthazzGUID = creature->GetGUID();
++_horsemanLoaded;
return; return;
case NPC_SAPPHIRON: case NPC_SAPPHIRON:
_sapphironGUID = creature->GetGUID(); _sapphironGUID = creature->GetGUID();
@@ -272,6 +276,9 @@ public:
return; return;
} }
if (_horsemanLoaded == HorsemanCount)
SetBossState(BOSS_HORSEMAN, GetBossState(BOSS_HORSEMAN));
InstanceScript::OnCreatureCreate(creature); InstanceScript::OnCreatureCreate(creature);
} }
@@ -681,13 +688,25 @@ public:
} }
// Horseman handling // Horseman handling
if (bossId == BOSS_HORSEMAN && !_horsemanLoadDoneState) if (bossId == BOSS_HORSEMAN && _horsemanLoaded == HorsemanCount)
{ {
uint8 horsemanKilled {};
if (Creature* cr = instance->GetCreature(_blaumeuxGUID))
horsemanKilled += !cr->IsAlive();
if (Creature* cr = instance->GetCreature(_rivendareGUID))
horsemanKilled += !cr->IsAlive();
if (Creature* cr = instance->GetCreature(_zeliekGUID))
horsemanKilled += !cr->IsAlive();
if (Creature* cr = instance->GetCreature(_korthazzGUID))
horsemanKilled += !cr->IsAlive();
if (state == DONE) if (state == DONE)
{ {
_horsemanTimer++; _horsemanTimer++;
_horsemanKilled++; if (horsemanKilled < HorsemanCount)
if (_horsemanKilled < 4)
{ {
return false; return false;
} }
@@ -699,10 +718,9 @@ public:
} }
// respawn // respawn
else if (state == NOT_STARTED && _horsemanKilled > 0) else if (state == NOT_STARTED && horsemanKilled > 0)
{ {
Creature* cr; Creature* cr;
_horsemanKilled = 0;
if ((cr = instance->GetCreature(_blaumeuxGUID))) if ((cr = instance->GetCreature(_blaumeuxGUID)))
{ {
if (!cr->IsAlive()) if (!cr->IsAlive())
@@ -49,85 +49,40 @@ public:
SetHeaders(DataHeader); SetHeaders(DataHeader);
SetBossNumber(MAX_ENCOUNTERS); SetBossNumber(MAX_ENCOUNTERS);
LoadDoorData(doorData); LoadDoorData(doorData);
TeamIdInInstance = TEAM_NEUTRAL;
} }
void OnCreatureCreate(Creature* creature) override void OnCreatureCreate(Creature* creature) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* pPlayer = players.begin()->GetSource())
{
if (Group* group = pPlayer->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = pPlayer->GetTeamId();
}
else
TeamIdInInstance = pPlayer->GetTeamId();
}
}
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_ALLIANCE_RANGER: case NPC_ALLIANCE_RANGER:
creature->SetFaction(FACTION_MONSTER_2); creature->SetFaction(FACTION_MONSTER_2);
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_HORDE_RANGER); creature->UpdateEntry(NPC_HORDE_RANGER);
break; break;
case NPC_ALLIANCE_BERSERKER: case NPC_ALLIANCE_BERSERKER:
creature->SetFaction(FACTION_MONSTER_2); creature->SetFaction(FACTION_MONSTER_2);
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_HORDE_BERSERKER); creature->UpdateEntry(NPC_HORDE_BERSERKER);
break; break;
case NPC_ALLIANCE_COMMANDER: case NPC_ALLIANCE_COMMANDER:
creature->SetFaction(FACTION_MONSTER_2); creature->SetFaction(FACTION_MONSTER_2);
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_HORDE_COMMANDER); creature->UpdateEntry(NPC_HORDE_COMMANDER);
break; break;
case NPC_ALLIANCE_CLERIC: case NPC_ALLIANCE_CLERIC:
creature->SetFaction(FACTION_MONSTER_2); creature->SetFaction(FACTION_MONSTER_2);
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_HORDE_CLERIC); creature->UpdateEntry(NPC_HORDE_CLERIC);
break; break;
case NPC_COMMANDER_STOUTBEARD: case NPC_COMMANDER_STOUTBEARD:
creature->SetFaction(FACTION_MONSTER_2); creature->SetFaction(FACTION_MONSTER_2);
if (TeamIdInInstance == TEAM_ALLIANCE) if (GetTeamIdInInstance() == TEAM_ALLIANCE)
creature->UpdateEntry(NPC_COMMANDER_KOLURG); creature->UpdateEntry(NPC_COMMANDER_KOLURG);
break; break;
} }
} }
void OnPlayerEnter(Player* player) override
{
if (TeamIdInInstance == TEAM_NEUTRAL)
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
}
void OnPlayerLeave(Player* player) override
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFactionForRace(player->getRace());
}
void OnGameObjectCreate(GameObject* gameObject) override void OnGameObjectCreate(GameObject* gameObject) override
{ {
switch (gameObject->GetEntry()) switch (gameObject->GetEntry())
@@ -194,8 +149,6 @@ public:
(*i)->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE); (*i)->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
return true; return true;
} }
protected:
TeamId TeamIdInInstance;
}; };
}; };
@@ -33,12 +33,8 @@ enum bloodFurnace
DATA_KELIDAN = 2, DATA_KELIDAN = 2,
MAX_ENCOUNTER = 3, MAX_ENCOUNTER = 3,
DATA_DOOR1 = 10,
DATA_DOOR2 = 11,
DATA_DOOR3 = 12,
DATA_BROGGOK_REAR_DOOR = 13, DATA_BROGGOK_REAR_DOOR = 13,
DATA_BROGGOK_LEVER = 14, DATA_BROGGOK_LEVER = 14,
DATA_DOOR6 = 15,
DATA_PRISON_CELL1 = 20, DATA_PRISON_CELL1 = 20,
DATA_PRISON_CELL2 = 21, DATA_PRISON_CELL2 = 21,
@@ -62,7 +58,11 @@ enum BloodFurnaceGO
{ {
GO_BROGGOK_DOOR_FRONT = 181822, GO_BROGGOK_DOOR_FRONT = 181822,
GO_BROGGOK_DOOR_REAR = 181819, GO_BROGGOK_DOOR_REAR = 181819,
GO_BROGGOK_LEVER = 181982 GO_BROGGOK_LEVER = 181982,
GO_KELIDAN_DOOR_EXIT1 = 181823,
GO_KELIDAN_DOOR_EXIT2 = 181766,
GO_MAKER_DOOR_FRONT = 181811,
GO_MAKER_DOOR_REAR = 181812
}; };
template <class AI, class T> template <class AI, class T>
@@ -101,15 +101,10 @@ public:
bool OnGossipHello(Player* /*player*/, GameObject* go) override bool OnGossipHello(Player* /*player*/, GameObject* go) override
{ {
if (InstanceScript* instance = go->GetInstanceScript()) if (InstanceScript* instance = go->GetInstanceScript())
{
if (instance->GetBossState(DATA_BROGGOK) == NOT_STARTED) if (instance->GetBossState(DATA_BROGGOK) == NOT_STARTED)
{
if (Creature* broggok = instance->GetCreature(DATA_BROGGOK)) if (Creature* broggok = instance->GetCreature(DATA_BROGGOK))
{
broggok->AI()->DoAction(ACTION_PREPARE_BROGGOK); broggok->AI()->DoAction(ACTION_PREPARE_BROGGOK);
}
}
}
go->UseDoorOrButton(); go->UseDoorOrButton();
return false; return false;
} }
@@ -67,10 +67,6 @@ struct boss_kelidan_the_breaker : public BossAI
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
DoCastSelf(SPELL_EVOCATION); DoCastSelf(SPELL_EVOCATION);
if (instance)
{
instance->SetData(DATA_KELIDAN, NOT_STARTED);
}
} }
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
@@ -78,10 +74,7 @@ struct boss_kelidan_the_breaker : public BossAI
Talk(SAY_WAKE); Talk(SAY_WAKE);
_JustEngagedWith(); _JustEngagedWith();
me->InterruptNonMeleeSpells(false); me->InterruptNonMeleeSpells(false);
if (instance)
{
instance->SetData(DATA_KELIDAN, IN_PROGRESS);
}
scheduler.Schedule(1s, [this](TaskContext context) scheduler.Schedule(1s, [this](TaskContext context)
{ {
DoCastAOE(SPELL_SHADOW_BOLT_VOLLEY); DoCastAOE(SPELL_SHADOW_BOLT_VOLLEY);
@@ -97,9 +90,7 @@ struct boss_kelidan_the_breaker : public BossAI
me->AddAura(SPELL_BURNING_NOVA, me); me->AddAura(SPELL_BURNING_NOVA, me);
ApplyImmunities(true); ApplyImmunities(true);
if (IsHeroic()) if (IsHeroic())
{
DoCastAOE(SPELL_VORTEX); DoCastAOE(SPELL_VORTEX);
}
scheduler.DelayGroup(0, 6s); scheduler.DelayGroup(0, 6s);
scheduler.Schedule(5s, [this](TaskContext /*context*/) scheduler.Schedule(5s, [this](TaskContext /*context*/)
{ {
@@ -112,41 +103,29 @@ struct boss_kelidan_the_breaker : public BossAI
void KilledUnit(Unit* /*victim*/) override void KilledUnit(Unit* /*victim*/) override
{ {
if (urand(0, 1)) if (urand(0, 1))
{
Talk(SAY_KILL); Talk(SAY_KILL);
}
} }
void DoAction(int32 param) override void DoAction(int32 param) override
{ {
if (param == ACTION_CHANNELER_DIED) if (param == ACTION_CHANNELER_DIED)
{ {
if (me->FindNearestCreature(NPC_SHADOWMOON_CHANNELER, 100.0f)) if (!me->FindNearestCreature(NPC_SHADOWMOON_CHANNELER, 100.0f))
{ {
return; me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone();
} }
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone();
} }
else if (param == ACTION_CHANNELER_AGGRO) else if (param == ACTION_CHANNELER_AGGRO)
{
Talk(SAY_ADD_AGGRO); Talk(SAY_ADD_AGGRO);
}
} }
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
Talk(SAY_DIE); Talk(SAY_DIE);
_JustDied(); _JustDied();
if (instance) me->GetMap()->LoadGrid(0, -111.0f);
{
me->GetMap()->LoadGrid(0, -111.0f);
instance->SetData(DATA_KELIDAN, DONE);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR1), true);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR6), true);
}
} }
void ApplyImmunities(bool apply) void ApplyImmunities(bool apply)
@@ -42,22 +42,10 @@ struct boss_the_maker : public BossAI
}); });
} }
void Reset() override
{
_Reset();
if (instance)
{
instance->SetData(DATA_THE_MAKER, NOT_STARTED);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
}
}
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
_JustEngagedWith(); _JustEngagedWith();
instance->SetData(DATA_THE_MAKER, IN_PROGRESS);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), false);
scheduler.Schedule(6s, [this](TaskContext context) scheduler.Schedule(6s, [this](TaskContext context)
{ {
DoCastRandomTarget(SPELL_EXPLODING_BEAKER); DoCastRandomTarget(SPELL_EXPLODING_BEAKER);
@@ -72,30 +60,13 @@ struct boss_the_maker : public BossAI
void KilledUnit(Unit* victim) override void KilledUnit(Unit* victim) override
{ {
if (victim->IsPlayer() && urand(0, 1)) if (victim->IsPlayer() && urand(0, 1))
{
Talk(SAY_KILL); Talk(SAY_KILL);
}
} }
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
{ {
Talk(SAY_DIE); Talk(SAY_DIE);
_JustDied(); _JustDied();
instance->SetData(DATA_THE_MAKER, DONE);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR3), true);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
} }
}; };
@@ -22,9 +22,13 @@
DoorData const doorData[] = DoorData const doorData[] =
{ {
{ GO_BROGGOK_DOOR_FRONT, DATA_BROGGOK, DOOR_TYPE_ROOM }, { GO_MAKER_DOOR_FRONT, DATA_THE_MAKER, DOOR_TYPE_ROOM },
{ GO_BROGGOK_DOOR_REAR, DATA_BROGGOK, DOOR_TYPE_PASSAGE }, { GO_MAKER_DOOR_REAR, DATA_THE_MAKER, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END { GO_BROGGOK_DOOR_FRONT, DATA_BROGGOK, DOOR_TYPE_ROOM },
{ GO_BROGGOK_DOOR_REAR, DATA_BROGGOK, DOOR_TYPE_PASSAGE },
{ GO_KELIDAN_DOOR_EXIT1, DATA_KELIDAN, DOOR_TYPE_PASSAGE },
{ GO_KELIDAN_DOOR_EXIT2, DATA_KELIDAN, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END
}; };
ObjectData const gameobjectData[] = ObjectData const gameobjectData[] =
@@ -56,26 +60,15 @@ public:
LoadObjectData(creatureData, gameobjectData); LoadObjectData(creatureData, gameobjectData);
} }
uint32 _auiEncounter[MAX_ENCOUNTER];
ObjectGuid _doorGUIDs[6];
ObjectGuid _prisonGUIDs[4];
GuidSet _prisonersCell[4];
uint8 _prisonerCounter[4];
void Initialize() override void Initialize() override
{ {
memset(&_auiEncounter, 0, sizeof(_auiEncounter));
memset(&_prisonerCounter, 0, sizeof(_prisonerCounter)); memset(&_prisonerCounter, 0, sizeof(_prisonerCounter));
} }
void OnCreatureCreate(Creature* creature) override void OnCreatureCreate(Creature* creature) override
{ {
if (creature->GetEntry() == NPC_NASCENT_FEL_ORC) if (creature->GetEntry() == NPC_NASCENT_FEL_ORC)
{
StorePrisoner(creature); StorePrisoner(creature);
}
InstanceScript::OnCreatureCreate(creature); InstanceScript::OnCreatureCreate(creature);
} }
@@ -88,20 +81,6 @@ public:
void OnGameObjectCreate(GameObject* go) override void OnGameObjectCreate(GameObject* go) override
{ {
if (go->GetEntry() == 181766) //Final exit door
_doorGUIDs[0] = go->GetGUID();
if (go->GetEntry() == 181811) //The Maker Front door
_doorGUIDs[1] = go->GetGUID();
if (go->GetEntry() == 181812) //The Maker Rear door
{
_doorGUIDs[2] = go->GetGUID();
if (GetData(DATA_THE_MAKER) == DONE)
HandleGameObject(go->GetGUID(), true);
}
if (go->GetEntry() == 181823) //Kelidan exit door
_doorGUIDs[5] = go->GetGUID();
if (go->GetEntry() == 181821) //Broggok prison cell front right if (go->GetEntry() == 181821) //Broggok prison cell front right
_prisonGUIDs[0] = go->GetGUID(); _prisonGUIDs[0] = go->GetGUID();
if (go->GetEntry() == 181818) //Broggok prison cell back right if (go->GetEntry() == 181818) //Broggok prison cell back right
@@ -118,12 +97,6 @@ public:
{ {
switch (data) switch (data)
{ {
case DATA_DOOR1:
case DATA_DOOR2:
case DATA_DOOR3:
case DATA_DOOR6:
return _doorGUIDs[data - DATA_DOOR1];
case DATA_PRISON_CELL1: case DATA_PRISON_CELL1:
case DATA_PRISON_CELL2: case DATA_PRISON_CELL2:
case DATA_PRISON_CELL3: case DATA_PRISON_CELL3:
@@ -142,50 +115,17 @@ public:
if (type == DATA_BROGGOK) if (type == DATA_BROGGOK)
{ {
if (state == IN_PROGRESS) if (state == IN_PROGRESS)
{
ActivateCell(DATA_PRISON_CELL1); ActivateCell(DATA_PRISON_CELL1);
HandleGameObject(_doorGUIDs[3], false);
}
else if (state == NOT_STARTED) else if (state == NOT_STARTED)
{ {
ResetPrisons(); ResetPrisons();
HandleGameObject(_doorGUIDs[4], false); DoRespawnGameObject(DATA_BROGGOK_LEVER);
HandleGameObject(_doorGUIDs[3], true);
if (GameObject* lever = GetGameObject(DATA_BROGGOK_LEVER))
{
lever->Respawn();
}
} }
} }
return true; return true;
} }
void SetData(uint32 type, uint32 data) override
{
switch (type)
{
case DATA_THE_MAKER:
case DATA_KELIDAN:
_auiEncounter[type] = data;
break;
}
if (data == DONE)
SaveToDB();
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case DATA_THE_MAKER:
case DATA_KELIDAN:
return _auiEncounter[type];
}
return 0;
}
void ResetPrisons() void ResetPrisons()
{ {
for (uint8 i = 0; i < 4; ++i) for (uint8 i = 0; i < 4; ++i)
@@ -273,13 +213,9 @@ public:
break; break;
case DATA_BROGGOK_REAR_DOOR: case DATA_BROGGOK_REAR_DOOR:
if (GameObject* go = GetGameObject(DATA_BROGGOK_REAR_DOOR)) if (GameObject* go = GetGameObject(DATA_BROGGOK_REAR_DOOR))
{
HandleGameObject(ObjectGuid::Empty, true, go); HandleGameObject(ObjectGuid::Empty, true, go);
}
if (Creature* broggok = GetCreature(DATA_BROGGOK)) if (Creature* broggok = GetCreature(DATA_BROGGOK))
{
broggok->AI()->DoAction(ACTION_ACTIVATE_BROGGOK); broggok->AI()->DoAction(ACTION_ACTIVATE_BROGGOK);
}
break; break;
} }
} }
@@ -294,6 +230,11 @@ public:
prisoner->SetInCombatWithZone(); prisoner->SetInCombatWithZone();
} }
} }
private:
ObjectGuid _prisonGUIDs[4];
GuidSet _prisonersCell[4];
uint8 _prisonerCounter[4];
}; };
InstanceScript* GetInstanceScript(InstanceMap* map) const override InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -59,56 +59,11 @@ public:
SetBossNumber(ENCOUNTER_COUNT); SetBossNumber(ENCOUNTER_COUNT);
LoadObjectData(creatureData, nullptr); LoadObjectData(creatureData, nullptr);
LoadDoorData(doorData); LoadDoorData(doorData);
TeamIdInInstance = TEAM_NEUTRAL;
RescueTimer = 100 * MINUTE * IN_MILLISECONDS; RescueTimer = 100 * MINUTE * IN_MILLISECONDS;
} }
void OnPlayerEnter(Player* player) override
{
if (TeamIdInInstance == TEAM_NEUTRAL)
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
}
void OnPlayerLeave(Player* player) override
{
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
player->SetFactionForRace(player->getRace());
}
void OnCreatureCreate(Creature* creature) override void OnCreatureCreate(Creature* creature) override
{ {
if (TeamIdInInstance == TEAM_NEUTRAL)
{
Map::PlayerList const& players = instance->GetPlayers();
if (!players.IsEmpty())
if (Player* player = players.begin()->GetSource())
{
if (Group* group = player->GetGroup())
{
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
else
TeamIdInInstance = player->GetTeamId();
}
else
TeamIdInInstance = player->GetTeamId();
}
}
switch (creature->GetEntry()) switch (creature->GetEntry())
{ {
case NPC_SHATTERED_EXECUTIONER: case NPC_SHATTERED_EXECUTIONER:
@@ -117,22 +72,22 @@ public:
ExecutionerGUID = creature->GetGUID(); ExecutionerGUID = creature->GetGUID();
break; break;
case NPC_RIFLEMAN_BROWNBEARD: case NPC_RIFLEMAN_BROWNBEARD:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_KORAG_PROUDMANE); creature->UpdateEntry(NPC_KORAG_PROUDMANE);
PrisonerGUID[0] = creature->GetGUID(); PrisonerGUID[0] = creature->GetGUID();
break; break;
case NPC_CAPTAIN_ALINA: case NPC_CAPTAIN_ALINA:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_CAPTAIN_BONESHATTER); creature->UpdateEntry(NPC_CAPTAIN_BONESHATTER);
PrisonerGUID[1] = creature->GetGUID(); PrisonerGUID[1] = creature->GetGUID();
break; break;
case NPC_PRIVATE_JACINT: case NPC_PRIVATE_JACINT:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_SCOUT_ORGARR); creature->UpdateEntry(NPC_SCOUT_ORGARR);
PrisonerGUID[2] = creature->GetGUID(); PrisonerGUID[2] = creature->GetGUID();
break; break;
case NPC_RANDY_WHIZZLESPROCKET: case NPC_RANDY_WHIZZLESPROCKET:
if (TeamIdInInstance == TEAM_HORDE) if (GetTeamIdInInstance() == TEAM_HORDE)
creature->UpdateEntry(NPC_DRISELLA); creature->UpdateEntry(NPC_DRISELLA);
break; break;
} }
@@ -147,7 +102,7 @@ public:
instance->LoadGrid(230, -80); instance->LoadGrid(230, -80);
if (Creature* kargath = GetCreature(DATA_KARGATH)) if (Creature* kargath = GetCreature(DATA_KARGATH))
sCreatureTextMgr->SendChat(kargath, TeamIdInInstance == TEAM_ALLIANCE ? 3 : 4, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); sCreatureTextMgr->SendChat(kargath, GetTeamIdInInstance() == TEAM_ALLIANCE ? 3 : 4, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
RescueTimer = 80 * MINUTE * IN_MILLISECONDS; RescueTimer = 80 * MINUTE * IN_MILLISECONDS;
} }
@@ -213,7 +168,6 @@ public:
ObjectGuid ExecutionerGUID; ObjectGuid ExecutionerGUID;
ObjectGuid PrisonerGUID[3]; ObjectGuid PrisonerGUID[3];
uint32 RescueTimer; uint32 RescueTimer;
TeamId TeamIdInInstance;
}; };
}; };