diff --git a/apps/codestyle/codestyle-sql.py b/apps/codestyle/codestyle-sql.py index 0df5dec05..662f0962c 100644 --- a/apps/codestyle/codestyle-sql.py +++ b/apps/codestyle/codestyle-sql.py @@ -15,8 +15,9 @@ results = { "Multiple blank lines check": "Passed", "Trailing whitespace check": "Passed", "SQL codestyle check": "Passed", - "INSERT safety usage check": "Passed", - "Missing semicolon check": "Passed" + "INSERT & DELETE safety usage check": "Passed", + "Missing semicolon check": "Passed", + "Backtick check": "Passed" } # Collect all files in all directories @@ -44,8 +45,9 @@ def parsing_file(files: list) -> None: multiple_blank_lines_check(file, file_path) trailing_whitespace_check(file, file_path) sql_check(file, file_path) - insert_safety_check(file, file_path) + insert_delete_safety_check(file, file_path) semicolon_check(file, file_path) + backtick_check(file, file_path) except UnicodeDecodeError: print(f"\nCould not decode file {file_path}") sys.exit(1) @@ -134,9 +136,10 @@ def sql_check(file: io, file_path: str) -> None: error_handler = True results["SQL codestyle check"] = "Failed" -def insert_safety_check(file: io, file_path: str) -> None: +def insert_delete_safety_check(file: io, file_path: str) -> None: global error_handler, results file.seek(0) # Reset file pointer to the beginning + not_delete = ["creature_template", "gameobject_template", "item_template", "quest_template"] check_failed = False previous_line = "" @@ -148,11 +151,18 @@ def insert_safety_check(file: io, file_path: str) -> None: 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 + match = re.match(r"DELETE FROM\s+`([^`]+)`", line, re.IGNORECASE) + if match: + table_name = match.group(1) + if table_name in not_delete: + print( + f"Entries from {table} should not be deleted! {file_path} at line {line_number}") + check_failed = True # Handle the script error and update the result output if check_failed: error_handler = True - results["INSERT safety usage check"] = "Failed" + results["INSERT & DELETE safety usage check"] = "Failed" def semicolon_check(file: io, file_path: str) -> None: global error_handler, results @@ -192,6 +202,30 @@ def semicolon_check(file: io, file_path: str) -> None: error_handler = True results["Missing semicolon check"] = "Failed" +def backtick_check(file: io, file_path: str) -> None: + global error_handler, results + file.seek(0) + check_failed = False + pattern = re.compile( + r'\b(SELECT|FROM|JOIN|WHERE|GROUP BY|ORDER BY|DELETE FROM|UPDATE|INSERT INTO|SET)\s+([^;]+)', + re.IGNORECASE) + + for line_number, line in enumerate(file, start=1): + matches = pattern.findall(line) + for clause, content in matches: + words = re.findall(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b', content) + for word in words: + if word.upper() in {"SELECT", "FROM", "JOIN", "WHERE", "GROUP", "BY", "ORDER", + "DELETE", "UPDATE", "INSERT", "INTO", "SET", "VALUES"}: + continue + if not re.search(rf'`{re.escape(word)}`', content): + print(f"Missing backticks around ({word}). {file_path} at line {line_number}") + check_failed = True + + if check_failed: + error_handler = True + results["Backtick check"] = "Failed" + # Collect all files from matching directories all_files = collect_files_from_directories(src_directory) diff --git a/apps/installer/includes/os_configs/windows.sh b/apps/installer/includes/os_configs/windows.sh index 7687739d7..39d8eca6b 100644 --- a/apps/installer/includes/os_configs/windows.sh +++ b/apps/installer/includes/os_configs/windows.sh @@ -1,6 +1,6 @@ # install chocolatey before -@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" +# powershell.exe -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" # install automatically following packages: # cmake @@ -24,7 +24,7 @@ fi choco install -y --skip-checksums $INSTALL_ARGS cmake.install -y --installargs 'ADD_CMAKE_TO_PATH=System' choco install -y --skip-checksums $INSTALL_ARGS visualstudio2022-workload-nativedesktop -choco install -y --skip-checksums $INSTALL_ARGS openssl --version=3.1.1 -choco install -y --skip-checksums $INSTALL_ARGS boost-msvc-14.3 --version=1.82.0 -choco install -y --skip-checksums $INSTALL_ARGS mysql --version=8.0.31 +choco install -y --skip-checksums $INSTALL_ARGS openssl --force --version=3.3.2 +choco install -y --skip-checksums $INSTALL_ARGS boost-msvc-14.3 --force --version=1.87.0 +choco install -y --skip-checksums $INSTALL_ARGS mysql --force --version=8.4.4 diff --git a/data/sql/updates/db_characters/2025_01_31_00.sql b/data/sql/updates/db_characters/2025_01_31_00.sql new file mode 100644 index 000000000..da531119d --- /dev/null +++ b/data/sql/updates/db_characters/2025_01_31_00.sql @@ -0,0 +1,13 @@ +-- DB update 2024_11_15_00 -> 2025_01_31_00 +-- +DROP TABLE IF EXISTS `world_state`; +CREATE TABLE IF NOT EXISTS `world_state` ( + `Id` INT UNSIGNED NOT NULL COMMENT 'Internal save ID', + `Data` longtext, + PRIMARY KEY(`Id`) +) ENGINE=MYISAM DEFAULT CHARSET=utf8mb4 COMMENT='WorldState save system'; + +-- Isle of Quel'danas is in its final stage with all subphases completed +-- open all Sunwell Plateau gates +DELETE FROM `world_state` WHERE `Id` = 20; +INSERT INTO `world_state` (`Id`, `Data`) VALUES(20, '3 15 10000 10000 10000 10000 10000 10000 10000 10000 10000 10000 3 80 80 80'); diff --git a/data/sql/updates/db_world/2025_01_31_00.sql b/data/sql/updates/db_world/2025_01_31_00.sql new file mode 100644 index 000000000..422e8f678 --- /dev/null +++ b/data/sql/updates/db_world/2025_01_31_00.sql @@ -0,0 +1,1201 @@ +-- DB update 2025_01_28_00 -> 2025_01_31_00 +-- +DELETE FROM `command` WHERE `name` IN ('worldstate sunsreach phase', 'worldstate sunsreach subphase', 'worldstate sunsreach gate'); +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('worldstate sunsreach phase', 3, 'Syntax: .worldstate sunsreach phase .\nSets the phase of Sun''s Reach.\nValid values are:\n0: Staging Area\n1: Sanctum\n2: Armory\n3: Harbor.'), +('worldstate sunsreach subphase', 3, 'Syntax: .worldstate sunsreach subphase .\nSets the subphase mask of Sun''s Reach.\nValid values are:\n1: Portal\n2: Anvil\n4: Alchemy Lab\n8: Monument\n15: All.'), +('worldstate sunsreach gate', 3, 'Syntax: .worldstate sunsreach gate .\nSets the phase of Sunwell Plateau Gate.\nValid values are:\n0: All Gates Closed\n1: Gate 1 Agamath Open\n2: Gate 2 Rohendar Open\n3: Gate 3 Archonisus Open.'); + +-- Smith Hauthaa +SET @cguidsmith = 93964; +-- Shaani +SET @cguidjc = 94386; +-- Mar'nah +SET @cguidalch = 94378; +-- Demonic Crystals +SET @guidcrystals = 5300500; +-- Alchemy lab +SET @guidalch = 5300290; +-- Portal Subphase, Shattrath City, Shattered Sun Warrior and Shattered Sun Marksman +SET @cguidportalshat = 165102; +-- Portal Subphase, Isle of Quel'Danas +SET @cguidportalisle = 5300070; +-- Dawnblade Blood Knight +SET @cguidbloodknights = 5300293; +-- Dawnblade Summoner, Dawnblade Marksman +SET @cguidsummonermarksman = 5300355; +-- Irespeaker +SET @cguidirespeaker = 5300460; +-- Abyssal Flamewalker, Unleashed Hellion +SET @cguidflamewalkerhellion = 5300473; +-- Invisible Stalker Floating -> Fel Crystal Spell target +SET @cguidfelcrystalspelltarget = 5300031; + +SET +@sunsreachpone = 101, +@sunsreachptwoonly = 102, +@sunsreachptwoperm = 103, +@sunsreachnoportal = 104, +@sunsreachportal = 105, +@sunsreachpthreeonly = 106, +@sunsreachpthreeperm = 107, +@sunsreachnoanvil = 108, +@sunsreachanvil = 109, +@sunsreachpfour = 110, +@sunsreachnomonument = 111, +@sunsreachmonument = 112, +@sunsreachnolab = 113, +@sunsreachlab = 114, +@sunsreachkiru = 115, +@sunwellnone = 116, +@sunwellfirst = 117, +@sunwellsecond = 118, +@sunwellall = 119; + +DELETE FROM `game_event` WHERE `eventEntry` IN (@sunsreachpone, @sunsreachptwoonly, @sunsreachptwoperm, @sunsreachnoportal, @sunsreachportal, @sunsreachpthreeonly, @sunsreachpthreeperm, @sunsreachnoanvil, @sunsreachanvil, @sunsreachpfour, @sunsreachnomonument, @sunsreachmonument, @sunsreachnolab, @sunsreachlab, @sunsreachkiru, @sunwellnone, @sunwellfirst, @sunwellsecond, @sunwellall); +INSERT INTO `game_event` (`eventEntry`, `start_time`, `end_time`, `occurence`, `length`, `holiday`, `holidayStage`, `description`, `world_event`, `announce`) VALUES +(@sunsreachpone, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase 1', 5, 2), +(@sunsreachptwoonly, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase 2 Only', 5, 2), +(@sunsreachptwoperm, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase 2 Permanent', 5, 2), +(@sunsreachnoportal, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase No Portal', 5, 2), +(@sunsreachportal, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase Portal', 5, 2), +(@sunsreachpthreeonly, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase 3 Only', 5, 2), +(@sunsreachpthreeperm, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase 3 Permanent', 5, 2), +(@sunsreachnoanvil, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase No Anvil', 5, 2), +(@sunsreachanvil, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase Anvil', 5, 2), +(@sunsreachpfour, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase 4', 5, 2), +(@sunsreachnomonument, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase No Monument', 5, 2), +(@sunsreachmonument, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase Monument', 5, 2), +(@sunsreachnolab, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase No Alchemy Lab', 5, 2), +(@sunsreachlab, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase Alchemy Lab', 5, 2), +(@sunsreachkiru, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'Sun''s Reach Reclamation Phase K''iru', 5, 2), +(@sunwellnone, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'SWP - All Gates Closed', 5, 2), -- 1 1 1 +(@sunwellfirst, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'SWP - First Gate Open', 5, 2), -- 0 1 1 +(@sunwellsecond, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'SWP - Second Gate Open', 5, 2), -- 0 0 1 +(@sunwellall, '2000-01-01 14:00:00', '2000-01-01 14:00:00', 5184000, 2592000, 0, 0, 'SWP - All Gates Open', 5, 2); -- 0 0 0 + +UPDATE `creature_template` SET `ScriptName`='npc_suns_reach_reclamation' WHERE `entry` IN (24965,24967,25061,25057,24932,25108,25069,25046,24975,25112,25163); +UPDATE `creature_template` SET `ScriptName`='npc_sunwell_gate' WHERE `entry` = 25169; + +DELETE FROM `game_event_creature` WHERE `eventEntry` IN (@sunsreachpone, @sunsreachptwoonly, @sunsreachptwoperm, @sunsreachnoportal, @sunsreachportal, @sunsreachpthreeonly, @sunsreachpthreeperm, @sunsreachnoanvil, @sunsreachanvil, @sunsreachpfour, @sunsreachnomonument, @sunsreachmonument, @sunsreachnolab, @sunsreachlab, @sunsreachkiru, @sunwellnone, @sunwellfirst, @sunwellsecond, @sunwellall, -@sunsreachpone, -@sunsreachptwoonly, -@sunsreachptwoperm, -@sunsreachnoportal, -@sunsreachportal, -@sunsreachpthreeonly, -@sunsreachpthreeperm, -@sunsreachnoanvil, -@sunsreachanvil, -@sunsreachpfour, -@sunsreachnomonument, -@sunsreachmonument, -@sunsreachnolab, -@sunsreachlab, -@sunsreachkiru, -@sunwellnone, -@sunwellfirst, -@sunwellsecond, -@sunwellall); +INSERT INTO `game_event_creature` (`guid`, `eventEntry`) VALUES +-- Phase 2 +(93950, @sunsreachptwoperm), -- 25061 (Harbinger Inuuro) +(93951, @sunsreachptwoperm), -- 25057 (Battlemage Arynna) +(93952, @sunsreachptwoperm), -- 25034 (Tradesman Portanuus ) +(93953, @sunsreachptwoperm), -- 25133 (Astromancer Darnarian) +(96655, @sunsreachptwoperm), -- 24932 (Exarch Nasuun) +-- Phase 3 +(@cguidsmith, @sunsreachpthreeperm), -- 25046 (Smith Hauthaa ) +(93955, @sunsreachpthreeperm), -- 25108 (Vindicator Kaalan) +(93954, @sunsreachpthreeperm), -- 25035 (Tyrael Flamekissed ) +(93960, @sunsreachpthreeperm), -- 26089 (Kayri ) +(93956, @sunsreachpthreeperm), -- 26090 (Karynna ) +(93959, @sunsreachpthreeperm), -- 26091 (Olus ) +(93958, @sunsreachpthreeperm), -- 26092 (Soryn ) +(93957, @sunsreachpthreeperm), -- 25069 (Magister Ilastar) +-- Phase 4 +(@cguidalch, @sunsreachpfour), -- 24975 (Mar'nah ) +(94379, @sunsreachpfour), -- 25036 (Caregiver Inaara ) +(94384, @sunsreachpfour), -- 25112 (Anchorite Ayuri) +(94385, @sunsreachpfour), -- 25163 (Anchorite Kairthos) +(@cguidjc, @sunsreachpfour), -- 25950 (Shaani ) +-- Kaalif? +(94381, @sunsreachpfour), -- 25043 (Sereth Duskbringer ) +(94383, @sunsreachpfour), -- 25088 (Captain Valindria) +(94380, @sunsreachpfour), -- 25037 (Seraphina Bloodheart ) +(94382, @sunsreachpfour), -- 25045 (Sentinel ) +-- Anvil +(40444, @sunsreachanvil), -- 27667 (Anwehu ) +-- Alchemy Lab +(44253, @sunsreachlab), -- 27666 (Ontuvo ) +(984, @sunsreachlab), -- 25039 (Kaalif ) +-- K'iru +(62847, @sunsreachkiru), -- 25174 (K'iru) +-- Sanctum Allies +(76576, @sunsreachptwoperm), -- 24994 (Shattered Sun Sentry) 5300440 +(78387, @sunsreachptwoperm), -- 24994 (Shattered Sun Sentry) 5300445 +(76578, @sunsreachptwoperm), -- 24994 (Shattered Sun Sentry) 5300442 +(54113, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300093 +(54114, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300094 +(54143, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300095 +(65681, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300107 +(54176, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300097 +(54165, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300096 +(54177, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300098 +(54178, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300099 +(54181, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300100 +(54182, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300101 +(54184, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300103 +(54183, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300102 +(54185, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300104 +(56315, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300105 +(65680, @sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) 5300106 +(71926, @sunsreachptwoperm), -- 25115 (Shattered Sun Warrior) 5301090 +(71925, @sunsreachptwoperm), -- 25115 (Shattered Sun Warrior) 5301089 +(76577, @sunsreachptwoperm), -- 24994 (Shattered Sun Sentry) 5300441 +(76582, @sunsreachptwoperm), -- 24994 (Shattered Sun Sentry) +(76581, @sunsreachptwoperm), -- 24994 (Shattered Sun Sentry) +-- Armory Allies +(65693, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300118 +(65692, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300117 +(65691, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300116 +(65690, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300115 +(65689, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300114 +(65688, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300113 +(65685, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300111 +(65684, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300110 +(65683, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300109 +(65686, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300112 +(65682, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5300108 +(65687, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) 5301587 +-- (5300152, @sunsreachpthreeperm), -- 24938 (Shattered Sun Marksman) Missing? +(93961, @sunsreachpthreeperm), -- 26253 (Shattered Sun Peacekeeper) 5301179 +(71927, @sunsreachpthreeperm), -- 25115 (Shattered Sun Warrior) 5301091 +(71928, @sunsreachpthreeperm), -- 25115 (Shattered Sun Warrior) 5301092 +(76579, @sunsreachpthreeperm), -- 24994 (Shattered Sun Sentry) 5300443 +(78388, @sunsreachpthreeperm), -- 24994 (Shattered Sun Sentry) 5300446 +(72677, @sunsreachpthreeperm), -- 25115 (Shattered Sun Warrior) 5301093 +(72989, @sunsreachpthreeperm), -- 25115 (Shattered Sun Warrior) 5301094 +(78386, @sunsreachpthreeperm), -- 24994 (Shattered Sun Sentry) 5300433 +-- (5300436, @sunsreachpthreeperm), -- 24994 (Shattered Sun Sentry) Missing? +(77479, @sunsreachpthreeperm), -- 24994 (Shattered Sun Sentry) 5300444 +(78385, @sunsreachpthreeperm), -- 24994 (Shattered Sun Sentry) +(78389, @sunsreachpthreeperm), -- 24994 (Shattered Sun Sentry) 5300447 +(94387, @sunsreachpthreeperm), -- 25115 (Shattered Sun Warrior) +-- Dawning Square Allies (Unconfirmed) +(65702, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300126 +(65700, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300125 +(65696, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300121 +(65695, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300120 +(65694, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300119 +(65697, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300122 +(65699, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300124 +(65698, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300123 +(76580, @sunsreachpfour), -- 24994 (Shattered Sun Sentry) 5300430 +-- Harbor Allies +(94433, @sunsreachpfour), -- 25115 (Shattered Sun Warrior) 5301210 +(94432, @sunsreachpfour), -- 25115 (Shattered Sun Warrior) 5301211 +(94401, @sunsreachpfour), -- 24994 (Shattered Sun Sentry) 5300448 +(94406, @sunsreachpfour), -- 24994 (Shattered Sun Sentry) 5300451 +(94413, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300134 +(94414, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300135 +(94415, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300136 +(12719, @sunsreachpfour), -- 24994 (Shattered Sun Sentry) 5300429 +(94416, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300137 +(94417, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300138 +(94418, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300139 +(94419, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300140 +(94420, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300141 +(94422, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300142 +(94423, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300143 +(94424, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300144 +(94425, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300145 +(94426, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300146 +(94427, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300147 +(94428, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300148 +(94429, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300149 +(94430, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300150 +(94431, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300151 +(94409, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300130 +(94402, @sunsreachpfour), -- 24994 (Shattered Sun Sentry) 5300449 +(94377, @sunsreachpfour), -- 24994 (Shattered Sun Sentry) +(83998, @sunsreachpfour), -- 24994 (Shattered Sun Sentry) +(94435, @sunsreachpfour), -- 25115 (Shattered Sun Warrior) 5301097 +(94434, @sunsreachpfour), -- 25115 (Shattered Sun Warrior) 5301096 +(94436, @sunsreachpfour), -- 25115 (Shattered Sun Warrior) 5301098 +(94437, @sunsreachpfour), -- 25115 (Shattered Sun Warrior) 5301099 +(94438, @sunsreachpfour), -- 25115 (Shattered Sun Warrior) 5301100 +(94408, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300129 +(94407, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300128 +(94410, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300131 +(94411, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300132 +(94412, @sunsreachpfour), -- 24938 (Shattered Sun Marksman) 5300133 +(94403, @sunsreachpfour), -- 24994 (Shattered Sun Sentry) 5300450 +-- Sanctum Enemies +(5300412, -@sunsreachptwoperm), -- 24979 (Dawnblade Marksman) +(5300411, -@sunsreachptwoperm), -- 24979 (Dawnblade Marksman) +(5300414, -@sunsreachptwoperm), -- 24979 (Dawnblade Marksman) +(5300313, -@sunsreachptwoperm), -- 24976 (Dawnblade Blood Knight) +(5300314, -@sunsreachptwoperm), -- 24976 (Dawnblade Blood Knight) +(5300368, -@sunsreachptwoperm), -- 24978 (Dawnblade Summoner) +-- Armory Enemies +(5300463, -@sunsreachpthreeperm), -- 24999 (Irespeaker) +(5300462, -@sunsreachpthreeperm), -- 24999 (Irespeaker) +(5300498, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(5300460, -@sunsreachpthreeperm), -- 24999 (Irespeaker) +(5300461, -@sunsreachpthreeperm), -- 24999 (Irespeaker) +(5300464, -@sunsreachpthreeperm), -- 24999 (Irespeaker) +(5300493, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(5300494, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(5300465, -@sunsreachpthreeperm), -- 24999 (Irespeaker) +(5300477, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300478, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300476, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300495, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(93965, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300480, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300365, -@sunsreachpthreeperm), -- 24978 (Dawnblade Summoner) +(5300499, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(5300479, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300475, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300481, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300500, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(5300496, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(5300497, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(5300501, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(93982, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(@cguidfelcrystalspelltarget+0, -@sunsreachpthreeperm), -- 25953 (Fel Crystal Spell Target) +(@cguidfelcrystalspelltarget+1, -@sunsreachpthreeperm), -- 25953 (Fel Crystal Spell Target) +(@cguidfelcrystalspelltarget+2, -@sunsreachpthreeperm), -- 25953 (Fel Crystal Spell Target) +(@cguidfelcrystalspelltarget+3, -@sunsreachpthreeperm), -- 25953 (Fel Crystal Spell Target) +(@cguidfelcrystalspelltarget+4, -@sunsreachpthreeperm), -- 25953 (Fel Crystal Spell Target) +-- Dawning Square Enemies +(5300406, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300403, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300408, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300407, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300404, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300405, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +-- Harbor Enemies +(5300410, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300302, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300303, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300409, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300397, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300399, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300356, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300359, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300301, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300358, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300300, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300393, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300355, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300357, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300394, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300295, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300364, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300312, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300367, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300366, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300360, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300361, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300307, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300298, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300395, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300297, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300396, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300415, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300398, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300305, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300306, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300304, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300308, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300363, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300392, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300391, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300390, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300389, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300413, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300400, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300310, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300362, -@sunsreachpfour), -- 24978 (Dawnblade Summoner) +(5300388, -@sunsreachpfour), -- 24979 (Dawnblade Marksman) +(5300311, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300299, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +(5300296, -@sunsreachpfour), -- 24976 (Dawnblade Blood Knight) +-- Unmarked +(93969, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300473, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(5300474, -@sunsreachpthreeperm), -- 25001 (Abyssal Flamewalker) +(93983, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(5300503, -@sunsreachpthreeperm), -- 25002 (Unleashed Hellion) +(54030, -@sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) +(54031, -@sunsreachptwoperm), -- 24938 (Shattered Sun Marksman) +(5300293, -@sunsreachptwoperm), -- 24976 (Dawnblade Blood Knight) +(5300294, -@sunsreachptwoperm), -- 24976 (Dawnblade Blood Knight) +(5300309, -@sunsreachptwoperm), -- 24976 (Dawnblade Blood Knight) +(5300315, -@sunsreachptwoperm), -- 24976 (Dawnblade Blood Knight) +(5300369, -@sunsreachptwoperm), -- 24978 (Dawnblade Summoner) +(5300370, -@sunsreachptwoperm), -- 24978 (Dawnblade Summoner) +(5300401, -@sunsreachptwoperm), -- 24979 (Dawnblade Marksman) +(5300402, -@sunsreachptwoperm), -- 24979 (Dawnblade Marksman) +(71916, -@sunsreachptwoperm), -- 25115 (Shattered Sun Warrior) +(71917, -@sunsreachptwoperm), -- 25115 (Shattered Sun Warrior) +(71919, -@sunsreachptwoperm), -- 25115 (Shattered Sun Warrior) +(54030, -@sunsreachptwoonly), -- 24938 (Shattered Sun Marksman) +(54031, -@sunsreachptwoonly), -- 24938 (Shattered Sun Marksman) +(5300293, -@sunsreachptwoonly), -- 24976 (Dawnblade Blood Knight) +(5300294, -@sunsreachptwoonly), -- 24976 (Dawnblade Blood Knight) +(5300309, -@sunsreachptwoonly), -- 24976 (Dawnblade Blood Knight) +(5300315, -@sunsreachptwoonly), -- 24976 (Dawnblade Blood Knight) +(5300369, -@sunsreachptwoonly), -- 24978 (Dawnblade Summoner) +(5300370, -@sunsreachptwoonly), -- 24978 (Dawnblade Summoner) +(5300401, -@sunsreachptwoonly), -- 24979 (Dawnblade Marksman) +(5300402, -@sunsreachptwoonly), -- 24979 (Dawnblade Marksman) +(@cguidportalshat+0, @sunsreachportal), -- 25115 (Shattered Sun Warrior) +(@cguidportalshat+1, @sunsreachportal), -- 25115 (Shattered Sun Warrior) +(@cguidportalshat+2, @sunsreachportal), -- 25115 (Shattered Sun Warrior) +(@cguidportalshat+3, @sunsreachportal), -- 25115 (Shattered Sun Warrior) +(@cguidportalshat+4, @sunsreachportal), -- 24938 (Shattered Sun Marksman) +(@cguidportalshat+5, @sunsreachportal), -- 24938 (Shattered Sun Marksman) +(@cguidportalshat+6, @sunsreachportal), -- 24938 (Shattered Sun Marksman) +(@cguidportalshat+7, @sunsreachportal), -- 24938 (Shattered Sun Marksman) +(@cguidportalisle+0, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+1, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+2, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+3, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+4, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+5, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+6, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+7, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+8, @sunsreachportal), -- 24936 (Sunwell Daily Bunny x 0.01) +(@cguidportalisle+9, @sunsreachportal); -- 24936 (Sunwell Daily Bunny x 0.01) + +DELETE FROM `game_event_gameobject` WHERE `eventEntry` IN (@sunsreachpone, @sunsreachptwoonly, @sunsreachptwoperm, @sunsreachnoportal, @sunsreachportal, @sunsreachpthreeonly, @sunsreachpthreeperm, @sunsreachnoanvil, @sunsreachanvil, @sunsreachpfour, @sunsreachnomonument, @sunsreachmonument, @sunsreachnolab, @sunsreachlab, @sunsreachkiru, @sunwellnone, @sunwellfirst, @sunwellsecond, @sunwellall, -@sunsreachpone, -@sunsreachptwoonly, -@sunsreachptwoperm, -@sunsreachnoportal, -@sunsreachportal, -@sunsreachpthreeonly, -@sunsreachpthreeperm, -@sunsreachnoanvil, -@sunsreachanvil, -@sunsreachpfour, -@sunsreachnomonument, -@sunsreachmonument, -@sunsreachnolab, -@sunsreachlab, -@sunsreachkiru, -@sunwellnone, -@sunwellfirst, -@sunwellsecond, -@sunwellall); +INSERT INTO `game_event_gameobject` (`guid`, `eventEntry`) VALUES +-- Portal +(47196, @sunsreachportal), -- 187056, Shattrath Portal to Isle of Quel'Danas +(27755, @sunsreachportal), -- 187335, Portal from Shattrath City +-- Armory +(27811, @sunsreachpthreeperm), -- 187112, Forge +-- Anvil +(27810, @sunsreachanvil), -- 187111, Hauthaa's Anvil +-- Phase 4 +(27845, @sunsreachpfour), -- 187113, Mailbox +-- Monument +(50446, @sunsreachmonument), -- 187116, Monument to the Fallen - Sunwell Plateau +(27862, @sunsreachmonument), -- 187116, Monument to the Fallen - Isle of Quel'Danas +(@guidalch, @sunsreachlab), -- 187115, Alchemy Lab +-- Crystals +(@guidcrystals+0, -@sunsreachpthreeperm), -- 187120, Demonic Crystal +(@guidcrystals+1, -@sunsreachpthreeperm), -- 187120, Demonic Crystal +(@guidcrystals+2, -@sunsreachpthreeperm), -- 187120, Demonic Crystal +(@guidcrystals+3, -@sunsreachpthreeperm), -- 187120, Demonic Crystal +(@guidcrystals+4, -@sunsreachpthreeperm), -- 187120, Demonic Crystal +-- Banners +(27839, @sunsreachptwoperm), -- 187356, Shattered Sun Banner (Draenei - Pole) +(27833, @sunsreachptwoperm), -- 187357, Shattered Sun Banner (Blood Elf - Pole) +(27838, @sunsreachpthreeperm), -- 187357, Shattered Sun Banner (Blood Elf - Pole) +(27844, @sunsreachpthreeperm), -- 187356, Shattered Sun Banner (Draenei - Pole) +(27830, @sunsreachpfour), -- 187356, Shattered Sun Banner (Draenei - Pole) +(27831, @sunsreachpfour), -- 187356, Shattered Sun Banner (Draenei - Pole) +(27861, @sunsreachpfour), -- 187357, Shattered Sun Banner (Blood Elf - Pole) +(27836, @sunsreachpfour), -- 187357, Shattered Sun Banner (Blood Elf - Pole) +(27827, @sunsreachpfour), -- 187357, Shattered Sun Banner (Blood Elf - Pole) +(27828, @sunsreachpfour), -- 187356, Shattered Sun Banner (Draenei - Pole) +-- Gates +(50441, @sunwellnone), -- 187766, Agamath, The First Gate +(50439, @sunwellnone), -- 187764, Rohendor, The Second Gate +(50440, @sunwellnone), -- 187765, Archonisus, The Third Gate +(50439, @sunwellfirst), -- 187764, Rohendor, The Second Gate +(50440, @sunwellfirst), -- 187765, Archonisus, The Third Gate +(50440, @sunwellsecond); -- 187765, Archonisus, The Third Gate + +DELETE FROM `creature_queststarter` WHERE `quest` IN (11514, 11520, 11521, 11523, 11525, 11532, 11533, 11535, 11536, 11537, 11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549); +DELETE FROM `game_event_creature_quest` WHERE `eventEntry` IN (@sunsreachpone, @sunsreachptwoonly, @sunsreachptwoperm, @sunsreachnoportal, @sunsreachportal, @sunsreachpthreeonly, @sunsreachpthreeperm, @sunsreachnoanvil, @sunsreachanvil, @sunsreachpfour, @sunsreachnomonument, @sunsreachmonument, @sunsreachnolab, @sunsreachlab, @sunsreachkiru, @sunwellnone, @sunwellfirst, @sunwellsecond, @sunwellall); +INSERT INTO `game_event_creature_quest` (`eventEntry`, `id`, `quest`) VALUES +-- Phase 1 +(@sunsreachpone, 24965, 11524), -- Erratic Behavior +(@sunsreachpone, 24967, 11496), -- The Sanctum Wards +-- Phase 2 +(@sunsreachptwoonly, 25061, 11538), -- The Battle for the Sun's Reach Armory +(@sunsreachptwoonly, 25057, 11532), -- Distraction at the Dead Scar +-- No portal +(@sunsreachnoportal, 25034, 11517), -- Report to Nasuun +(@sunsreachnoportal, 24932, 11513), -- Intercepting the Mana Cells +-- Phase 3 +(@sunsreachpthreeonly, 25108, 11542), -- Intercept the Reinforcements +(@sunsreachpthreeonly, 25069, 11539), -- Taking the Harbor +-- No anvil +(@sunsreachnoanvil, 25046, 11535), -- Making Ready +-- No alchemy lab +(@sunsreachnolab, 24975, 11520), -- Discovering Your Roots +-- No monument +(@sunsreachnomonument, 25112, 11545), -- A Charitable Donation +-- Phase 2 permanent +(@sunsreachptwoperm, 24967, 11523), -- Arm the Wards! +(@sunsreachptwoperm, 24965, 11525), -- Further Conversions +-- Portal +(@sunsreachportal, 24932, 11514), -- Maintaining the Sunwell Portal +(@sunsreachportal, 25133, 11547), -- Know Your Ley Lines +(@sunsreachportal, 25034, 11534), -- Report to Nasuun +-- Phase 3 permanent +(@sunsreachpthreeperm, 25057, 11533), -- The Air Strikes Must Continue +(@sunsreachpthreeperm, 25061, 11537), -- The Battle Must Go On +-- Anvil +(@sunsreachanvil, 25046, 11536), -- Don't Stop Now.... +(@sunsreachanvil, 25046, 11544), -- Ata'mal Armaments +-- Phase 4 +(@sunsreachpfour, 25069, 11540), -- Crush the Dawnblade +(@sunsreachpfour, 25088, 11541), -- Disrupt the Greengill Coast +(@sunsreachpfour, 25108, 11543), -- Keeping the Enemy at Bay +(@sunsreachpfour, 25163, 11549), -- A Magnanimous Benefactor +-- Monument +(@sunsreachmonument, 25112, 11548), -- Your Continued Support +-- Alchemy lab +(@sunsreachlab, 24975, 11521), -- Rediscovering Your Roots +(@sunsreachlab, 24975, 11546); -- Open for Business + +DELETE FROM `gossip_menu` WHERE `MenuID` IN (51000, 51001, 51002, 51003, 51004, 51005, 51006, 51007, 51008, 51009, 51010, 51011, 51012, 51013); -- Custom IDs +DELETE FROM `gossip_menu` WHERE `MenuID` IN (9046, 9307) AND `TextID` IN (12226, 12304, 12305, 12306); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +-- Exarch Nasuun +(9046, 12226), -- Portal progress +(51000, 12300), -- Armory progress +(51001, 12301), -- Anvil progress +(51002, 12302), -- Harbor progress +(51003, 12303), -- Alchemy lab progress +(9307, 12304), -- Agamath gate progress +(9307, 12305), -- Rohendor gate progress +(9307, 12306), -- Archonisus gate progress +-- Vindicator Moorba +(51004, 12602), -- Agamath gate progress +(51004, 12603), -- Rohendor gate progress +(51004, 12605), -- Archonisus gate progress +-- Vindicator Xayann +(51005, 12240), -- Sanctum progress +-- Captain Theris Dawnheart +(51006, 12260), -- Sanctum progress +-- Harbinger Inuuro +(51007, 12255), -- Armory progress +-- Battlemage Arynna +(51008, 12257), -- Armory progress +-- Magister Ilastar +(51009, 12339), -- Harbor progress +-- Vindicator Kaalan +(51010, 12319), -- Harbor progress +-- Smith Hauthaa +(51011, 12285), -- Anvil progress +-- Mar'nah +(51012, 12238), -- Alchemy lab progress +-- Anchorite Ayuri +(51013, 12322); -- Monument progress + +DELETE FROM `npc_text` WHERE `ID` IN (12306, 12602, 12603, 12605); +INSERT INTO `npc_text` (`ID`, `text0_0`, `text0_1`, `BroadcastTextID0`, `lang0`, `Probability0`, `em0_0`, `em0_1`, `em0_2`, `em0_3`, `em0_4`, `em0_5`, `text1_0`, `text1_1`, `BroadcastTextID1`, `lang1`, `Probability1`, `em1_0`, `em1_1`, `em1_2`, `em1_3`, `em1_4`, `em1_5`, `text2_0`, `text2_1`, `BroadcastTextID2`, `lang2`, `Probability2`, `em2_0`, `em2_1`, `em2_2`, `em2_3`, `em2_4`, `em2_5`, `text3_0`, `text3_1`, `BroadcastTextID3`, `lang3`, `Probability3`, `em3_0`, `em3_1`, `em3_2`, `em3_3`, `em3_4`, `em3_5`, `text4_0`, `text4_1`, `BroadcastTextID4`, `lang4`, `Probability4`, `em4_0`, `em4_1`, `em4_2`, `em4_3`, `em4_4`, `em4_5`, `text5_0`, `text5_1`, `BroadcastTextID5`, `lang5`, `Probability5`, `em5_0`, `em5_1`, `em5_2`, `em5_3`, `em5_4`, `em5_5`, `text6_0`, `text6_1`, `BroadcastTextID6`, `lang6`, `Probability6`, `em6_0`, `em6_1`, `em6_2`, `em6_3`, `em6_4`, `em6_5`, `text7_0`, `text7_1`, `BroadcastTextID7`, `lang7`, `Probability7`, `em7_0`, `em7_1`, `em7_2`, `em7_3`, `em7_4`, `em7_5`, `VerifiedBuild`) VALUES +(12602, 'All three barriers are fully operational. Consult with Archmage Ne''thul in Sun''s Reach Harbor to aid the effort in unlocking the gates.', '', 25535, 0, 1, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), +(12603, 'Agamath, the First Gate has been breached. Two of Kil''jaeden''s most powerful lieutenants, Lady Sacrolash and Grand Warlock Alythess, are now vulnerable to attack.', '', 25534, 0, 1, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), +(12605, 'Agamath, the First Gate and Rohendor, the Second Gate are now destroyed. Only Archonisus, the Third Gate remains.', '', 25536, 0, 1, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), +(12306, 'Rohendor, the Second Gate has been brought down, but the last of the Sunwell Plateau''s magical barriers, Archonisus, resists us, $n.$B$BMaintain your efforts to assist at the Sunwell in any way that you can.', '', 24234, 0, 1, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + +DELETE FROM `gossip_menu_option` WHERE `MenuID` IN (51000, 51001, 51002, 51003); +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES +(51000, 0, 0, 'I have something else to ask you about.', 24226, 1, 1, 9046, 0, 0, 0, '', 0, 0), +(51001, 0, 0, 'I have something else to ask you about.', 24226, 1, 1, 9046, 0, 0, 0, '', 0, 0), +(51002, 0, 0, 'I have something else to ask you about.', 24226, 1, 1, 9046, 0, 0, 0, '', 0, 0), +(51003, 0, 0, 'I have something else to ask you about.', 24226, 1, 1, 9046, 0, 0, 0, '', 0, 0); + +DELETE FROM `gossip_menu_option` WHERE `MenuID` = 9046 AND `OptionID` IN (0, 1, 2, 3); +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES +(9046, 0, 0, 'What news of the fight to take the Sun''s Reach Armory?', 24222, 1, 1, 51000, 0, 0, 0, '', 0, 0), +(9046, 1, 0, 'How close are we to the completion of the anvil and forge at the Sun''s Reach Armory?', 24224, 1, 1, 51002, 0, 0, 0, '', 0, 0), +(9046, 2, 0, 'Exarch, have we taken the Sun''s Reach Harbor yet?', 24227, 1, 1, 51001, 0, 0, 0, '', 0, 0), +(9046, 3, 0, 'Nasuun, do you know how long until we have an alchemy lab at the Sun''s Reach Harbor?', 24229, 1, 1, 51003, 0, 0, 0, '', 0, 0); + +DELETE FROM `creature_questender` WHERE `quest` IN (11496, 11513, 11517, 11520, 11524, 11532, 11535, 11538, 11539, 11542, 11545); +INSERT INTO `creature_questender` (`id`, `quest`) VALUES +(24965, 11524), -- Erratic Behavior +(24967, 11496), -- The Sanctum Wards +(25061, 11538), -- The Battle for the Sun's Reach Armory +(25057, 11532), -- Distraction at the Dead Scar +-- No portal +(24932, 11517), -- Report to Nasuun +(24932, 11513), -- Intercepting the Mana Cells +(25108, 11542), -- Intercept the Reinforcements +(25069, 11539), -- Taking the Harbor +(25046, 11535), -- Making Ready +(24975, 11520), -- Discovering Your Roots +(25112, 11545); -- A Charitable Donation + +DELETE FROM `conditions` WHERE `ConditionTypeOrReference` = 12 AND `ConditionValue1` IN (@sunsreachpone, @sunsreachptwoonly, @sunsreachptwoperm, @sunsreachnoportal, @sunsreachportal, @sunsreachpthreeonly, @sunsreachpthreeperm, @sunsreachnoanvil, @sunsreachanvil, @sunsreachpfour, @sunsreachnomonument, @sunsreachmonument, @sunsreachnolab, @sunsreachlab, @sunsreachkiru, @sunwellnone, @sunwellfirst, @sunwellsecond, @sunwellall); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +-- Vindicator Xayann +(14, 9052, 12240, 0, 0, 12, 0, @sunsreachpone, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 1'' is active'), +(14, 9052, 12241, 0, 1, 12, 0, @sunsreachpone, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 1'' is not active'), +-- Captain Theris Dawnhearth +(14, 9065, 12260, 0, 0, 12, 0, @sunsreachpone, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 1'' is active'), +(14, 9065, 12259, 0, 1, 12, 0, @sunsreachpone, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 1'' is not active'), +-- Exarch Nasuun +(14, 9046, 12226, 0, 0, 12, 0, @sunsreachnoportal, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Portal'' is active'), +(14, 9046, 12227, 0, 1, 12, 0, @sunsreachnoportal, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Portal'' is not active'), +-- Battlemage Arynna +(14, 9064, 12257, 0, 0, 12, 0, @sunsreachptwoonly, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 2 Only'' is active'), +(14, 9064, 12258, 0, 1, 12, 0, @sunsreachptwoonly, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 2 Only'' is not active'), +-- Harbinger Inuuro +(14, 9063, 12255, 0, 0, 12, 0, @sunsreachptwoonly, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 2 Only'' is active'), +(14, 9063, 12256, 0, 1, 12, 0, @sunsreachptwoonly, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 2 Only'' is not active'), +-- +(14, 51000, 12300, 0, 0, 12, 0, @sunsreachptwoonly, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 2 Only'' is active'), +(14, 51001, 12301, 0, 0, 12, 0, @sunsreachnoanvil, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Anvil'' is active'), +-- Smith Hauthaa +(14, 9087, 12285, 0, 0, 12, 0, @sunsreachnoanvil, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Anvil'' is active'), +(14, 9087, 12286, 0, 1, 12, 0, @sunsreachnoanvil, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Anvil'' is not active'), +-- +(14, 51002, 12302, 0, 0, 12, 0, @sunsreachpthreeonly, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 3 Only'' is active'), +-- Magister Ilastar +(14, 9127, 12339, 0, 0, 12, 0, @sunsreachpthreeonly, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 3 Only'' is active'), +(14, 9127, 12340, 0, 1, 12, 0, @sunsreachpthreeonly, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 3 Only'' is not active'), +-- Vindicator Kaalan +(14, 9111, 12319, 0, 0, 12, 0, @sunsreachpthreeonly, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 3 Only'' is active'), +(14, 9111, 12320, 0, 1, 12, 0, @sunsreachpthreeonly, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase 3 Only'' is not active'), +-- +(14, 51003, 12303, 0, 0, 12, 0, @sunsreachnolab, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Alchemy Lab'' is active'), +-- Mar'nah +(14, 9050, 12238, 0, 0, 12, 0, @sunsreachnolab, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Alchemy Lab'' is active'), +(14, 9050, 12237, 0, 1, 12, 0, @sunsreachnolab, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Alchemy Lab'' is not active'), +-- Shaani Jewelcrafting Supplies> +(14, 9198, 12496, 0, 0, 12, 0, @sunsreachnolab, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Alchemy Lab'' is active'), +(14, 9198, 12497, 0, 1, 12, 0, @sunsreachnolab, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Alchemy Lab'' is not active'), +-- Anchorite Ayuri +(14, 9115, 12322, 0, 0, 12, 0, @sunsreachnomonument, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Monument'' is active'), +(14, 9115, 12323, 0, 1, 12, 0, @sunsreachnomonument, 0, 0, 1, 0, 0, '', 'Show gossip text if the event ''Sun''s Reach Reclamation Phase No Monument'' is not active'), +-- Exarch Nasuun +(15, 9046, 0, 0, 0, 12, 0, @sunsreachptwoonly, 0, 0, 0, 0, 0, '', 'Show gossip option if the event ''Sun''s Reach Reclamation Phase 2 Only'' is active'), +(15, 9046, 1, 0, 0, 12, 0, @sunsreachnoanvil, 0, 0, 0, 0, 0, '', 'Show gossip option if the event ''Sun''s Reach Reclamation Phase No Anvil'' is active'), +(15, 9046, 2, 0, 0, 12, 0, @sunsreachpthreeonly, 0, 0, 0, 0, 0, '', 'Show gossip option if the event ''Sun''s Reach Reclamation Phase 3 Only'' is active'), +(15, 9046, 3, 0, 0, 12, 0, @sunsreachnolab, 0, 0, 0, 0, 0, '', 'Show gossip option if the event ''Sun''s Reach Reclamation Phase No Alchemy Lab'' is active'), +-- Sunwell Gates +(14, 9307, 12304, 0, 0, 12, 0, @sunwellnone, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''SWP - All Gates Closed'' is active'), +(14, 9307, 12305, 0, 0, 12, 0, @sunwellfirst, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''SWP - First Gate Open'' is active'), +(14, 9307, 12306, 0, 0, 12, 0, @sunwellsecond, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''SWP - Second Gate Open'' is active'), +-- +(14, 51004, 12602, 0, 0, 12, 0, @sunwellnone, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''SWP - All Gates Closed'' is active'), +(14, 51004, 12603, 0, 0, 12, 0, @sunwellfirst, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''SWP - First Gate Open'' is active'), +(14, 51004, 12605, 0, 0, 12, 0, @sunwellsecond, 0, 0, 0, 0, 0, '', 'Show gossip text if the event ''SWP - Second Gate Open'' is active'); + +-- Staging +-- Captain Theris Dawnhearth +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9065) AND (`TextID` IN (12260)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9065, 12260); +-- Vindicator Xayann +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9052) AND (`TextID` IN (12240)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9052, 12240); + +-- Sanctum +-- Battlemage Arynna +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9064) AND (`TextID` IN (12257)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9064, 12257); +-- Harbinger Inuuro +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9063) AND (`TextID` IN (12255)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9063, 12255); + +-- Armory +-- Magister Ilastar +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9127) AND (`TextID` IN (12339)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9127, 12339); + +-- Anvil subphase +-- Smith Hauthaa +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9087) AND (`TextID` IN (12285)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9087, 12285); + +-- Harbor +-- Shaani Jewelcrafting Supplies> +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9198) AND (`TextID` IN (12496)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9198, 12496); +-- Mar'nah +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9050) AND (`TextID` IN (12238)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9050, 12238); + +-- Monument +DELETE FROM `gossip_menu` WHERE (`MenuID` = 9115) AND (`TextID` IN (12322)); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES +(9115, 12322); + +-- Portal Subphase Shattrath mobs walking to portal, entering and despawning +-- Remove Shattrath - Shattered Sun Marksman that should be spawned by Portal Subphase +DELETE FROM `creature` WHERE (`id1` = 24938) AND (`guid` IN (96656, 96657, 96658)); +-- Remove Shattrath - Shattered Sun Warrior that should be spawned by Portal Subphase +DELETE FROM `creature` WHERE (`id1` = 25115) AND (`guid` IN (96593)); + +-- Anvil vendor +-- Smith Hauthaa +DELETE FROM `npc_vendor` WHERE (`entry` = 25046); +DELETE FROM `game_event_npc_vendor` WHERE (`eventEntry` = @sunsreachanvil) AND `guid` = @cguidsmith; +INSERT INTO `game_event_npc_vendor` (`eventEntry`, `guid`, `slot`, `item`, `maxcount`, `incrtime`, `ExtendedCost`) VALUES +(@sunsreachanvil, @cguidsmith, 0, 34887, 0, 0, 2059), +(@sunsreachanvil, @cguidsmith, 0, 34888, 0, 0, 2059), +(@sunsreachanvil, @cguidsmith, 0, 34889, 0, 0, 2059), +(@sunsreachanvil, @cguidsmith, 0, 34890, 0, 0, 2059), +(@sunsreachanvil, @cguidsmith, 0, 34891, 0, 0, 2329), +(@sunsreachanvil, @cguidsmith, 0, 34892, 0, 0, 2329), +(@sunsreachanvil, @cguidsmith, 0, 34893, 0, 0, 2331), +(@sunsreachanvil, @cguidsmith, 0, 34894, 0, 0, 2331), +(@sunsreachanvil, @cguidsmith, 0, 34895, 0, 0, 2329), +(@sunsreachanvil, @cguidsmith, 0, 34896, 0, 0, 2329), +(@sunsreachanvil, @cguidsmith, 0, 34898, 0, 0, 2329), +(@sunsreachanvil, @cguidsmith, 0, 34900, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34901, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34902, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34903, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34904, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34905, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34906, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34910, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34911, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34912, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34914, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34916, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34917, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34918, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34919, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34921, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34922, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34923, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34924, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34925, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34926, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34927, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34928, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34929, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34930, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34931, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34932, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34933, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34934, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34935, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34936, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34937, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34938, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34939, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34940, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34941, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34942, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34943, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34944, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34945, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34946, 0, 0, 2333), +(@sunsreachanvil, @cguidsmith, 0, 34947, 0, 0, 2049), +(@sunsreachanvil, @cguidsmith, 0, 34949, 0, 0, 2332), +(@sunsreachanvil, @cguidsmith, 0, 34950, 0, 0, 2332), +(@sunsreachanvil, @cguidsmith, 0, 34951, 0, 0, 2332), +(@sunsreachanvil, @cguidsmith, 0, 34952, 0, 0, 2332); + +-- Mar'nah +DELETE FROM `npc_vendor` WHERE (`entry` = 24975); +DELETE FROM `game_event_npc_vendor` WHERE (`eventEntry` = @sunsreachlab) AND `guid` = @cguidalch; +INSERT INTO `game_event_npc_vendor` (`eventEntry`, `guid`, `slot`, `item`, `maxcount`, `incrtime`, `ExtendedCost`) VALUES +(@sunsreachlab, @cguidalch, 0, 3371, 0, 0, 0), +(@sunsreachlab, @cguidalch, 0, 3372, 0, 0, 0), +(@sunsreachlab, @cguidalch, 0, 8925, 0, 0, 0), +(@sunsreachlab, @cguidalch, 0, 13467, 3, 9000, 0), +(@sunsreachlab, @cguidalch, 0, 18256, 0, 0, 0), +(@sunsreachlab, @cguidalch, 0, 22785, 3, 9000, 0), +(@sunsreachlab, @cguidalch, 0, 22786, 3, 9000, 0), +(@sunsreachlab, @cguidalch, 0, 22791, 3, 9000, 0), +(@sunsreachlab, @cguidalch, 0, 22793, 1, 9000, 0), +(@sunsreachlab, @cguidalch, 0, 40411, 0, 0, 0); + +-- Shaani +DELETE FROM `npc_vendor` WHERE (`entry` = 25950); +DELETE FROM `game_event_npc_vendor` WHERE (`eventEntry` = @sunsreachlab) AND `guid` = @cguidjc; +INSERT INTO `game_event_npc_vendor` (`eventEntry`, `guid`, `slot`, `item`, `maxcount`, `incrtime`, `ExtendedCost`) VALUES +(@sunsreachlab, @cguidjc, 0, 32227, 0, 0, 1642), +(@sunsreachlab, @cguidjc, 0, 32228, 0, 0, 1642), +(@sunsreachlab, @cguidjc, 0, 32229, 0, 0, 1642), +(@sunsreachlab, @cguidjc, 0, 32230, 0, 0, 1642), +(@sunsreachlab, @cguidjc, 0, 32231, 0, 0, 1642), +(@sunsreachlab, @cguidjc, 0, 32249, 0, 0, 1642), +(@sunsreachlab, @cguidjc, 0, 35238, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35239, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35240, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35241, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35242, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35243, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35244, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35245, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35246, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35247, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35248, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35249, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35250, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35251, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35252, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35253, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35254, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35255, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35256, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35257, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35258, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35259, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35260, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35261, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35262, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35263, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35264, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35265, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35266, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35267, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35268, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35269, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35270, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35271, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35322, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35323, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35325, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35766, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35767, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35768, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 35769, 0, 0, 0), +(@sunsreachlab, @cguidjc, 0, 37504, 0, 0, 0); + +-- Shattered Sun Marksman + Warrior Transform Auras +-- Marksman Transform Auras +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 24938) AND (`source_type` = 0) AND (`id` IN (3, 4, 5, 6)); +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 +(24938, 0, 3, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493810, 2493813, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Random Script'), +(24938, 0, 4, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493820, 2493823, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Random Script'), +(24938, 0, 5, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Random Script'), +(24938, 0, 6, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Random Script'); +-- Bridge Marksman spawn in Harbor Phase, (hard-coded bunny target GUIDs...) +DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (-65694, -65695, -65696, -65697, -65698, -65699, -65700, -65702)) AND (`source_type` = 0) AND (`id` IN (1, 2)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(-65694, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65694, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65695, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65695, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65696, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65696, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65697, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65697, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65698, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65698, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65699, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65699, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65700, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65700, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65702, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493830, 2493833, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'), +(-65702, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2493840, 2493843, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - On Respawn - Run Script'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` BETWEEN 2493810 AND 2493813); +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 +(2493810, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44962, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - BE Male Transform Tier 1'''), +(2493811, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44921, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - BE Female Transform Tier 1'''), +(2493812, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44925, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - Draenei Male Transform Tier 1'''), +(2493813, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44929, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - Draenei Female Transform Tier 1'''); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` BETWEEN 2493820 AND 2493823); +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 +(2493820, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44918, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - BE Male Transform Tier 2'''), +(2493821, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44922, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - BE Female Transform Tier 2'''), +(2493822, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44926, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - Draenei Male Transform Tier 2'''), +(2493823, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44930, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - Draenei Female Transform Tier 2'''); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` BETWEEN 2493830 AND 2493833); +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 +(2493830, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44919, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - BE Male Transform Tier 3'''), +(2493831, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44923, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - BE Female Transform Tier 3'''), +(2493832, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44927, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - Draenei Male Transform Tier 3'''), +(2493833, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44931, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - Draenei Female Transform Tier 3'''); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` BETWEEN 2493840 AND 2493843); +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 +(2493840, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44920, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - BE Male Transform Tier 4'''), +(2493841, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44924, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - BE Female Transform Tier 4'''), +(2493842, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44928, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - Draenei Male Transform Tier 4'''), +(2493843, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44932, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Marksman - Actionlist - Cast ''Serverside - Archer - Draenei Female Transform Tier 4'''); + +-- Shattered Sun Warrior Transform Auras +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 25115; +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 25115) AND (`source_type` = 0); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `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 +(25115, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2511510, 2511513, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - On Respawn - Run Random Script'), +(25115, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2511520, 2511523, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - On Respawn - Run Random Script'), +(25115, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2511530, 2511533, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - On Respawn - Run Random Script'), +(25115, 0, 3, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 88, 2511540, 2511543, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - On Respawn - Run Random Script'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` BETWEEN 2511510 AND 2511513); +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 +(2511510, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45159, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - BE Male Transform Tier 1'''), +(2511511, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45155, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - BE Female Transform Tier 1'''), +(2511512, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45167, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - Draenei Male Transform Tier 1'''), +(2511513, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45163, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - Draenei Female Transform Tier 1'''); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` BETWEEN 2511520 AND 2511523); +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 +(2511520, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45160, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - BE Male Transform Tier 2'''), +(2511521, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45156, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - BE Female Transform Tier 2'''), +(2511522, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45168, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - Draenei Male Transform Tier 2'''), +(2511523, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45164, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - Draenei Female Transform Tier 2'''); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` BETWEEN 2511530 AND 2511533); +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 +(2511530, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45161, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - BE Male Transform Tier 3'''), +(2511531, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45157, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - BE Female Transform Tier 3'''), +(2511532, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45169, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - Draenei Male Transform Tier 3'''), +(2511533, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45165, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - Draenei Female Transform Tier 3'''); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` BETWEEN 2511540 AND 2511543); +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 +(2511540, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45162, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - BE Male Transform Tier 4'''), +(2511541, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45158, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - BE Female Transform Tier 4'''), +(2511542, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45170, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - Draenei Male Transform Tier 4'''), +(2511543, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 45166, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Sun Warrior - Actionlist - Cast ''Serverside - Warrior - Draenei Female Transform Tier 4'''); + +-- Marksman SAI conditions +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` IN (4, 5, 6, 7)) AND (`SourceEntry` = 24938) AND (`SourceId` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +-- Tier 1: !anvil && !p4 (!@sunsreachanvil && !@sunsreachpfour) +(22, 4, 24938, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +(22, 4, 24938, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is not active'), +-- Tier 2: p3 only && anvil (@sunsreachpthreeonly && @sunsreachanvil) +(22, 5, 24938, 0, 0, 12, 1, @sunsreachpthreeonly, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Three Only'' is active'), +(22, 5, 24938, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 6, 24938, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 6, 24938, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 7, 24938, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 7, 24938, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'); +-- Bridge Marksman SAI conditions +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` IN (2, 3)) AND (`SourceEntry` IN (-65694, -65695, -65696, -65697, -65698, -65699, -65700, -65702)) AND (`SourceId` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 2, -65694, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 2, -65694, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 3, -65694, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, -65694, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 2, -65695, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 2, -65695, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 3, -65695, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, -65695, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 2, -65696, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 2, -65696, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 3, -65696, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, -65696, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 2, -65697, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 2, -65697, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 3, -65697, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, -65697, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 2, -65698, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 2, -65698, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 3, -65698, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, -65698, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 2, -65699, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 2, -65699, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 3, -65699, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, -65699, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 2, -65700, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 2, -65700, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 3, -65700, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, -65700, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 2, -65702, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 2, -65702, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 3, -65702, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, -65702, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'); + +-- Warrior SAI conditions +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` IN (1, 2, 3, 4)) AND (`SourceEntry` = 25115) AND (`SourceId` = 0); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +-- Tier 1: !anvil && !p4 (!@sunsreachanvil && !@sunsreachpfour) +(22, 1, 25115, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +(22, 1, 25115, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is not active'), +-- Tier 2: p3 only && anvil (@sunsreachpthreeonly && @sunsreachanvil) +(22, 2, 25115, 0, 0, 12, 1, @sunsreachpthreeonly, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Three Only'' is active'), +(22, 2, 25115, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'), +-- Tier 3: p4 && !anvil (@sunsreachpfour && !@sunsreachanvil) +(22, 3, 25115, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 3, 25115, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 1, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is not active'), +-- Tier 4: p4 && anvil (@sunsreachpfour && @sunsreachanvil) +(22, 4, 25115, 0, 0, 12, 1, @sunsreachpfour, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Harbor'' is active'), +(22, 4, 25115, 0, 0, 12, 1, @sunsreachanvil, 0, 0, 0, 0, 0, '', 'if the event ''Sun''s Reach Reclamation Phase Anvil'' is active'); + +-- Gameobjects +-- Alchemy Lab +DELETE FROM `gameobject` WHERE (`id` = 187115) AND (`guid` IN (@guidalch)); +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`) VALUES +(@guidalch, 187115, 530, 4080, 4087, 1, 1, 12845.603516, -7011.98584, 18.592701, 5.543178, 0, 0, 0, 0, 0, 0, 0, '', 0); +-- Demonic Crystals +DELETE FROM `gameobject` WHERE `id` = 187120 AND `guid` BETWEEN @guidcrystals AND @guidcrystals+4; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `VerifiedBuild`, `Comment`) VALUES +(@guidcrystals+0, 187120, 530, 1, 1, 12685.7998046875, -6925.830078125, 39.61629867553711, 2.4260098934173584, 0.0, 0.0, 0.9366719722747804, 0.3502070009708404, 180, 0, ''), +(@guidcrystals+1, 187120, 530, 1, 1, 12707.7998046875, -6938.7900390625, 40.44039916992188, 1.815140008926392, 0.0, 0.0, 0.7880110144615173, 0.6156619787216187, 180, 0, ''), +(@guidcrystals+2, 187120, 530, 1, 1, 12665.0, -6935.72998046875, 29.555299758911133, -0.5934119820594788, 0.0, 0.0, 0.2923719882965088, -0.9563050270080566, 180, 0, ''), +(@guidcrystals+3, 187120, 530, 1, 1, 12655.7001953125, -6948.68994140625, 38.598098754882805, 2.687809944152832, 0.0, 0.0, 0.974370002746582, 0.2249509990215301, 180, 0, ''), +(@guidcrystals+4, 187120, 530, 1, 1, 12645.2001953125, -6980.97998046875, 40.50529861450195, -1.85004997253418, 0.0, 0.0, 0.0, 0.0, 180, 0, ''); + +-- Creatures +-- Portal Subphase, Shattrath City, Shattered Sun Warrior and Shattered Sun Marksman +DELETE FROM `creature` WHERE `id1` IN (25115, 24938) AND `guid` BETWEEN @cguidportalshat AND @cguidportalshat+7; +-- spawntimesecs 30-120s, 75s avg +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `MovementType`, `VerifiedBuild`, `Comment`) VALUES +(@cguidportalshat+0, 25115, 530, 1, 1, 1, -1983.31005859375, 5491.89013671875, -12.344799995422363, 0.1725849956274032, 75, 2, 0, ''), +(@cguidportalshat+1, 25115, 530, 1, 1, 1, -1866.1199951171875, 5519.31005859375, -12.344799995422363, 3.35932993888855, 75, 2, 0, ''), +(@cguidportalshat+2, 25115, 530, 1, 1, 1, -1955.0699462890625, 5432.39990234375, -12.344799995422363, 4.982600212097168, 75, 2, 0, ''), +(@cguidportalshat+3, 25115, 530, 1, 1, 1, -1753.5, 5495.75, -12.344799995422363, 3.782819986343384, 75, 2, 0, ''), +(@cguidportalshat+4, 24938, 530, 1, 1, 1, -1941.18994140625, 5486.89990234375, -12.344799995422363, 0.5934119820594788, 75, 2, 0, ''), +(@cguidportalshat+5, 24938, 530, 1, 1, 1, -1958.1099853515625, 5418.16015625, -12.344799995422363, 5.061450004577637, 75, 2, 0, ''), +(@cguidportalshat+6, 24938, 530, 1, 1, 1, -1771.47998046875, 5424.3798828125, -12.344799995422363, 1.7976900339126587, 75, 2, 0, ''), +(@cguidportalshat+7, 24938, 530, 1, 1, 1, -1799.050048828125, 5549.31982421875, -12.344799995422363, 5.026549816131592, 75, 2, 0, ''); + +DELETE FROM `waypoint_data` WHERE `id` = (@cguidportalshat+0)*10; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`) VALUES +((@cguidportalshat+0)*10, 1, -1983.33, 5492.03, -12.4281, 0.0, 250, 1, 0), +((@cguidportalshat+0)*10, 2, -1941.97, 5499.10, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+0)*10, 3, -1905.15, 5501.05, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+0)*10, 4, -1875.16, 5471.33, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+0)*10, 5, -1853.28, 5475.17, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+0)*10, 6, -1847.65, 5493.82, -12.4545, 0.0, 0, 1, 0), +((@cguidportalshat+0)*10, 7, -1841.89, 5499.54, -12.4281, 1.23, 5000, 1, @cguidportalshat*10); + +DELETE FROM `waypoint_data` WHERE `id` = (@cguidportalshat+1)*10; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`) VALUES +((@cguidportalshat+1)*10, 1, -1866.18, 5519.39, -12.4281, 0.0, 250, 1, 0), +((@cguidportalshat+1)*10, 2, -1889.29, 5514.19, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+1)*10, 3, -1897.09, 5497.14, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+1)*10, 4, -1876.34, 5471.40, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+1)*10, 5, -1856.19, 5471.47, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+1)*10, 6, -1845.27, 5496.98, -12.4569, 0.0, 0, 1, 0), +((@cguidportalshat+1)*10, 7, -1840.91, 5499.92, -12.4280, 1.23, 5000, 1, @cguidportalshat*10); + +DELETE FROM `waypoint_data` WHERE `id` = (@cguidportalshat+2)*10; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`) VALUES +((@cguidportalshat+2)*10, 1, -1954.96, 5432.12, -12.4281, 0.0, 250, 1, 0), +((@cguidportalshat+2)*10, 2, -1947.68, 5405.70, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+2)*10, 3, -1928.35, 5396.70, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+2)*10, 4, -1892.14, 5430.80, -12.4282, 0.0, 0, 1, 0), +((@cguidportalshat+2)*10, 5, -1865.26, 5463.53, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+2)*10, 6, -1841.39, 5493.11, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+2)*10, 7, -1840.05, 5499.26, -12.4280, 1.23, 5000, 1, @cguidportalshat*10); + +DELETE FROM `waypoint_data` WHERE `id` = (@cguidportalshat+3)*10; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`) VALUES +((@cguidportalshat+3)*10, 1, -1753.56, 5495.54, -12.4281, 0.0, 250, 1, 0), +((@cguidportalshat+3)*10, 2, -1791.01, 5467.76, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+3)*10, 3, -1825.64, 5453.07, -12.4282, 0.0, 0, 1, 0), +((@cguidportalshat+3)*10, 4, -1844.89, 5473.19, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+3)*10, 5, -1840.24, 5498.82, -12.4281, 1.23, 5000, 1, @cguidportalshat*10); + +DELETE FROM `waypoint_data` WHERE `id` = (@cguidportalshat+4)*10; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`) VALUES +((@cguidportalshat+4)*10, 1, -1941.15, 5487.12, -12.42811, 0.0, 250, 1, 0), +((@cguidportalshat+4)*10, 2, -1914.21, 5504.99, -12.42810, 0.0, 0, 1, 0), +((@cguidportalshat+4)*10, 3, -1896.75, 5495.92, -12.42810, 0.0, 0, 1, 0), +((@cguidportalshat+4)*10, 4, -1879.80, 5472.28, -12.42810, 0.0, 0, 1, 0), +((@cguidportalshat+4)*10, 5, -1853.05, 5469.34, -12.42811, 0.0, 0, 1, 0), +((@cguidportalshat+4)*10, 6, -1839.51, 5498.56, -12.42811, 0.0, 0, 1, 0), +((@cguidportalshat+4)*10, 7, -1839.51, 5498.56, -12.42810, 1.23, 5000, 1, @cguidportalshat*10); + +DELETE FROM `waypoint_data` WHERE `id` = (@cguidportalshat+5)*10; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`) VALUES +((@cguidportalshat+5)*10, 1, -1958.15, 5418.13, -12.4281, 0.0, 250, 1, 0), +((@cguidportalshat+5)*10, 2, -1937.75, 5396.30, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+5)*10, 3, -1903.02, 5412.98, -12.4282, 0.0, 0, 1, 0), +((@cguidportalshat+5)*10, 4, -1885.32, 5439.74, -12.4281,0.0, 0, 1, 0), +((@cguidportalshat+5)*10, 5, -1856.43, 5471.17, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+5)*10, 6, -1848.19, 5493.08, -12.4475, 0.0, 0, 1, 0), +((@cguidportalshat+5)*10, 7, -1841.45, 5499.37, -12.4281, 1.23, 5000, 1, @cguidportalshat*10); + +DELETE FROM `waypoint_data` WHERE `id` = (@cguidportalshat+6)*10; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`) VALUES +((@cguidportalshat+6)*10, 1, -1771.40, 5424.44, -12.4281, 0.0, 250, 1, 0), +((@cguidportalshat+6)*10, 2, -1780.13, 5458.50, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+6)*10, 3, -1802.26, 5461.31, -12.4281, 0.0, 0, 1, 0), +((@cguidportalshat+6)*10, 4, -1826.47, 5454.01, -12.4283, 0.0, 0, 1, 0), +((@cguidportalshat+6)*10, 5, -1844.75, 5471.00, -12.4282, 0.0, 0, 1, 0), +((@cguidportalshat+6)*10, 6, -1840.07, 5498.43, -12.4281, 1.23, 5000, 1, @cguidportalshat*10); + +DELETE FROM `waypoint_data` WHERE `id` = (@cguidportalshat+7)*10; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`) VALUES +((@cguidportalshat+7)*10, 1, -1799.13, 5549.21,0 -12.42810, 0.0, 250, 1, 0), +((@cguidportalshat+7)*10, 2, -1786.30, 5503.25,0 -12.42810, 0.0, 0, 1, 0), +((@cguidportalshat+7)*10, 3, -1788.18, 5469.74,0 -12.42811, 0.0, 0, 1, 0), +((@cguidportalshat+7)*10, 4, -1822.23, 5450.82,0 -12.42813, 0.0, 0, 1, 0), +((@cguidportalshat+7)*10, 5, -1844.87, 5471.94,0 -12.42820, 0.0, 0, 1, 0), +((@cguidportalshat+7)*10, 6, -1840.02, 5499.12,0 -12.42810, 1.23, 5000, 1, @cguidportalshat*10); + +DELETE FROM `waypoint_scripts` WHERE `id` = @cguidportalshat*10 AND `guid` BETWEEN (@cguidportalshat*10) AND (@cguidportalshat*10)+2; +INSERT INTO `waypoint_scripts` (`id`, `delay`, `command`, `datalong`, `datalong2`, `dataint`, `x`, `y`, `z`, `o`, `guid`) VALUES +(@cguidportalshat*10, 0, 15, 34427, 1, 0, 0.0, 0.0, 0.0, 0.0, (@cguidportalshat*10)+0), +(@cguidportalshat*10, 0, 1, 66, 0, 0, 0.0, 0.0, 0.0, 0.0, (@cguidportalshat*10)+1), +(@cguidportalshat*10, 0, 18, 1000, 0, 0, 0.0, 0.0, 0.0, 0.0, (@cguidportalshat*10)+2); + +-- Set `path_id` for the above creatures +DELETE FROM `creature_addon` WHERE `guid` BETWEEN @cguidportalshat AND @cguidportalshat+7; +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES +(@cguidportalshat+0, (@cguidportalshat+0)*10, 0, 0, 0, 45, 0, NULL), +(@cguidportalshat+1, (@cguidportalshat+1)*10, 0, 0, 0, 45, 0, NULL), +(@cguidportalshat+2, (@cguidportalshat+2)*10, 0, 0, 0, 45, 0, NULL), +(@cguidportalshat+3, (@cguidportalshat+3)*10, 0, 0, 0, 45, 0, NULL), +(@cguidportalshat+4, (@cguidportalshat+4)*10, 0, 0, 0, 45, 0, NULL), +(@cguidportalshat+5, (@cguidportalshat+5)*10, 0, 0, 0, 45, 0, NULL), +(@cguidportalshat+6, (@cguidportalshat+6)*10, 0, 0, 0, 45, 0, NULL), +(@cguidportalshat+7, (@cguidportalshat+7)*10, 0, 0, 0, 45, 0, NULL); + +-- Portal Subphase, Isle of Quel'Danas +DELETE FROM `creature` WHERE `id1` = 24936 AND `guid` BETWEEN @cguidportalisle AND @cguidportalisle+9; +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `MovementType`, `VerifiedBuild`, `Comment`) VALUES +(@cguidportalisle+0, 24936, 530, 1, 1, -1842.9300537109373, 5509.740234375, -12.184900283813477, 5.039340019226073, 300, 0, 0, ''), +(@cguidportalisle+1, 24936, 530, 1, 1, -1841.0500488281248, 5510.43994140625, -10.386300086975098, 4.83420991897583, 300, 0, 0, ''), +(@cguidportalisle+2, 24936, 530, 1, 1, -1833.4599609375, 5507.990234375, -11.58769989013672, 3.994129896163941, 300, 0, 0, ''), +(@cguidportalisle+3, 24936, 530, 1, 1, -1833.1500244140625, 5507.06005859375, -12.136099815368652, 3.902909994125366, 300, 0, 0, ''), +(@cguidportalisle+4, 24936, 530, 1, 1, -1839.1700439453125, 5510.02978515625, -12.219599723815918, 4.6390299797058105, 300, 0, 0, ''), +(@cguidportalisle+5, 24936, 530, 1, 1, -1835.4100341796875, 5507.0400390625, -12.114999771118164, 4.103789806365967, 300, 0, 0, ''), +(@cguidportalisle+6, 24936, 530, 1, 1, -1841.6999511718752, 5510.3798828125, -11.60849952697754, 4.900139808654785, 300, 0, 0, ''), +(@cguidportalisle+7, 24936, 530, 1, 1, -1834.4000244140625, 5507.919921875, -10.934700012207031, 4.06702995300293, 300, 0, 0, ''), +(@cguidportalisle+8, 24936, 530, 1, 1, -1840.27001953125, 5509.81005859375, -11.740400314331056, 4.758059978485107, 300, 0, 0, ''), +(@cguidportalisle+9, 24936, 530, 1, 1, -1832.4599609375, 5506.02001953125, -12.198599815368652, 3.76786994934082, 300, 0, 0, ''); + +-- Dawnblade Blood Knight +DELETE FROM `creature` WHERE `id1` = 24976 AND `guid` BETWEEN @cguidbloodknights AND @cguidbloodknights+22; +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`, `VerifiedBuild`, `Comment`) VALUES +(@cguidbloodknights+00, 24976, 530, 1, 1, 1, 12873.400390625, -6957.669921875, 3.931679964065552, 1.5707999467849731, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+01, 24976, 530, 1, 1, 1, 12874.599609375, -6958.58984375, 3.9531400203704834, 0.5235990285873413, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+02, 24976, 530, 1, 1, 1, 12845.599609375, -7014.43017578125, 71.28970336914062, 0.6806780099868774, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+03, 24976, 530, 1, 1, 1, 12826.599609375, -7030.5498046875, 71.57510375976561, 1.9024100303649905, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+04, 24976, 530, 1, 1, 1, 12833.400390625, -6993.60986328125, 71.206298828125, 1.7278800010681152, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+05, 24976, 530, 1, 1, 1, 12817.7998046875, -6999.2900390625, 71.34230041503906, -2.7931900024414062, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+06, 24976, 530, 1, 1, 1, 12850.7998046875, -7035.56005859375, 47.862499237060554, 2.932149887084961, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+07, 24976, 530, 1, 1, 1, 12852.2998046875, -7051.7099609375, 19.04030036926269, 2.0726099014282227, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+08, 24976, 530, 1, 1, 1, 12846.599609375, -7008.5400390625, 18.5935001373291, 3.0896999835968018, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+09, 24976, 530, 1, 1, 1, 12811.5, -6989.0400390625, 18.721200942993164, 2.6005399227142334, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+10, 24976, 530, 1, 1, 1, 12801.7001953125, -6997.02978515625, 18.71999931335449, 2.007129907608032, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+11, 24976, 530, 1, 1, 1, 12869.5, -7019.9599609375, 3.2795801162719727, 5.4698500633239755, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+12, 24976, 530, 1, 1, 1, 12871.2998046875, -7022.18994140625, 3.2777199745178223, 5.5664801597595215, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+13, 24976, 530, 1, 1, 1, 12872.0, -7018.4599609375, 3.274280071258545, 6.139150142669679, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+14, 24976, 530, 1, 1, 1, 12837.900390625, -7049.5400390625, 3.3980100154876713, 5.550149917602539, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+15, 24976, 530, 1, 1, 1, 12748.5, -7066.2998046875, 7.478529930114745, 6.09119987487793, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+16, 24976, 530, 1, 1, 1, 12887.2998046875, -6924.3701171875, 3.8923499584198, 0.1548810005187988, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+17, 24976, 530, 1, 1, 1, 12869.5, -6986.85009765625, 3.2696700096130367, 1.5028200149536133, 300, 0.0, 0, 0, ''), +(@cguidbloodknights+18, 24976, 530, 1, 1, 1, 12756.2001953125, -7139.580078125, 3.462500095367432, 2.255970001220703, 300, 3.0, 1, 0, ''), +(@cguidbloodknights+19, 24976, 530, 1, 1, 1, 12787.099609375, -7032.419921875, 11.81439971923828, 0.1741870045661926, 300, 5.0, 1, 0, ''), +(@cguidbloodknights+20, 24976, 530, 1, 1, 1, 12736.7998046875, -6890.7998046875, 12.408699989318848, 5.4163498878479, 300, 5.0, 1, 0, ''), +(@cguidbloodknights+21, 24976, 530, 1, 1, 1, 12755.900390625, -6937.7099609375, 12.485600471496582, 3.4923501014709477, 300, 5.0, 1, 0, ''), +(@cguidbloodknights+22, 24976, 530, 1, 1, 1, 12821.900390625, -6919.1298828125, 11.729999542236328, 1.271530032157898, 300, 5.0, 1, 0, ''); + +-- Dawnblade Summoner, Dawnblade Marksman +DELETE FROM `creature` WHERE `id1` IN (24978, 24979) AND `guid` BETWEEN @cguidsummonermarksman AND @cguidsummonermarksman+60; +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`, `VerifiedBuild`, `Comment`) VALUES +(@cguidsummonermarksman+00, 24978, 530, 1, 1, 1, 12798.2998046875, -6996.10009765625, 47.56069946289063, 1.2217299938201904, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+01, 24978, 530, 1, 1, 1, 12820.2001953125, -7040.509765625, 18.676000595092773, 2.164210081100464, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+02, 24978, 530, 1, 1, 1, 12845.7998046875, -7007.8701171875, 47.51129913330078, 2.909019947052002, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+03, 24978, 530, 1, 1, 1, 12858.400390625, -7044.52978515625, 19.007099151611328, 1.9688700437545776, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+04, 24978, 530, 1, 1, 1, 12834.599609375, -6994.66015625, 18.762199401855472, 3.525520086288452, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+05, 24978, 530, 1, 1, 1, 12810.5, -7055.56005859375, 3.0357499122619633, 5.900400161743164, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+06, 24978, 530, 1, 1, 1, 12834.400390625, -7066.47021484375, 3.369379997253418, 1.3788100481033323, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+07, 24978, 530, 1, 1, 1, 12853.900390625, -6976.75, 5.031179904937744, 5.301620006561279, 300, 3.0, 1, 0, ''), +(@cguidsummonermarksman+08, 24978, 530, 1, 1, 1, 12754.2001953125, -7103.52978515625, 6.988080024719238, 1.578089952468872, 300, 3.0, 1, 0, ''), +(@cguidsummonermarksman+09, 24978, 530, 1, 1, 1, 12757.400390625, -7029.89990234375, 9.374119758605955, 5.8371901512146, 300, 5.0, 1, 0, ''), +(@cguidsummonermarksman+10, 24978, 530, 1, 1, 1, 12745.099609375, -6984.7001953125, 19.198400497436523, 2.3560900688171387, 300, 3.0, 1, 0, ''), +(@cguidsummonermarksman+11, 24978, 530, 1, 1, 1, 12778.2998046875, -7005.10986328125, 13.887200355529783, 1.0297399759292605, 300, 3.0, 1, 0, ''), +(@cguidsummonermarksman+12, 24978, 530, 1, 1, 1, 12760.099609375, -6993.27978515625, 11.464699745178224, 0.3670099973678589, 300, 3.0, 1, 0, ''), +(@cguidsummonermarksman+13, 24978, 530, 1, 1, 1, 12764.099609375, -6920.009765625, 12.275699615478516, -2.9297499656677246, 300, 3.0, 1, 0, ''), +(@cguidsummonermarksman+14, 24978, 530, 1, 1, 1, 12837.7998046875, -6943.52978515625, 7.168889999389648, 1.9164899587631223, 300, 3.0, 1, 0, ''), +(@cguidsummonermarksman+15, 24978, 530, 1, 1, 1, 12881.900390625, -6932.259765625, 3.9561200141906734, 1.015720009803772, 300, 3.0, 1, 0, ''), +(@cguidsummonermarksman+33, 24979, 530, 1, 1, 1, 12780.2001953125, -7133.77001953125, 9.23165035247803, 1.81046998500824, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+34, 24979, 530, 1, 1, 1, 12806.2998046875, -7089.10009765625, 8.221309661865234, -1.0778800249099731, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+35, 24979, 530, 1, 1, 1, 12848.7001953125, -7128.97998046875, 6.870110034942627, 2.702569961547852, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+36, 24979, 530, 1, 1, 1, 12828.2998046875, -7118.52001953125, 5.363649845123291, 4.1189799308776855, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+37, 24979, 530, 1, 1, 1, 12793.2998046875, -7121.31005859375, 5.416520118713379, 5.479209899902344, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+38, 24979, 530, 1, 1, 1, 12800.400390625, -6980.72021484375, 47.661598205566406, 5.375609874725343, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+39, 24979, 530, 1, 1, 1, 12843.5, -7041.06005859375, 47.91299819946289, 0.1919859945774078, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+40, 24979, 530, 1, 1, 1, 12809.2998046875, -7004.2998046875, 70.59559631347656, 4.712389945983888, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+41, 24979, 530, 1, 1, 1, 12841.7998046875, -7001.31982421875, 71.206298828125, 0.5759590268135071, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+42, 24979, 530, 1, 1, 1, 12879.900390625, -6997.669921875, 3.0978500843048096, 0.0349065996706485, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+43, 24979, 530, 1, 1, 1, 12877.7998046875, -7028.16015625, 3.275310039520264, 5.6374101638793945, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+44, 24979, 530, 1, 1, 1, 12807.2998046875, -7028.919921875, 18.69499969482422, 0.8552110195159912, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+45, 24979, 530, 1, 1, 1, 12787.099609375, -6955.93994140625, 13.763099670410156, 2.007129907608032, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+46, 24979, 530, 1, 1, 1, 12898.599609375, -6956.919921875, 3.3791999816894527, 0.7504919767379761, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+47, 24979, 530, 1, 1, 1, 12885.7001953125, -6938.580078125, 3.899499893188477, 0.2443459928035736, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+48, 24979, 530, 1, 1, 1, 12668.5, -6860.10009765625, 13.115699768066406, 2.932149887084961, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+49, 24979, 530, 1, 1, 1, 12657.400390625, -6820.08984375, 12.552800178527832, 0.4712390005588531, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+50, 24979, 530, 1, 1, 1, 12646.400390625, -6830.10986328125, 12.41569995880127, 5.113810062408447, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+51, 24979, 530, 1, 1, 1, 12689.7998046875, -6848.2001953125, 13.33329963684082, 0.2967059910297394, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+52, 24979, 530, 1, 1, 1, 12703.2001953125, -6868.35986328125, 12.553899765014648, 5.3581600189208975, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+53, 24979, 530, 1, 1, 1, 12692.7001953125, -6878.35009765625, 12.4197998046875, 5.550149917602539, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+54, 24979, 530, 1, 1, 1, 12794.900390625, -7012.02001953125, 18.750099182128903, 2.268929958343506, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+55, 24979, 530, 1, 1, 1, 12826.099609375, -6984.009765625, 18.64080047607422, 1.924110054969788, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+56, 24979, 530, 1, 1, 1, 12765.2998046875, -6897.490234375, 13.382100105285645, 3.7815499305725098, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+57, 24979, 530, 1, 1, 1, 12769.2001953125, -6902.72998046875, 13.392399787902832, -2.02396011352539, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+58, 24979, 530, 1, 1, 1, 12775.7998046875, -6970.490234375, 14.151200294494627, 2.1118500232696533, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+59, 24979, 530, 1, 1, 1, 12852.599609375, -6911.85009765625, 8.594349861145021, 0.2445050030946731, 300, 0.0, 0, 0, ''), +(@cguidsummonermarksman+60, 24979, 530, 1, 1, 1, 12865.099609375, -7039.6298828125, 3.2777299880981445, 3.875829935073853, 300, 0.0, 0, 0, ''); + +-- Irespeaker +DELETE FROM `creature` WHERE `id1` = 24999 AND `guid` BETWEEN @cguidirespeaker AND @cguidirespeaker+5; +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`, `VerifiedBuild`, `Comment`) VALUES +(@cguidirespeaker+0, 24999, 530, 1, 1, 12702.7001953125, -6942.97021484375, 36.3202018737793, 0.4014259874820709, 300, 0.0, 0, 0, ''), +(@cguidirespeaker+1, 24999, 530, 1, 1, 12684.599609375, -6933.43994140625, 36.32070159912109, 1.6231600046157837, 300, 0.0, 0, 0, ''), +(@cguidirespeaker+2, 24999, 530, 1, 1, 12655.400390625, -6976.35986328125, 36.316699981689446, 3.4033899307250977, 300, 0.0, 0, 0, ''), +(@cguidirespeaker+3, 24999, 530, 1, 1, 12660.0, -6950.81982421875, 36.32229995727539, 3.0543301105499268, 300, 0.0, 0, 0, ''), +(@cguidirespeaker+4, 24999, 530, 1, 1, 12670.7001953125, -6940.8798828125, 23.57360076904297, 1.745329976081848, 300, 0.0, 0, 0, ''), +(@cguidirespeaker+5, 24999, 530, 1, 1, 12684.0, -6957.1201171875, 15.554200172424316, 0.63127201795578, 300, 0.0, 0, 0, ''); + +-- Abyssal Flamewalker, Unleashed Hellion +DELETE FROM `creature` WHERE `id1` IN (25001, 25002) AND `guid` BETWEEN @cguidflamewalkerhellion AND @cguidflamewalkerhellion+30; +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`, `VerifiedBuild`, `Comment`) VALUES +(@cguidflamewalkerhellion+00, 25001, 530, 1, 1, 12692.0, -7107.39990234375, 19.421600341796875, 6.03203010559082, 300, 8.0, 1, 0, ''), +(@cguidflamewalkerhellion+01, 25001, 530, 1, 1, 12663.7001953125, -7082.509765625, 19.48740005493164, 4.04925012588501, 300, 8.0, 1, 0, ''), +(@cguidflamewalkerhellion+02, 25001, 530, 1, 1, 12641.0, -7043.39013671875, 19.326499938964844, 0.1822019964456558, 300, 8.0, 1, 0, ''), +(@cguidflamewalkerhellion+03, 25001, 530, 1, 1, 12728.2001953125, -6945.3798828125, 14.332799911499023, 1.623579978942871, 300, 0.0, 2, 0, ''), +(@cguidflamewalkerhellion+04, 25001, 530, 1, 1, 12657.0, -6979.91015625, 14.657400131225586, 4.1078500747680655, 300, 8.0, 1, 0, ''), +(@cguidflamewalkerhellion+05, 25001, 530, 1, 1, 12703.900390625, -6920.830078125, 13.740599632263184, 0.8711439967155457, 300, 8.0, 1, 0, ''), +(@cguidflamewalkerhellion+06, 25001, 530, 1, 1, 12696.0, -7010.14013671875, 21.250799179077152, 1.210919976234436, 300, 8.0, 1, 0, ''), +(@cguidflamewalkerhellion+07, 25001, 530, 1, 1, 12606.099609375, -6987.64990234375, 17.03179931640625, 5.598269939422607, 300, 8.0, 1, 0, ''), +(@cguidflamewalkerhellion+08, 25001, 530, 1, 1, 12636.7001953125, -7014.68017578125, 20.319900512695312, 2.3435299396514893, 300, 8.0, 1, 0, ''), +(@cguidflamewalkerhellion+20, 25002, 530, 1, 1, 12702.0, -6950.81005859375, 15.645500183105469, 0.663224995136261, 300, 0.0, 0, 0, ''), +(@cguidflamewalkerhellion+21, 25002, 530, 1, 1, 12696.2001953125, -6942.97998046875, 15.641799926757812, 0.5235990285873413, 300, 0.0, 0, 0, ''), +(@cguidflamewalkerhellion+22, 25002, 530, 1, 1, 12701.099609375, -6983.31005859375, 25.60110092163086, 6.117310047149657, 300, 0.0, 0, 0, ''), +(@cguidflamewalkerhellion+23, 25002, 530, 1, 1, 12683.2001953125, -6957.72021484375, 36.25310134887695, 3.7768199443817134, 300, 0.0, 0, 0, ''), +(@cguidflamewalkerhellion+24, 25002, 530, 1, 1, 12673.099609375, -6943.68994140625, 36.338600158691406, 5.46288013458252, 300, 0.0, 0, 0, ''), +(@cguidflamewalkerhellion+25, 25002, 530, 1, 1, 12704.0, -6972.18017578125, 36.23080062866211, 0.3528819978237152, 300, 0.0, 0, 0, ''), +(@cguidflamewalkerhellion+26, 25002, 530, 1, 1, 12689.7998046875, -6983.56005859375, 15.571100234985352, 5.247819900512695, 300, 3.0, 1, 0, ''), +(@cguidflamewalkerhellion+27, 25002, 530, 1, 1, 12657.7001953125, -7019.89990234375, 21.81920051574707, 2.5725700855255127, 300, 3.0, 1, 0, ''), +(@cguidflamewalkerhellion+28, 25002, 530, 1, 1, 12612.900390625, -7022.419921875, 18.695499420166016, 1.23540997505188, 300, 5.0, 1, 0, ''), +(@cguidflamewalkerhellion+30, 25002, 530, 1, 1, 12652.2998046875, -7074.39013671875, 18.13419914245605, 5.452239990234375, 300, 5.0, 1, 0, ''); + +-- Invisible Stalker Floating -> Fel Crystal Spell target +DELETE FROM `creature` WHERE `id1` = 25953 AND `guid` BETWEEN @cguidfelcrystalspelltarget AND @cguidfelcrystalspelltarget+4; +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`, `VerifiedBuild`, `Comment`) VALUES +(@cguidfelcrystalspelltarget+0, 25953, 530, 1, 1, 12707.900390625, -6938.85009765625, 39.885299682617195, 6.24828004837036, 300, 0.0, 0, 0, ''), +(@cguidfelcrystalspelltarget+1, 25953, 530, 1, 1, 12685.900390625, -6925.9501953125, 39.12950134277344, 3.4906599521636963, 300, 0.0, 0, 0, ''), +(@cguidfelcrystalspelltarget+2, 25953, 530, 1, 1, 12665.0, -6935.7099609375, 28.988800048828125, 5.5326900482177725, 300, 0.0, 0, 0, ''), +(@cguidfelcrystalspelltarget+3, 25953, 530, 1, 1, 12655.599609375, -6948.64990234375, 38.00170135498047, 1.518440008163452, 300, 0.0, 0, 0, ''), +(@cguidfelcrystalspelltarget+4, 25953, 530, 1, 1, 12645.099609375, -6981.1298828125, 39.86289978027344, 2.2863800525665283, 300, 0.0, 0, 0, ''); + +-- Abyssal Flamewalker +DELETE FROM `creature_addon` WHERE (`guid` = 5300476); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES +(5300476, 53004760, 0, 0, 1, 0, 0, ''); +DELETE FROM `waypoint_data` WHERE `id` = 53004760; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(53004760, 1, 12728.2, -6945.38, 14.3328, NULL, 0, 0, 0, 100, 0), +(53004760, 2, 12728.0, -6963.33, 17.2544, NULL, 0, 0, 0, 100, 0), +(53004760, 3, 12723.1, -6977.58, 18.9559, NULL, 0, 0, 0, 100, 0), +(53004760, 4, 12728.0, -6963.33, 17.2544, NULL, 0, 0, 0, 100, 0); + +-- Fix Dawnblade Marksman not showing bow +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 24979) AND (`source_type` = 0) AND (`id` IN (2)); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(24979, 0, 2, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 40, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dawnblade Marksman - On Reset - Set Sheath Ranged'); + +-- Do not remove transform auras on evade +-- SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT = 0x02000000, // TITLE Aura stays after combat DESCRIPTION Aura will not be removed when the unit leaves combat +UPDATE `spell_dbc` SET `AttributesEx`=`AttributesEx`|(0x02000000) WHERE `ID` IN (44918, 44919, 44920, 44921, 44922, 44923, 44924, 44925, 44926, 44927, 44928, 44929, 44930, 44931, 44932, 44962, 45155, 45156, 45157, 45158, 45159, 45160, 45161, 45162, 45163, 45164, 45165, 45166, 45167, 45168, 45169, 45170); + +-- Close First, Second, Third Gate +UPDATE `gameobject` SET `state` = 1 WHERE `id` IN (187766, 187765, 187764) AND `guid` IN (50441, 50440, 50439); diff --git a/data/sql/updates/db_world/2025_01_31_01.sql b/data/sql/updates/db_world/2025_01_31_01.sql new file mode 100644 index 000000000..40a0a40cd --- /dev/null +++ b/data/sql/updates/db_world/2025_01_31_01.sql @@ -0,0 +1,11 @@ +-- DB update 2025_01_31_00 -> 2025_01_31_01 +-- Add pure energy immune script for Vex +UPDATE `creature_template` SET `ScriptName` = 'npc_pure_energy' WHERE (`entry` = 24745); + +-- AOE_IMMUNE Flag for pure energy +UPDATE `creature_template` SET `flags_extra` = (`flags_extra` | 4194304) WHERE (`entry` = 24745); + +-- Vexallus (Entry: 24744) Overload Emote with broadcasttextid 77866 +DELETE FROM `creature_text` WHERE `CreatureID` = 24744 AND `GroupID` = 5 AND `ID` = 0; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(24744, 5, 0, 'Vexallus overloads!', 41, 0, 100, 0, 0, 0, 23781, 0, 'Vexallus - EMOTE_OVERLOAD'); diff --git a/data/sql/updates/db_world/2025_02_01_00.sql b/data/sql/updates/db_world/2025_02_01_00.sql new file mode 100644 index 000000000..ce5c7b48f --- /dev/null +++ b/data/sql/updates/db_world/2025_02_01_00.sql @@ -0,0 +1,8 @@ +-- DB update 2025_01_31_01 -> 2025_02_01_00 +-- +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24761); +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 +(24761, 0, 0, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44406, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Brightscale Wyrm - On Just Died - Cast \'Energy Infusion\''); + +DELETE FROM `spell_custom_attr` WHERE `spell_id`= 44406; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (44406, 4194304); diff --git a/data/sql/updates/db_world/2025_02_01_01.sql b/data/sql/updates/db_world/2025_02_01_01.sql new file mode 100644 index 000000000..2333799ee --- /dev/null +++ b/data/sql/updates/db_world/2025_02_01_01.sql @@ -0,0 +1,3 @@ +-- DB update 2025_02_01_00 -> 2025_02_01_01 +-- +UPDATE `creature_template` SET `ScriptName` = '' WHERE (`entry` = 24745); diff --git a/data/sql/updates/db_world/2025_02_01_02.sql b/data/sql/updates/db_world/2025_02_01_02.sql new file mode 100644 index 000000000..f72daf656 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_01_02.sql @@ -0,0 +1,3 @@ +-- DB update 2025_02_01_01 -> 2025_02_01_02 +-- +DELETE FROM `acore_string` WHERE `entry` = 6617; diff --git a/data/sql/updates/db_world/2025_02_03_00.sql b/data/sql/updates/db_world/2025_02_03_00.sql new file mode 100644 index 000000000..cfce0823e --- /dev/null +++ b/data/sql/updates/db_world/2025_02_03_00.sql @@ -0,0 +1,16 @@ +-- DB update 2025_02_01_02 -> 2025_02_03_00 +-- Add Russian locale for QuestID: 4641 +DELETE FROM `quest_offer_reward_locale` WHERE `ID` = 4641 AND `locale` = 'ruRU'; +INSERT INTO `quest_offer_reward_locale` (`ID`, `locale`, `RewardText`, `VerifiedBuild`) VALUES (4641,'ruRU','Очередной рекрут Калтунка?$B$BВидно, плохи наши дела, если у нас нет никого получше. Ну, ничего. К тому времени, как мы решим, что тебе пора покинуть долину, из тебя $c получится бравый воитель Орды!',0); + +-- Add Russian locale for QuestID: 788 +DELETE FROM `quest_offer_reward_locale` WHERE `ID` = 788 AND `locale` = 'ruRU'; +INSERT INTO `quest_offer_reward_locale` (`ID`, `locale`, `RewardText`, `VerifiedBuild`) VALUES (788,'ruRU','Ну что ж, $N, неплохо. Но не задирай носа: грядут бои с куда более серьезными врагами.$b$bОднако ты показал себя достойным бойцом. В следующем испытании тебе придется встретиться с более опасным противником, так что дополнительная защита не помешает.',0); + +-- Fix Russian locale for QuestID: 783 +DELETE FROM `quest_template_locale` WHERE `ID` = 783 AND `locale` = 'ruRU'; +INSERT INTO `quest_template_locale` (`ID`, `locale`, `Title`, `Details`, `Objectives`, `VerifiedBuild`) VALUES (783, 'ruRU', 'Внутренняя угроза', 'Надеюсь, ты $gготов:готова; к подвигам, |3-6($c), поскольку для тебя есть дело здесь, в Североземье.$B$BИ я имею в виду не мирные сельские заботы.$B$BСтража Штормграда с трудом поддерживает здесь мир: слишком многие из нас находятся в дальних краях, а тревожных вестей меньше не становится. И потому мы надеемся на помощь всех, кто готов защитить свой дом и своих близких.$B$BЕсли ты $gготов:готова; откликнуться на призыв, то поговори с моим командиром, маршалом Макбрайдом. Он здесь, в аббатстве у меня за спиной.', 'Поговорите с маршалом Макбрайдом.', 0); + +-- Fix Russian locale for QuestID: 792 +DELETE FROM `quest_template_locale` WHERE `ID` = 792 AND `locale` = 'ruRU'; +INSERT INTO `quest_template_locale` (`ID`, `locale`, `Title`, `Details`, `Objectives`, `VerifiedBuild`) VALUES (792, 'ruRU', 'Злобные фамильяры', 'Что ж, |3-6($c), надеюсь, у нас ты многому научишься.$b$bМеня послали сюда, чтобы я стала твоей наставницей, но оказывается, здесь не все ладно!$b$bВ долине Испытаний обосновался клан Пылающего Клинка. Эти твари скрываются в пещере на северо-востоке, и их злобные фамильяры выбираются оттуда и сеют хаос.$b$bИтак, вот твое первое задание в борьбе с Пылающим Клинком: перебей их столько, сколько сумеешь, и, если выживешь, возвращайся ко мне.', 'Убейте 8 злобных фамильяров и вернитесь к Зурите Востроглазой, которая ждет вас у Логова.', 0); diff --git a/data/sql/updates/db_world/2025_02_03_01.sql b/data/sql/updates/db_world/2025_02_03_01.sql new file mode 100644 index 000000000..e3f423643 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_03_01.sql @@ -0,0 +1,3 @@ +-- DB update 2025_02_03_00 -> 2025_02_03_01 +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 25485) AND (`source_type` = 0) AND (`id` IN (0)); diff --git a/data/sql/updates/db_world/2025_02_04_00.sql b/data/sql/updates/db_world/2025_02_04_00.sql new file mode 100644 index 000000000..be4a13744 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_04_00.sql @@ -0,0 +1,7 @@ +-- DB update 2025_02_03_01 -> 2025_02_04_00 +-- +-- Set questId on WP start +UPDATE `smart_scripts` SET `action_param4` = 5203 WHERE (`entryorguid` = 1101600) AND (`source_type` = 9) AND (`id` = 9); +-- Delete area explored action +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 11016) AND (`source_type` = 0) AND (`id` = 38); +UPDATE `smart_scripts` SET `link`=39 WHERE (`entryorguid` = 11016) AND (`source_type` = 0) AND (`id` = 37); diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index a6dd8742d..e55caf9a5 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -4304,6 +4304,19 @@ Event.Announce = 0 # ################################################################################################### +################################################################################################### +# WORLD STATE +# +# Sunsreach.CounterMax +# Description: Counter value to be reached to transition phases +# during the Sun's Reach Reclamation event. +# Default: 10000 + +Sunsreach.CounterMax = 10000 + +# +################################################################################################### + ################################################################################################### # AUCTION HOUSE # diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index e5d77ca4f..d5a78dee0 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2696,7 +2696,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_PLAYER_TALK: { - char const* text = sObjectMgr->GetAcoreString(e.action.playerTalk.textId, DEFAULT_LOCALE); + std::string text = sObjectMgr->GetAcoreString(e.action.playerTalk.textId, DEFAULT_LOCALE); if (!targets.empty()) for (WorldObject* target : targets) @@ -3282,6 +3282,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u sWorldState->HandleExternalEvent(static_cast(e.action.worldStateScript.eventId), e.action.worldStateScript.param); break; } + case SMART_ACTION_DISABLE_REWARD: + { + for (WorldObject* target : targets) + if (IsCreature(target)) + { + target->ToCreature()->SetReputationRewardDisabled(static_cast(e.action.reward.reputation)); + target->ToCreature()->SetLootRewardDisabled(static_cast(e.action.reward.loot)); + } + break; + } default: LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); break; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index f79ed9e14..834e48007 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -860,6 +860,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e) case SMART_ACTION_MOVEMENT_PAUSE: return sizeof(SmartAction::move); case SMART_ACTION_MOVEMENT_RESUME: return sizeof(SmartAction::move); case SMART_ACTION_WORLD_SCRIPT: return sizeof(SmartAction::worldStateScript); + case SMART_ACTION_DISABLE_REWARD: return sizeof(SmartAction::reward); default: LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -1894,6 +1895,9 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return IsSAIBoolValid(e, e.action.setHealthRegen.regenHealth); case SMART_ACTION_CALL_TIMED_ACTIONLIST: return IsSAIBoolValid(e, e.action.timedActionList.allowOverride); + case SMART_ACTION_DISABLE_REWARD: + return IsSAIBoolValid(e, e.action.reward.reputation) && + IsSAIBoolValid(e, e.action.reward.loot); case SMART_ACTION_FLEE_FOR_ASSIST: case SMART_ACTION_MOVE_TO_POS: case SMART_ACTION_EVADE: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 159f8cb87..994129ecf 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -738,8 +738,9 @@ enum SMART_ACTION SMART_ACTION_MOVEMENT_PAUSE = 235, // timer SMART_ACTION_MOVEMENT_RESUME = 236, // timerOverride SMART_ACTION_WORLD_SCRIPT = 237, // eventId, param + SMART_ACTION_DISABLE_REWARD = 238, // reputation 0/1, loot 0/1 - SMART_ACTION_AC_END = 238, // placeholder + SMART_ACTION_AC_END = 239, // placeholder }; enum class SmartActionSummonCreatureFlags @@ -1501,6 +1502,12 @@ struct SmartAction uint32 param5; uint32 param6; } raw; + + struct + { + SAIBool reputation; + SAIBool loot; + } reward; }; }; diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 1850fb03a..13d989385 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -2438,7 +2438,7 @@ bool AchievementMgr::HasAchieved(uint32 achievementId) const bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement) { - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, nullptr)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, nullptr)) return false; if (achievement->mapID != -1 && GetPlayer()->GetMapId() != uint32(achievement->mapID)) @@ -2917,7 +2917,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() continue; } - if (!GetCriteriaDataSet(criteria) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, entryId, nullptr)) + if (!GetCriteriaDataSet(criteria) && !sDisableMgr->IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, entryId, nullptr)) LOG_ERROR("sql.sql", "Table `achievement_criteria_data` does not have expected data for criteria (Entry: {} Type: {}) for achievement {}.", criteria->ID, criteria->requiredType, criteria->referredAchievement); } diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 454bb3e4f..1d87e34e8 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -58,7 +58,8 @@ namespace Acore void operator()(WorldPacket& data, LocaleConstant loc_idx) { - char const* text = sObjectMgr->GetAcoreString(_textId, loc_idx); + std::string strtext = sObjectMgr->GetAcoreString(_textId, loc_idx); + char const* text = strtext.c_str(); if (_args) { // we need copy va_list before use or original va_list will corrupted @@ -95,9 +96,12 @@ namespace Acore void operator()(WorldPacket& data, LocaleConstant loc_idx) { - char const* text = sObjectMgr->GetAcoreString(_textId, loc_idx); - char const* arg1str = _arg1 ? sObjectMgr->GetAcoreString(_arg1, loc_idx) : ""; - char const* arg2str = _arg2 ? sObjectMgr->GetAcoreString(_arg2, loc_idx) : ""; + std::string strtext = sObjectMgr->GetAcoreString(_textId, loc_idx); + char const* text = strtext.c_str(); + std::string stragr1str = sObjectMgr->GetAcoreString(_arg1, loc_idx); + char const* arg1str = _arg1 ? stragr1str.c_str() : ""; + std::string strarg2str = sObjectMgr->GetAcoreString(_arg2, loc_idx); + char const* arg2str = _arg2 ? strarg2str.c_str() : ""; char str[2048]; snprintf(str, 2048, text, arg1str, arg2str); @@ -1659,13 +1663,6 @@ void Battleground::EndNow() SetEndTime(0); } -// To be removed -char const* Battleground::GetAcoreString(int32 entry) -{ - // FIXME: now we have different DBC locales and need localized message for each target client - return sObjectMgr->GetAcoreStringForDBCLocale(entry); -} - void Battleground::HandleTriggerBuff(GameObject* gameObject) { // Xinef: crash fix? diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 1460514d9..54dc97afd 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -559,8 +559,6 @@ public: void DoorOpen(uint32 type); void DoorClose(uint32 type); - //to be removed - const char* GetAcoreString(int32 entry); virtual bool HandlePlayerUnderMap(Player* /*player*/) { return false; } diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 4874cf157..8e91dd0d4 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -467,7 +467,7 @@ void BattlegroundMgr::LoadBattlegroundTemplates() BattlegroundTypeId bgTypeId = static_cast(fields[0].Get()); - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId, nullptr)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId, nullptr)) continue; // can be overwrite by values from DB diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index a0fa83d96..505249350 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -37,7 +37,7 @@ Player* ChatHandler::GetPlayer() const return m_session ? m_session->GetPlayer() : nullptr; } -char const* ChatHandler::GetAcoreString(uint32 entry) const +std::string ChatHandler::GetAcoreString(uint32 entry) const { return m_session->GetAcoreString(entry); } @@ -953,7 +953,7 @@ std::string ChatHandler::GetNameLink(Player* chr) const return playerLink(chr->GetName()); } -char const* CliHandler::GetAcoreString(uint32 entry) const +std::string CliHandler::GetAcoreString(uint32 entry) const { return sObjectMgr->GetAcoreStringForDBCLocale(entry); } diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 80d8e37d8..d54813843 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -148,7 +148,7 @@ public: } // function with different implementation for chat/console - virtual char const* GetAcoreString(uint32 entry) const; + virtual std::string GetAcoreString(uint32 entry) const; virtual void SendSysMessage(std::string_view str, bool escapeCharacters = false); void SendSysMessage(uint32 entry); @@ -276,7 +276,7 @@ public: explicit CliHandler(void* callbackArg, Print* zprint) : m_callbackArg(callbackArg), m_print(zprint) { } // overwrite functions - char const* GetAcoreString(uint32 entry) const override; + std::string GetAcoreString(uint32 entry) const override; void SendSysMessage(std::string_view, bool escapeCharacters) override; bool ParseCommands(std::string_view str) override; std::string GetNameLink() const override; diff --git a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.cpp b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.cpp index d39c99190..0c5f14147 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.cpp +++ b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.cpp @@ -24,7 +24,7 @@ void Acore::Impl::ChatCommands::SendErrorMessageToHandler(ChatHandler* handler, handler->SetSentErrorMessage(true); } -char const* Acore::Impl::ChatCommands::GetAcoreString(ChatHandler const* handler, AcoreStrings which) +std::string Acore::Impl::ChatCommands::GetAcoreString(ChatHandler const* handler, AcoreStrings which) { return handler->GetAcoreString(which); } diff --git a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h index 2ffe70900..a4bff85b9 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h @@ -120,7 +120,7 @@ namespace Acore::Impl::ChatCommands }; AC_GAME_API void SendErrorMessageToHandler(ChatHandler* handler, std::string_view str); - AC_GAME_API char const* GetAcoreString(ChatHandler const* handler, AcoreStrings which); + AC_GAME_API std::string GetAcoreString(ChatHandler const* handler, AcoreStrings which); template std::string FormatAcoreString(ChatHandler const* handler, AcoreStrings which, Ts&&... args) { diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp index e521389ce..e1019aee8 100644 --- a/src/server/game/Conditions/DisableMgr.cpp +++ b/src/server/game/Conditions/DisableMgr.cpp @@ -28,393 +28,418 @@ #include "VMapMgr2.h" #include "World.h" -namespace DisableMgr +std::map> DisableMgr::m_DisableMap; + +DisableMgr::DisableMgr() {} +DisableMgr::~DisableMgr() {} + +DisableMgr* DisableMgr::instance() { - namespace + static DisableMgr instance; + return &instance; +} + +void DisableMgr::LoadDisables() +{ + uint32 oldMSTime = getMSTime(); + + // reload case + for (DisableMap::iterator itr = m_DisableMap.begin(); itr != m_DisableMap.end(); ++itr) + itr->second.clear(); + + m_DisableMap.clear(); + + QueryResult result = WorldDatabase.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables"); + + uint32 total_count = 0; + + if (!result) { - struct DisableData - { - uint8 flags; - std::set params[2]; // params0, params1 - }; - - // single disables here with optional data - typedef std::map DisableTypeMap; - // global disable map by source - typedef std::map DisableMap; - - DisableMap m_DisableMap; - - uint8 MAX_DISABLE_TYPES = 11; - } - - void LoadDisables() - { - uint32 oldMSTime = getMSTime(); - - // reload case - for (DisableMap::iterator itr = m_DisableMap.begin(); itr != m_DisableMap.end(); ++itr) - itr->second.clear(); - - m_DisableMap.clear(); - - QueryResult result = WorldDatabase.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables"); - - uint32 total_count = 0; - - if (!result) - { - LOG_WARN("server.loading", ">> Loaded 0 disables. DB table `disables` is empty!"); - LOG_INFO("server.loading", " "); - return; - } - - Field* fields; - do - { - fields = result->Fetch(); - DisableType type = DisableType(fields[0].Get()); - if (type >= MAX_DISABLE_TYPES) - { - LOG_ERROR("sql.sql", "Invalid type {} specified in `disables` table, skipped.", type); - continue; - } - - uint32 entry = fields[1].Get(); - uint8 flags = fields[2].Get(); - std::string params_0 = fields[3].Get(); - std::string params_1 = fields[4].Get(); - - DisableData data; - data.flags = flags; - - switch (type) - { - case DISABLE_TYPE_GO_LOS: - if (!sObjectMgr->GetGameObjectTemplate(entry)) - { - LOG_ERROR("sql.sql", "Gameobject entry {} from `disables` doesn't exist in dbc, skipped.", entry); - continue; - } - if (flags) - LOG_ERROR("sql.sql", "Disable flags specified for gameobject {}, useless data.", entry); - break; - case DISABLE_TYPE_SPELL: - if (!(sSpellMgr->GetSpellInfo(entry) || flags & SPELL_DISABLE_DEPRECATED_SPELL)) - { - LOG_ERROR("sql.sql", "Spell entry {} from `disables` doesn't exist in dbc, skipped.", entry); - continue; - } - - if (!flags || flags > MAX_SPELL_DISABLE_TYPE) - { - LOG_ERROR("sql.sql", "Disable flags for spell {} are invalid, skipped.", entry); - continue; - } - - if (flags & SPELL_DISABLE_MAP) - { - for (std::string_view mapStr : Acore::Tokenize(params_0, ',', true)) - { - if (Optional mapId = Acore::StringTo(mapStr)) - data.params[0].insert(*mapId); - else - LOG_ERROR("sql.sql", "Disable map '{}' for spell {} is invalid, skipped.", mapStr, entry); - } - } - - if (flags & SPELL_DISABLE_AREA) - { - for (std::string_view areaStr : Acore::Tokenize(params_1, ',', true)) - { - if (Optional areaId = Acore::StringTo(areaStr)) - data.params[1].insert(*areaId); - else - LOG_ERROR("sql.sql", "Disable area '{}' for spell {} is invalid, skipped.", areaStr, entry); - } - } - - // xinef: if spell has disabled los, add flag - if (flags & SPELL_DISABLE_LOS) - { - SpellInfo* spellInfo = const_cast(sSpellMgr->GetSpellInfo(entry)); - spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT; - } - - break; - // checked later - case DISABLE_TYPE_QUEST: - break; - case DISABLE_TYPE_MAP: - case DISABLE_TYPE_LFG_MAP: - { - MapEntry const* mapEntry = sMapStore.LookupEntry(entry); - if (!mapEntry) - { - LOG_ERROR("sql.sql", "Map entry {} from `disables` doesn't exist in dbc, skipped.", entry); - continue; - } - bool isFlagInvalid = false; - switch (mapEntry->map_type) - { - case MAP_COMMON: - if (flags) - isFlagInvalid = true; - break; - case MAP_INSTANCE: - case MAP_RAID: - if (flags & DUNGEON_STATUSFLAG_HEROIC && !GetMapDifficultyData(entry, DUNGEON_DIFFICULTY_HEROIC)) - isFlagInvalid = true; - else if (flags & RAID_STATUSFLAG_10MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_10MAN_HEROIC)) - isFlagInvalid = true; - else if (flags & RAID_STATUSFLAG_25MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_25MAN_HEROIC)) - isFlagInvalid = true; - break; - case MAP_BATTLEGROUND: - case MAP_ARENA: - LOG_ERROR("sql.sql", "Battleground map {} specified to be disabled in map case, skipped.", entry); - continue; - } - if (isFlagInvalid) - { - LOG_ERROR("sql.sql", "Disable flags for map {} are invalid, skipped.", entry); - continue; - } - break; - } - case DISABLE_TYPE_BATTLEGROUND: - if (!sBattlemasterListStore.LookupEntry(entry)) - { - LOG_ERROR("sql.sql", "Battleground entry {} from `disables` doesn't exist in dbc, skipped.", entry); - continue; - } - if (flags) - LOG_ERROR("sql.sql", "Disable flags specified for battleground {}, useless data.", entry); - break; - case DISABLE_TYPE_OUTDOORPVP: - if (entry > MAX_OUTDOORPVP_TYPES) - { - LOG_ERROR("sql.sql", "OutdoorPvPTypes value {} from `disables` is invalid, skipped.", entry); - continue; - } - if (flags) - LOG_ERROR("sql.sql", "Disable flags specified for outdoor PvP {}, useless data.", entry); - break; - case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: - if (!sAchievementCriteriaStore.LookupEntry(entry)) - { - LOG_ERROR("sql.sql", "Achievement Criteria entry {} from `disables` doesn't exist in dbc, skipped.", entry); - continue; - } - if (flags) - LOG_ERROR("sql.sql", "Disable flags specified for Achievement Criteria {}, useless data.", entry); - break; - case DISABLE_TYPE_VMAP: - { - MapEntry const* mapEntry = sMapStore.LookupEntry(entry); - if (!mapEntry) - { - LOG_ERROR("sql.sql", "Map entry {} from `disables` doesn't exist in dbc, skipped.", entry); - continue; - } - switch (mapEntry->map_type) - { - case MAP_COMMON: - if (flags & VMAP::VMAP_DISABLE_AREAFLAG) - LOG_INFO("disable", "Areaflag disabled for world map {}.", entry); - if (flags & VMAP::VMAP_DISABLE_LIQUIDSTATUS) - LOG_INFO("disable", "Liquid status disabled for world map {}.", entry); - break; - case MAP_INSTANCE: - case MAP_RAID: - if (flags & VMAP::VMAP_DISABLE_HEIGHT) - LOG_INFO("disable", "Height disabled for instance map {}.", entry); - if (flags & VMAP::VMAP_DISABLE_LOS) - LOG_INFO("disable", "LoS disabled for instance map {}.", entry); - break; - case MAP_BATTLEGROUND: - if (flags & VMAP::VMAP_DISABLE_HEIGHT) - LOG_INFO("disable", "Height disabled for battleground map {}.", entry); - if (flags & VMAP::VMAP_DISABLE_LOS) - LOG_INFO("disable", "LoS disabled for battleground map {}.", entry); - break; - case MAP_ARENA: - if (flags & VMAP::VMAP_DISABLE_HEIGHT) - LOG_INFO("disable", "Height disabled for arena map {}.", entry); - if (flags & VMAP::VMAP_DISABLE_LOS) - LOG_INFO("disable", "LoS disabled for arena map {}.", entry); - break; - default: - break; - } - break; - } - case DISABLE_TYPE_GAME_EVENT: - { - GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList(); - if (activeEvents.find(entry) != activeEvents.end()) - { - sGameEventMgr->StopEvent(entry); - LOG_INFO("disable", "Event entry {} was stopped because it has been disabled.", entry); - } - break; - } - case DISABLE_TYPE_LOOT: - break; - default: - break; - } - - m_DisableMap[type].insert(DisableTypeMap::value_type(entry, data)); - ++total_count; - } while (result->NextRow()); - - LOG_INFO("server.loading", ">> Loaded {} Disables in {} ms", total_count, GetMSTimeDiffToNow(oldMSTime)); + LOG_WARN("server.loading", ">> Loaded 0 disables. DB table `disables` is empty!"); LOG_INFO("server.loading", " "); + return; } - void CheckQuestDisables() + Field* fields; + do { - uint32 oldMSTime = getMSTime(); - - uint32 count = m_DisableMap[DISABLE_TYPE_QUEST].size(); - if (!count) + fields = result->Fetch(); + DisableType type = DisableType(fields[0].Get()); + if (type >= MAX_DISABLE_TYPES) { - LOG_INFO("server.loading", ">> Checked 0 quest disables."); - LOG_INFO("server.loading", " "); - return; + LOG_ERROR("sql.sql", "Invalid type {} specified in `disables` table, skipped.", type); + continue; } - // check only quests, rest already done at startup - for (DisableTypeMap::iterator itr = m_DisableMap[DISABLE_TYPE_QUEST].begin(); itr != m_DisableMap[DISABLE_TYPE_QUEST].end();) + uint32 entry = fields[1].Get(); + uint8 flags = fields[2].Get(); + std::string params_0 = fields[3].Get(); + std::string params_1 = fields[4].Get(); + + DisableData data; + data.flags = flags; + + if (!HandleDisableType(type, entry, flags, params_0, params_1, data)) + continue; + + m_DisableMap[type].insert(DisableTypeMap::value_type(entry, data)); + ++total_count; + } while (result->NextRow()); + + LOG_INFO("server.loading", ">> Loaded {} Disables in {} ms", total_count, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", " "); +} + +/** +* @brief Allow to add disables without adding it to the database. Useful for modules. +* +* @param type Disable type +* @param entry Entry of Spell/Quest/Map/BG/Achievement/Map/GameEvent/Item +* @param flags Flag depending on Type +* @param param0 MapId if DISABLE_TYPE_SPELL used, 0 for all maps. +* @param param1 AreaId if DISABLE_TYPE_SPELL used, 0 for all areas. +*/ +void DisableMgr::AddDisable(DisableType type, uint32 entry, uint8 flags, std::string param0, std::string param1) +{ + if (type >= MAX_DISABLE_TYPES) + { + LOG_ERROR("disables", "AddDisable: Invalid type {} specified for entry {}, skipped.", type); + return; + } + + DisableData data; + data.flags = flags; + + if (!HandleDisableType(type, entry, flags, param0, param1, data)) + return; + + m_DisableMap[type].insert(DisableTypeMap::value_type(entry, data)); +} + +bool DisableMgr::HandleDisableType(DisableType type, uint32 entry, uint8 flags, std::string const& params_0, std::string const& params_1, DisableData& data) +{ + switch (type) + { + case DISABLE_TYPE_GO_LOS: + if (!sObjectMgr->GetGameObjectTemplate(entry)) { - const uint32 entry = itr->first; - if (!sObjectMgr->GetQuestTemplate(entry)) + LOG_ERROR("sql.sql", "Gameobject entry {} from `disables` doesn't exist in dbc, skipped.", entry); + return false; + } + if (flags) + LOG_ERROR("sql.sql", "Disable flags specified for gameobject {}, useless data.", entry); + break; + case DISABLE_TYPE_SPELL: + if (!(sSpellMgr->GetSpellInfo(entry) || flags & SPELL_DISABLE_DEPRECATED_SPELL)) + { + LOG_ERROR("sql.sql", "Spell entry {} from `disables` doesn't exist in dbc, skipped.", entry); + return false; + } + + if (!flags || flags > MAX_SPELL_DISABLE_TYPE) + { + LOG_ERROR("sql.sql", "Disable flags for spell {} are invalid, skipped.", entry); + return false; + } + + if (flags & SPELL_DISABLE_MAP) + { + for (std::string_view mapStr : Acore::Tokenize(params_0, ',', true)) { - LOG_ERROR("sql.sql", "Quest entry {} from `disables` doesn't exist, skipped.", entry); - m_DisableMap[DISABLE_TYPE_QUEST].erase(itr++); - continue; + if (Optional mapId = Acore::StringTo(mapStr)) + data.params[0].insert(*mapId); + else + LOG_ERROR("sql.sql", "Disable map '{}' for spell {} is invalid, skipped.", mapStr, entry); } - if (itr->second.flags) - LOG_ERROR("sql.sql", "Disable flags specified for quest {}, useless data.", entry); - ++itr; } - LOG_INFO("server.loading", ">> Checked {} Quest Disables in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + if (flags & SPELL_DISABLE_AREA) + { + for (std::string_view areaStr : Acore::Tokenize(params_1, ',', true)) + { + if (Optional areaId = Acore::StringTo(areaStr)) + data.params[1].insert(*areaId); + else + LOG_ERROR("sql.sql", "Disable area '{}' for spell {} is invalid, skipped.", areaStr, entry); + } + } + + // xinef: if spell has disabled los, add flag + if (flags & SPELL_DISABLE_LOS) + { + SpellInfo* spellInfo = const_cast(sSpellMgr->GetSpellInfo(entry)); + spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LINE_OF_SIGHT; + } + + break; + // checked later + case DISABLE_TYPE_QUEST: + break; + case DISABLE_TYPE_MAP: + case DISABLE_TYPE_LFG_MAP: + { + MapEntry const* mapEntry = sMapStore.LookupEntry(entry); + if (!mapEntry) + { + LOG_ERROR("sql.sql", "Map entry {} from `disables` doesn't exist in dbc, skipped.", entry); + return false; + } + bool isFlagInvalid = false; + switch (mapEntry->map_type) + { + case MAP_COMMON: + if (flags) + isFlagInvalid = true; + break; + case MAP_INSTANCE: + case MAP_RAID: + if (flags & DUNGEON_STATUSFLAG_HEROIC && !GetMapDifficultyData(entry, DUNGEON_DIFFICULTY_HEROIC)) + isFlagInvalid = true; + else if (flags & RAID_STATUSFLAG_10MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_10MAN_HEROIC)) + isFlagInvalid = true; + else if (flags & RAID_STATUSFLAG_25MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_25MAN_HEROIC)) + isFlagInvalid = true; + break; + case MAP_BATTLEGROUND: + case MAP_ARENA: + LOG_ERROR("sql.sql", "Battleground map {} specified to be disabled in map case, skipped.", entry); + return false; + } + if (isFlagInvalid) + { + LOG_ERROR("sql.sql", "Disable flags for map {} are invalid, skipped.", entry); + return false; + } + break; + } + case DISABLE_TYPE_BATTLEGROUND: + if (!sBattlemasterListStore.LookupEntry(entry)) + { + LOG_ERROR("sql.sql", "Battleground entry {} from `disables` doesn't exist in dbc, skipped.", entry); + return false; + } + if (flags) + LOG_ERROR("sql.sql", "Disable flags specified for battleground {}, useless data.", entry); + break; + case DISABLE_TYPE_OUTDOORPVP: + if (entry > MAX_OUTDOORPVP_TYPES) + { + LOG_ERROR("sql.sql", "OutdoorPvPTypes value {} from `disables` is invalid, skipped.", entry); + return false; + } + if (flags) + LOG_ERROR("sql.sql", "Disable flags specified for outdoor PvP {}, useless data.", entry); + break; + case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: + if (!sAchievementCriteriaStore.LookupEntry(entry)) + { + LOG_ERROR("sql.sql", "Achievement Criteria entry {} from `disables` doesn't exist in dbc, skipped.", entry); + return false; + } + if (flags) + LOG_ERROR("sql.sql", "Disable flags specified for Achievement Criteria {}, useless data.", entry); + break; + case DISABLE_TYPE_VMAP: + { + MapEntry const* mapEntry = sMapStore.LookupEntry(entry); + if (!mapEntry) + { + LOG_ERROR("sql.sql", "Map entry {} from `disables` doesn't exist in dbc, skipped.", entry); + return false; + } + switch (mapEntry->map_type) + { + case MAP_COMMON: + if (flags & VMAP::VMAP_DISABLE_AREAFLAG) + LOG_INFO("disable", "Areaflag disabled for world map {}.", entry); + if (flags & VMAP::VMAP_DISABLE_LIQUIDSTATUS) + LOG_INFO("disable", "Liquid status disabled for world map {}.", entry); + break; + case MAP_INSTANCE: + case MAP_RAID: + if (flags & VMAP::VMAP_DISABLE_HEIGHT) + LOG_INFO("disable", "Height disabled for instance map {}.", entry); + if (flags & VMAP::VMAP_DISABLE_LOS) + LOG_INFO("disable", "LoS disabled for instance map {}.", entry); + break; + case MAP_BATTLEGROUND: + if (flags & VMAP::VMAP_DISABLE_HEIGHT) + LOG_INFO("disable", "Height disabled for battleground map {}.", entry); + if (flags & VMAP::VMAP_DISABLE_LOS) + LOG_INFO("disable", "LoS disabled for battleground map {}.", entry); + break; + case MAP_ARENA: + if (flags & VMAP::VMAP_DISABLE_HEIGHT) + LOG_INFO("disable", "Height disabled for arena map {}.", entry); + if (flags & VMAP::VMAP_DISABLE_LOS) + LOG_INFO("disable", "LoS disabled for arena map {}.", entry); + break; + default: + break; + } + break; + } + case DISABLE_TYPE_GAME_EVENT: + { + GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList(); + if (activeEvents.find(entry) != activeEvents.end()) + { + sGameEventMgr->StopEvent(entry); + LOG_INFO("disable", "Event entry {} was stopped because it has been disabled.", entry); + } + break; + } + case DISABLE_TYPE_LOOT: + break; + case MAX_DISABLE_TYPES: + { + LOG_ERROR("disable", "SourceType out of range for entry {}, skipped", entry); + return false; + } + default: + return false; + } + return true; +} + +void DisableMgr::CheckQuestDisables() +{ + uint32 oldMSTime = getMSTime(); + + uint32 count = m_DisableMap[DISABLE_TYPE_QUEST].size(); + if (!count) + { + LOG_INFO("server.loading", ">> Checked 0 quest disables."); LOG_INFO("server.loading", " "); + return; } - bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags) + // check only quests, rest already done at startup + for (DisableTypeMap::iterator itr = m_DisableMap[DISABLE_TYPE_QUEST].begin(); itr != m_DisableMap[DISABLE_TYPE_QUEST].end();) { - if (type > MAX_DISABLE_TYPES) + const uint32 entry = itr->first; + if (!sObjectMgr->GetQuestTemplate(entry)) { - LOG_ERROR("server", "Disables::IsDisabledFor() called with unknown disable type {}! (entry {}, flags {}).", type, entry, flags); - return false; + LOG_ERROR("sql.sql", "Quest entry {} from `disables` doesn't exist, skipped.", entry); + m_DisableMap[DISABLE_TYPE_QUEST].erase(itr++); + continue; } + if (itr->second.flags) + LOG_ERROR("sql.sql", "Disable flags specified for quest {}, useless data.", entry); + ++itr; + } - if (m_DisableMap[type].empty()) - return false; - - DisableTypeMap::iterator itr = m_DisableMap[type].find(entry); - if (itr == m_DisableMap[type].end()) // not disabled - return false; - - switch (type) - { - case DISABLE_TYPE_SPELL: - { - uint8 spellFlags = itr->second.flags; - if (unit) - { - if ((spellFlags & SPELL_DISABLE_PLAYER && unit->IsPlayer()) || - (unit->IsCreature() && ((unit->IsPet() && spellFlags & SPELL_DISABLE_PET) || spellFlags & SPELL_DISABLE_CREATURE))) - { - if (spellFlags & SPELL_DISABLE_MAP) - { - std::set const& mapIds = itr->second.params[0]; - if (mapIds.find(unit->GetMapId()) != mapIds.end()) - return true; // Spell is disabled on current map - - if (!(spellFlags & SPELL_DISABLE_AREA)) - return false; // Spell is disabled on another map, but not this one, return false - - // Spell is disabled in an area, but not explicitly our current mapId. Continue processing. - } - - if (spellFlags & SPELL_DISABLE_AREA) - { - std::set const& areaIds = itr->second.params[1]; - if (areaIds.find(unit->GetAreaId()) != areaIds.end()) - return true; // Spell is disabled in this area - return false; // Spell is disabled in another area, but not this one, return false - } - else - return true; // Spell disabled for all maps - } - - return false; - } - else if (spellFlags & SPELL_DISABLE_DEPRECATED_SPELL) // call not from spellcast - return true; - - break; - } - case DISABLE_TYPE_MAP: - case DISABLE_TYPE_LFG_MAP: - if (Player const* player = unit->ToPlayer()) - { - MapEntry const* mapEntry = sMapStore.LookupEntry(entry); - if (mapEntry->IsDungeon()) - { - uint8 disabledModes = itr->second.flags; - Difficulty targetDifficulty = player->GetDifficulty(mapEntry->IsRaid()); - GetDownscaledMapDifficultyData(entry, targetDifficulty); - switch (targetDifficulty) - { - case DUNGEON_DIFFICULTY_NORMAL: - return disabledModes & DUNGEON_STATUSFLAG_NORMAL; - case DUNGEON_DIFFICULTY_HEROIC: - return disabledModes & DUNGEON_STATUSFLAG_HEROIC; - case RAID_DIFFICULTY_10MAN_HEROIC: - return disabledModes & RAID_STATUSFLAG_10MAN_HEROIC; - case RAID_DIFFICULTY_25MAN_HEROIC: - return disabledModes & RAID_STATUSFLAG_25MAN_HEROIC; - } - } - else if (mapEntry->map_type == MAP_COMMON) - return true; - } - return false; - case DISABLE_TYPE_QUEST: - return true; - case DISABLE_TYPE_BATTLEGROUND: - case DISABLE_TYPE_OUTDOORPVP: - case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: - return true; - case DISABLE_TYPE_VMAP: - return flags & itr->second.flags; - case DISABLE_TYPE_GO_LOS: - return true; - case DISABLE_TYPE_GAME_EVENT: - return true; - case DISABLE_TYPE_LOOT: - return true; - } + LOG_INFO("server.loading", ">> Checked {} Quest Disables in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", " "); +} +bool DisableMgr::IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags) +{ + if (type >= MAX_DISABLE_TYPES) + { + LOG_ERROR("server", "Disables::IsDisabledFor() called with unknown disable type {}! (entry {}, flags {}).", type, entry, flags); return false; } - bool IsVMAPDisabledFor(uint32 entry, uint8 flags) - { - return IsDisabledFor(DISABLE_TYPE_VMAP, entry, nullptr, flags); - } + if (m_DisableMap[type].empty()) + return false; - bool IsPathfindingEnabled(const Map* map) + DisableTypeMap::iterator itr = m_DisableMap[type].find(entry); + if (itr == m_DisableMap[type].end()) // not disabled + return false; + + switch (type) { - if (!map) + case DISABLE_TYPE_SPELL: + { + uint8 spellFlags = itr->second.flags; + if (unit) + { + if ((spellFlags & SPELL_DISABLE_PLAYER && unit->IsPlayer()) || + (unit->IsCreature() && ((unit->IsPet() && spellFlags & SPELL_DISABLE_PET) || spellFlags & SPELL_DISABLE_CREATURE))) + { + if (spellFlags & SPELL_DISABLE_MAP) + { + std::set const& mapIds = itr->second.params[0]; + if (mapIds.find(unit->GetMapId()) != mapIds.end()) + return true; // Spell is disabled on current map + + if (!(spellFlags & SPELL_DISABLE_AREA)) + return false; // Spell is disabled on another map, but not this one, return false + + // Spell is disabled in an area, but not explicitly our current mapId. Continue processing. + } + + if (spellFlags & SPELL_DISABLE_AREA) + { + std::set const& areaIds = itr->second.params[1]; + if (areaIds.find(unit->GetAreaId()) != areaIds.end()) + return true; // Spell is disabled in this area + return false; // Spell is disabled in another area, but not this one, return false + } + else + return true; // Spell disabled for all maps + } + + return false; + } + else if (spellFlags & SPELL_DISABLE_DEPRECATED_SPELL) // call not from spellcast + return true; + + break; + } + case DISABLE_TYPE_MAP: + case DISABLE_TYPE_LFG_MAP: + if (Player const* player = unit->ToPlayer()) + { + MapEntry const* mapEntry = sMapStore.LookupEntry(entry); + if (mapEntry->IsDungeon()) + { + uint8 disabledModes = itr->second.flags; + Difficulty targetDifficulty = player->GetDifficulty(mapEntry->IsRaid()); + GetDownscaledMapDifficultyData(entry, targetDifficulty); + switch (targetDifficulty) + { + case DUNGEON_DIFFICULTY_NORMAL: + return disabledModes & DUNGEON_STATUSFLAG_NORMAL; + case DUNGEON_DIFFICULTY_HEROIC: + return disabledModes & DUNGEON_STATUSFLAG_HEROIC; + case RAID_DIFFICULTY_10MAN_HEROIC: + return disabledModes & RAID_STATUSFLAG_10MAN_HEROIC; + case RAID_DIFFICULTY_25MAN_HEROIC: + return disabledModes & RAID_STATUSFLAG_25MAN_HEROIC; + } + } + else if (mapEntry->map_type == MAP_COMMON) + return true; + } return false; - - return !MMAP::MMapFactory::forbiddenMaps[map->GetId()] && (sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) ? true : map->IsBattlegroundOrArena()); + case DISABLE_TYPE_VMAP: + return flags & itr->second.flags; + case DISABLE_TYPE_QUEST: + case DISABLE_TYPE_BATTLEGROUND: + case DISABLE_TYPE_OUTDOORPVP: + case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: + case DISABLE_TYPE_GO_LOS: + case DISABLE_TYPE_GAME_EVENT: + case DISABLE_TYPE_LOOT: + return true; + default: + break; } -} // Namespace + return false; +} + +bool DisableMgr::IsVMAPDisabledFor(uint32 entry, uint8 flags) +{ + return IsDisabledFor(DISABLE_TYPE_VMAP, entry, nullptr, flags); +} + +bool DisableMgr::IsPathfindingEnabled(Map const* map) +{ + if (!map) + return false; + + return !MMAP::MMapFactory::forbiddenMaps[map->GetId()] && (sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) ? true : map->IsBattlegroundOrArena()); +} diff --git a/src/server/game/Conditions/DisableMgr.h b/src/server/game/Conditions/DisableMgr.h index a446921d8..1c7b7f2a6 100644 --- a/src/server/game/Conditions/DisableMgr.h +++ b/src/server/game/Conditions/DisableMgr.h @@ -15,8 +15,8 @@ * with this program. If not, see . */ -#ifndef ACORE_DISABLEMGR_H -#define ACORE_DISABLEMGR_H +#ifndef _DISABLEMGR_H +#define _DISABLEMGR_H #include "Define.h" #include "Map.h" @@ -34,7 +34,8 @@ enum DisableType DISABLE_TYPE_GO_LOS = 7, DISABLE_TYPE_LFG_MAP = 8, DISABLE_TYPE_GAME_EVENT = 9, - DISABLE_TYPE_LOOT = 10 + DISABLE_TYPE_LOOT = 10, + MAX_DISABLE_TYPES }; enum SpellDisableTypes @@ -46,18 +47,43 @@ enum SpellDisableTypes SPELL_DISABLE_MAP = 0x10, SPELL_DISABLE_AREA = 0x20, SPELL_DISABLE_LOS = 0x40, - MAX_SPELL_DISABLE_TYPE = ( SPELL_DISABLE_PLAYER | SPELL_DISABLE_CREATURE | SPELL_DISABLE_PET | - SPELL_DISABLE_DEPRECATED_SPELL | SPELL_DISABLE_MAP | SPELL_DISABLE_AREA | - SPELL_DISABLE_LOS) + MAX_SPELL_DISABLE_TYPE = (SPELL_DISABLE_PLAYER | SPELL_DISABLE_CREATURE | SPELL_DISABLE_PET | + SPELL_DISABLE_DEPRECATED_SPELL | SPELL_DISABLE_MAP | SPELL_DISABLE_AREA | + SPELL_DISABLE_LOS) }; -namespace DisableMgr +struct DisableData { - void LoadDisables(); - bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0); - void CheckQuestDisables(); - bool IsVMAPDisabledFor(uint32 entry, uint8 flags); - bool IsPathfindingEnabled(const Map* map); -} + uint8 flags; + std::set params[2]; // params0, params1 +}; -#endif //ACORE_DISABLEMGR_H +class DisableMgr +{ +private: + DisableMgr(); + ~DisableMgr(); + +public: + static DisableMgr* instance(); + + void LoadDisables(); + void AddDisable(DisableType type, uint32 entry, uint8 flags, std::string param0, std::string param1); + bool HandleDisableType(DisableType type, uint32 entry, uint8 flags, std::string const& params_0, std::string const& params_1, DisableData& data); + static bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0); + void CheckQuestDisables(); + static bool IsVMAPDisabledFor(uint32 entry, uint8 flags); + static bool IsPathfindingEnabled(Map const* map); + +private: + // single disables here with optional data + typedef std::map DisableTypeMap; + // global disable map by source + typedef std::map DisableMap; + + static DisableMap m_DisableMap; +}; + +#define sDisableMgr DisableMgr::instance() + +#endif //_DISABLEMGR_H diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 672bf265f..2c540afa1 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -410,9 +410,9 @@ namespace lfg uint32 lockData = 0; if (dungeon->expansion > expansion || (onlySeasonalBosses && !dungeon->seasonal)) lockData = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; - else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player)) + else if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player)) lockData = LFG_LOCKSTATUS_RAID_LOCKED; - else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_LFG_MAP, dungeon->map, player)) + else if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_LFG_MAP, dungeon->map, player)) lockData = LFG_LOCKSTATUS_RAID_LOCKED; else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && (!mapEntry || !mapEntry->IsRaid()) && sInstanceSaveMgr->PlayerIsPermBoundToInstance(player->GetGUID(), dungeon->map, Difficulty(dungeon->difficulty))) lockData = LFG_LOCKSTATUS_RAID_LOCKED; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 3d56498f0..96c2d3847 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -286,7 +286,9 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_ProhibitSchoolTime[i] = 0; m_CreatureSpellCooldowns.clear(); - DisableReputationGain = false; + + DisableReputationReward = false; + DisableLootReward = false; m_SightDistance = sWorld->getFloatConfig(CONFIG_SIGHT_MONSTER); m_CombatDistance = 0.0f; diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index b9632748b..2642b7d08 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -359,8 +359,10 @@ public: Unit* SelectVictim(); - void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; } - [[nodiscard]] bool IsReputationGainDisabled() const { return DisableReputationGain; } + void SetReputationRewardDisabled(bool disable) { DisableReputationReward = disable; } + [[nodiscard]] bool IsReputationRewardDisabled() const { return DisableReputationReward; } + void SetLootRewardDisabled(bool disable) { DisableLootReward = disable; } + [[nodiscard]] bool IsLootRewardDisabled() const { return DisableLootReward; } [[nodiscard]] bool IsDamageEnoughForLootingAndReward() const; void LowerPlayerDamageReq(uint32 unDamage, bool damagedByPlayer = true); void ResetPlayerDamageReq(); @@ -478,7 +480,8 @@ protected: Position m_homePosition; Position m_transportHomePosition; - bool DisableReputationGain; + bool DisableReputationReward; + bool DisableLootReward; CreatureTemplate const* m_creatureInfo; // in difficulty mode > 0 can different from sObjectMgr->GetCreatureTemplate(GetEntry()) CreatureData const* m_creatureData; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index fc7d04c61..91778e42c 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -2594,7 +2594,7 @@ void GameObject::EnableCollision(bool enable) GetMap()->InsertGameObjectModel(*m_model);*/ uint32 phaseMask = 0; - if (enable && !DisableMgr::IsDisabledFor(DISABLE_TYPE_GO_LOS, GetEntry(), nullptr)) + if (enable && !sDisableMgr->IsDisabledFor(DISABLE_TYPE_GO_LOS, GetEntry(), nullptr)) phaseMask = GetPhaseMask(); m_model->enable(phaseMask); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index fed41c4e2..5a97ed8d1 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1340,7 +1340,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati return false; } - if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, mapid, this)) + if (AccountMgr::IsPlayerAccount(GetSession()->GetSecurity()) && sDisableMgr->IsDisabledFor(DISABLE_TYPE_MAP, mapid, this)) { LOG_ERROR("entities.player", "Player ({}, name: {}) tried to enter a forbidden map {}", GetGUID().ToString(), GetName(), mapid); SendTransferAborted(mapid, TRANSFER_ABORT_MAP_NOT_ALLOWED); @@ -4493,6 +4493,9 @@ void Player::BuildPlayerRepop() void Player::ResurrectPlayer(float restore_percent, bool applySickness) { + if (!sScriptMgr->CanPlayerResurrect(this)) + return; + WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4 * 4); // remove spirit healer position data << uint32(-1); data << float(0); @@ -5993,7 +5996,7 @@ void Player::RewardReputation(Unit* victim) if (!victim || victim->IsPlayer()) return; - if (victim->ToCreature()->IsReputationGainDisabled()) + if (victim->ToCreature()->IsReputationRewardDisabled()) return; ReputationOnKillEntry const* Rep = sObjectMgr->GetReputationOnKilEntry(victim->ToCreature()->GetCreatureTemplate()->Entry); @@ -8858,6 +8861,8 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) } } + sWorldState->FillInitialWorldStates(data, zoneid, areaid); + uint16 length = (data.wpos() - countPos) / 8; data.put(countPos, length); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 842f87d33..3bf1e4aad 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1728,6 +1728,10 @@ public: [[nodiscard]] bool HasTalent(uint32 spell_id, uint8 spec) const; [[nodiscard]] uint32 CalculateTalentsPoints() const; + void SetBonusTalentCount(uint32 count) { m_extraBonusTalentCount = count; }; + uint32 GetBonusTalentCount() { return m_extraBonusTalentCount; }; + void AddBonusTalent(uint32 count) { m_extraBonusTalentCount += count; }; + void RemoveBonusTalent(uint32 count) { m_extraBonusTalentCount -= count; }; // Dual Spec void UpdateSpecCount(uint8 count); diff --git a/src/server/game/Entities/Player/PlayerQuest.cpp b/src/server/game/Entities/Player/PlayerQuest.cpp index 679c59ca5..dcf74d0f3 100644 --- a/src/server/game/Entities/Player/PlayerQuest.cpp +++ b/src/server/game/Entities/Player/PlayerQuest.cpp @@ -236,7 +236,7 @@ Quest const* Player::GetNextQuest(ObjectGuid guid, Quest const* quest) bool Player::CanSeeStartQuest(Quest const* quest) { - if (!DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this) && SatisfyQuestClass(quest, false) && SatisfyQuestRace(quest, false) && + if (!sDisableMgr->IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this) && SatisfyQuestClass(quest, false) && SatisfyQuestRace(quest, false) && SatisfyQuestSkill(quest, false) && SatisfyQuestExclusiveGroup(quest, false) && SatisfyQuestReputation(quest, false) && SatisfyQuestPreviousQuest(quest, false) && SatisfyQuestNextChain(quest, false) && SatisfyQuestPrevChain(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) && @@ -250,7 +250,7 @@ bool Player::CanSeeStartQuest(Quest const* quest) bool Player::CanTakeQuest(Quest const* quest, bool msg) { - return !DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this) + return !sDisableMgr->IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this) && SatisfyQuestStatus(quest, msg) && SatisfyQuestExclusiveGroup(quest, msg) && SatisfyQuestClass(quest, msg) && SatisfyQuestRace(quest, msg) && SatisfyQuestLevel(quest, msg) && SatisfyQuestSkill(quest, msg) && SatisfyQuestReputation(quest, msg) diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index 0cf697bca..0080963b6 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -5619,7 +5619,7 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons bool Player::isAllowedToLoot(Creature const* creature) { - if (!creature->isDead() || !creature->IsDamageEnoughForLootingAndReward()) + if (!creature->isDead() || !creature->IsDamageEnoughForLootingAndReward() || creature->IsLootRewardDisabled()) return false; if (HasPendingBind()) @@ -6722,7 +6722,7 @@ bool Player::Satisfy(DungeonProgressionRequirements const* ar, uint32 target_map LevelMax = ar->levelMax; } - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, target_map, this)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_MAP, target_map, this)) { GetSession()->SendAreaTriggerMessage("{}", GetSession()->GetAcoreString(LANG_INSTANCE_CLOSED)); return false; diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index 4fec71887..efc83f329 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -555,7 +555,7 @@ void Player::UpdateLocalChannels(uint32 newZone) if (channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY) currentNameExt = sObjectMgr->GetAcoreStringForDBCLocale( - LANG_CHANNEL_CITY); + LANG_CHANNEL_CITY).c_str(); else currentNameExt = current_zone_name.c_str(); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 953bda4cf..48b593294 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17798,7 +17798,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp bool isRewardAllowed = true; if (creature) { - isRewardAllowed = creature->IsDamageEnoughForLootingAndReward(); + isRewardAllowed = (creature->IsDamageEnoughForLootingAndReward() && !creature->IsLootRewardDisabled()); if (!isRewardAllowed) creature->SetLootRecipient(nullptr); } @@ -20444,7 +20444,7 @@ void Unit::PetSpellFail(SpellInfo const* spellInfo, Unit* target, uint32 result) if (!charmInfo || !IsCreature()) return; - if ((DisableMgr::IsPathfindingEnabled(GetMap()) || result != SPELL_FAILED_LINE_OF_SIGHT) && target) + if ((sDisableMgr->IsPathfindingEnabled(GetMap()) || result != SPELL_FAILED_LINE_OF_SIGHT) && target) { if ((result == SPELL_FAILED_LINE_OF_SIGHT || result == SPELL_FAILED_OUT_OF_RANGE) || !ToCreature()->HasReactState(REACT_PASSIVE)) if (Unit* owner = GetOwner()) @@ -21355,6 +21355,12 @@ bool Unit::CanRestoreMana(SpellInfo const* spellInfo) const return false; } +void Unit::SetShapeshiftForm(ShapeshiftForm form) +{ + SetByteValue(UNIT_FIELD_BYTES_2, 3, form); + sScriptMgr->OnUnitSetShapeshiftForm((Unit*)this, form); +} + bool Unit::IsInDisallowedMountForm() const { if (SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(getTransForm())) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 004c11c34..812b5d392 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1869,10 +1869,7 @@ public: // ShapeShitForm (use by druid) [[nodiscard]] ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, 3)); } - void SetShapeshiftForm(ShapeshiftForm form) - { - SetByteValue(UNIT_FIELD_BYTES_2, 3, form); - } + void SetShapeshiftForm(ShapeshiftForm form); bool IsAttackSpeedOverridenShapeShift() const; [[nodiscard]] bool IsInFeralForm() const { diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 0909ae7db..1927e4ee4 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -133,7 +133,7 @@ void GameEventMgr::StartInternalEvent(uint16 event_id) bool GameEventMgr::StartEvent(uint16 event_id, bool overwrite) { - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_GAME_EVENT, event_id, nullptr) && !overwrite) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_GAME_EVENT, event_id, nullptr) && !overwrite) { return false; } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 1dc3eeed3..208a5ccbf 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -3072,7 +3072,7 @@ void ObjectMgr::LoadItemTemplates() else if (itemTemplate.Spells[1].SpellId != -1) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[1].SpellId); - if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[1].SpellId, nullptr)) + if (!spellInfo && !sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[1].SpellId, nullptr)) { LOG_ERROR("sql.sql", "Item (Entry: {}) has wrong (not existing) spell in spellid_{} ({})", entry, 1 + 1, itemTemplate.Spells[1].SpellId); itemTemplate.Spells[0].SpellId = 0; @@ -3120,7 +3120,7 @@ void ObjectMgr::LoadItemTemplates() if (itemTemplate.Spells[j].SpellId && itemTemplate.Spells[j].SpellId != -1) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[j].SpellId); - if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[j].SpellId, nullptr)) + if (!spellInfo && !sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[j].SpellId, nullptr)) { LOG_ERROR("sql.sql", "Item (Entry: {}) has wrong (not existing) spell in spellid_{} ({})", entry, j + 1, itemTemplate.Spells[j].SpellId); itemTemplate.Spells[j].SpellId = 0; @@ -4616,7 +4616,7 @@ void ObjectMgr::LoadQuests() for (QuestMap::iterator iter = _questTemplates.begin(); iter != _questTemplates.end(); ++iter) { // skip post-loading checks for disabled quests - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, iter->first, nullptr)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_QUEST, iter->first, nullptr)) continue; Quest* qinfo = iter->second; @@ -8770,19 +8770,20 @@ bool ObjectMgr::LoadAcoreStrings() return true; } -char const* ObjectMgr::GetAcoreString(uint32 entry, LocaleConstant locale) const +std::string ObjectMgr::GetAcoreString(uint32 entry, LocaleConstant locale) const { - if (AcoreString const* ts = GetAcoreString(entry)) + AcoreString const* as = GetAcoreString(entry); + if (as && !as->Content.empty()) { - if (ts->Content.size() > std::size_t(locale) && !ts->Content[locale].empty()) - return ts->Content[locale].c_str(); + if (as->Content.size() > std::size_t(locale) && !as->Content[locale].empty()) + return as->Content[locale]; - return ts->Content[DEFAULT_LOCALE].c_str(); + return as->Content[DEFAULT_LOCALE]; } - LOG_ERROR("sql.sql", "Acore string entry {} not found in DB.", entry); - - return ""; + std::string msg = Acore::StringFormat("No entry for acore_string ({}) in DB.", entry); + LOG_ERROR("sql.sql", msg); + return msg; } void ObjectMgr::LoadFishingBaseSkillLevel() diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index abcc985b8..7ecbeb49d 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1315,8 +1315,8 @@ public: return &itr->second; } - [[nodiscard]] char const* GetAcoreString(uint32 entry, LocaleConstant locale) const; - [[nodiscard]] char const* GetAcoreStringForDBCLocale(uint32 entry) const { return GetAcoreString(entry, DBCLocaleIndex); } + [[nodiscard]] std::string GetAcoreString(uint32 entry, LocaleConstant locale) const; + [[nodiscard]] std::string GetAcoreStringForDBCLocale(uint32 entry) const { return GetAcoreString(entry, DBCLocaleIndex); } [[nodiscard]] LocaleConstant GetDBCLocaleIndex() const { return DBCLocaleIndex; } void SetDBCLocaleIndex(LocaleConstant locale) { DBCLocaleIndex = locale; } diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index d1ec2d8d9..c2aafae81 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -90,7 +90,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData) } // chosen battleground type is disabled - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, nullptr)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, nullptr)) { ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED); return; @@ -721,7 +721,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData) } // arenas disabled - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, nullptr)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, nullptr)) { ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED); return; diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 9f72af9c0..4ee34697d 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -158,7 +158,7 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/) { HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(entry); - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_GAME_EVENT, sGameEventMgr->GetHolidayEventId(holiday->Id), nullptr)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_GAME_EVENT, sGameEventMgr->GetHolidayEventId(holiday->Id), nullptr)) { continue; } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index d7cf92181..16d7a5458 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -232,7 +232,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe return; // Not let attack through obstructions - bool checkLos = !DisableMgr::IsPathfindingEnabled(pet->GetMap()) || + bool checkLos = !sDisableMgr->IsPathfindingEnabled(pet->GetMap()) || (TargetUnit->IsCreature() && (TargetUnit->ToCreature()->isWorldBoss() || TargetUnit->ToCreature()->IsDungeonBoss())); if (checkLos && !pet->IsWithinLOSInMap(TargetUnit)) diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 2f0dd99d9..c00332dd0 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -421,7 +421,7 @@ bool LootItem::AllowedForPlayer(Player const* player, ObjectGuid source) const return false; } - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_LOOT, itemid, nullptr)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_LOOT, itemid, nullptr)) { return false; } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 92b9248e4..9371aeccb 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -145,7 +145,7 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) void Map::LoadMMap(int gx, int gy) { - if (!DisableMgr::IsPathfindingEnabled(this)) // pussywizard + if (!sDisableMgr->IsPathfindingEnabled(this)) // pussywizard return; int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(GetId(), gx, gy); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index fe1c85faf..7de625355 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1169,8 +1169,7 @@ enum AcoreStrings LANG_GM_SILENCE = 6616, // "Silence is ON for %s" - Spell 1852 - // Used for .string command - LANG_NO_ACORE_STRING_FOUND = 6617, + // Free strings 6617-7522 LANG_WORLD_CLOSED = 7523, LANG_WORLD_OPENED = 7524, diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 8cc50f25b..be1667e5b 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -63,7 +63,7 @@ void HomeMovementGenerator::_setTargetLocation(Creature* owner) } owner->UpdateAllowedPositionZ(x, y, z); - init.MoveTo(x, y, z, DisableMgr::IsPathfindingEnabled(owner->FindMap()), true); + init.MoveTo(x, y, z, sDisableMgr->IsPathfindingEnabled(owner->FindMap()), true); init.SetWalk(_walk); init.Launch(); diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp index 4ec46038c..015d3973c 100644 --- a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp @@ -35,7 +35,7 @@ PathGenerator::PathGenerator(WorldObject const* owner) : memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs)); uint32 mapId = _source->GetMapId(); - //if (DisableMgr::IsPathfindingEnabled(_sourceUnit->FindMap())) + //if (sDisableMgr->IsPathfindingEnabled(_sourceUnit->FindMap())) { MMAP::MMapMgr* mmap = MMAP::MMapFactory::createOrGetMMapMgr(); _navMesh = mmap->GetNavMesh(mapId); diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp index 2e5c86298..a27e534d7 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp @@ -60,7 +60,7 @@ void OutdoorPvPMgr::InitOutdoorPvP() { typeId = fields[0].Get(); - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_OUTDOORPVP, typeId, nullptr)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_OUTDOORPVP, typeId, nullptr)) continue; if (typeId >= MAX_OUTDOORPVP_TYPES) diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 4d1432f13..4855b25bc 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -903,6 +903,11 @@ bool ScriptMgr::AnticheatCheckMovementInfo(Player* player, MovementInfo const& m CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ANTICHEAT_CHECK_MOVEMENT_INFO, !script->AnticheatCheckMovementInfo(player, movementInfo, mover, jump)); } +bool ScriptMgr::CanPlayerResurrect(Player* player) +{ + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_RESURRECT, !script->CanPlayerResurrect(player)); +} + PlayerScript::PlayerScript(const char* name, std::vector enabledHooks) : ScriptObject(name, PLAYERHOOK_END) { diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.h b/src/server/game/Scripting/ScriptDefines/PlayerScript.h index 8eede5fbe..59c3c4b56 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.h +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.h @@ -204,6 +204,7 @@ enum PlayerHook PLAYERHOOK_CAN_SEND_ERROR_ALREADY_LOOTED, PLAYERHOOK_ON_AFTER_CREATURE_LOOT, PLAYERHOOK_ON_AFTER_CREATURE_LOOT_MONEY, + PLAYERHOOK_CAN_RESURRECT, PLAYERHOOK_END }; @@ -766,6 +767,15 @@ public: * @param player Contains information about the Player */ virtual void OnAfterCreatureLootMoney(Player* /*player*/) { } + + /** + * @brief This hook is called, to avoid player resurrect + * + * @param player Contains information about the Player + * + * @return true if player is authorized to resurect + */ + virtual bool CanPlayerResurrect(Player* /*player*/) { return true; } }; #endif diff --git a/src/server/game/Scripting/ScriptDefines/UnitScript.cpp b/src/server/game/Scripting/ScriptDefines/UnitScript.cpp index 5470b3a32..bbf83e5c6 100644 --- a/src/server/game/Scripting/ScriptDefines/UnitScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/UnitScript.cpp @@ -148,6 +148,11 @@ void ScriptMgr::OnUnitDeath(Unit* unit, Unit* killer) CALL_ENABLED_HOOKS(UnitScript, UNITHOOK_ON_UNIT_DEATH, script->OnUnitDeath(unit, killer)); } +void ScriptMgr::OnUnitSetShapeshiftForm(Unit* unit, uint8 form) +{ + CALL_ENABLED_HOOKS(UnitScript, UNITHOOK_ON_UNIT_SET_SHAPESHIFT_FORM, script->OnUnitSetShapeshiftForm(unit, form)); +} + UnitScript::UnitScript(const char* name, bool addToScripts, std::vector enabledHooks) : ScriptObject(name, UNITHOOK_END) { diff --git a/src/server/game/Scripting/ScriptDefines/UnitScript.h b/src/server/game/Scripting/ScriptDefines/UnitScript.h index 27354ec6f..efee6defe 100644 --- a/src/server/game/Scripting/ScriptDefines/UnitScript.h +++ b/src/server/game/Scripting/ScriptDefines/UnitScript.h @@ -45,6 +45,7 @@ enum UnitHook UNITHOOK_ON_UNIT_ENTER_EVADE_MODE, UNITHOOK_ON_UNIT_ENTER_COMBAT, UNITHOOK_ON_UNIT_DEATH, + UNITHOOK_ON_UNIT_SET_SHAPESHIFT_FORM, UNITHOOK_END }; @@ -115,6 +116,7 @@ public: virtual void OnUnitEnterEvadeMode(Unit* /*unit*/, uint8 /*evadeReason*/) { } virtual void OnUnitEnterCombat(Unit* /*unit*/, Unit* /*victim*/) { } virtual void OnUnitDeath(Unit* /*unit*/, Unit* /*killer*/) { } + virtual void OnUnitSetShapeshiftForm(Unit* /*unit*/, uint8 /*form*/) { } }; #endif diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 9cf654fb1..ade190eb0 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -492,6 +492,7 @@ public: /* PlayerScript */ void OnAfterCreatureLoot(Player* player); void OnAfterCreatureLootMoney(Player* player); bool OnCanPlayerFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell); + bool CanPlayerResurrect(Player* player); // Anti cheat void AnticheatSetCanFlybyServer(Player* player, bool apply); @@ -589,6 +590,7 @@ public: /* UnitScript */ void OnUnitEnterEvadeMode(Unit* unit, uint8 why); void OnUnitEnterCombat(Unit* unit, Unit* victim); void OnUnitDeath(Unit* unit, Unit* killer); + void OnUnitSetShapeshiftForm(Unit* unit, uint8 form); public: /* MovementHandlerScript */ void OnPlayerMove(Player* player, MovementInfo movementInfo, uint32 opcode); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index a220fe100..c6032243f 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -830,7 +830,7 @@ bool WorldSession::DisallowHyperlinksAndMaybeKick(std::string_view str) return false; } -char const* WorldSession::GetAcoreString(uint32 entry) const +std::string WorldSession::GetAcoreString(uint32 entry) const { return sObjectMgr->GetAcoreString(entry, GetSessionDbLocaleIndex()); } diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index bbd0cbcdd..ebccbc0fe 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -372,7 +372,7 @@ public: void SendAreaTriggerMessage(std::string_view str); template - void SendAreaTriggerMessage(char const* fmt, Args&&... args) + void SendAreaTriggerMessage(std::string fmt, Args&&... args) { if (!m_playerLoading) SendAreaTriggerMessage(Acore::StringFormat(fmt, std::forward(args)...)); @@ -528,9 +528,9 @@ public: time_t m_muteTime; // Locales - LocaleConstant GetSessionDbcLocale() const { return /*_isBot? LOCALE_enUS : */m_sessionDbcLocale; } - LocaleConstant GetSessionDbLocaleIndex() const { return /*_isBot? LOCALE_enUS : */m_sessionDbLocaleIndex; } - char const* GetAcoreString(uint32 entry) const; + LocaleConstant GetSessionDbcLocale() const { return m_sessionDbcLocale; } + LocaleConstant GetSessionDbLocaleIndex() const { return m_sessionDbLocaleIndex; } + std::string GetAcoreString(uint32 entry) const; std::string const* GetModuleString(std::string module, uint32 id) const; uint32 GetLatency() const { return m_latency; } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index a1f6907de..0559b5583 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3530,7 +3530,7 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const _spellEvent = new SpellEvent(this); m_caster->m_Events.AddEvent(_spellEvent, m_caster->m_Events.CalculateTime(1)); - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, m_caster)) + if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, m_caster)) { SendCastResult(SPELL_FAILED_SPELL_UNAVAILABLE); finish(false); @@ -6247,7 +6247,7 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_BAD_TARGETS; // Xinef: Pass only explicit unit target spells // pussywizard: - if (DisableMgr::IsPathfindingEnabled(m_caster->FindMap()) && m_spellInfo->NeedsExplicitUnitTarget()) + if (sDisableMgr->IsPathfindingEnabled(m_caster->FindMap()) && m_spellInfo->NeedsExplicitUnitTarget()) { Unit* target = m_targets.GetUnitTarget(); if (!target) @@ -7960,7 +7960,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const // if spell is triggered, need to check for LOS disable on the aura triggering it and inherit that behaviour if (IsTriggered() && m_triggeredByAuraSpell && (m_triggeredByAuraSpell.spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) || - DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_triggeredByAuraSpell.spellInfo->Id, nullptr, SPELL_DISABLE_LOS))) + sDisableMgr->IsDisabledFor(DISABLE_TYPE_SPELL, m_triggeredByAuraSpell.spellInfo->Id, nullptr, SPELL_DISABLE_LOS))) { return true; } diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index 51a63724a..dccf4ca4f 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -1602,6 +1602,7 @@ void SpellMgr::LoadSpellInfoCorrections() ApplySpellFix({ 44335 }, [](SpellInfo* spellInfo) { spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CHANGE_MAP; + spellInfo->AttributesCu |= SPELL_ATTR0_CU_SINGLE_AURA_STACK; }); ApplySpellFix({ diff --git a/src/server/game/Texts/ChatTextBuilder.cpp b/src/server/game/Texts/ChatTextBuilder.cpp index dff037a0b..ad0ff1fed 100644 --- a/src/server/game/Texts/ChatTextBuilder.cpp +++ b/src/server/game/Texts/ChatTextBuilder.cpp @@ -39,7 +39,8 @@ void Acore::CustomChatTextBuilder::operator()(WorldPacket& data, LocaleConstant void Acore::AcoreStringChatBuilder::operator()(WorldPacket& data, LocaleConstant locale) const { - char const* text = sObjectMgr->GetAcoreString(_textId, locale); + std::string strtext = sObjectMgr->GetAcoreString(_textId, locale); + char const* text = strtext.c_str(); if (_args) { diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 393db767e..5bace8fe0 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -422,6 +422,7 @@ enum WorldIntConfigs CONFIG_DAILY_RBG_MIN_LEVEL_AP_REWARD, CONFIG_AUCTIONHOUSE_WORKERTHREADS, CONFIG_SPELL_QUEUE_WINDOW, + CONFIG_SUNSREACH_COUNTER_MAX, INT_CONFIG_VALUE_COUNT }; @@ -572,7 +573,7 @@ public: virtual void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; virtual void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; virtual bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; - virtual void SendZoneText(uint32 zone, const char* text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; + virtual void SendZoneText(uint32 zone, std::string text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; virtual void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr) = 0; [[nodiscard]] virtual bool IsShuttingDown() const = 0; [[nodiscard]] virtual uint32 GetShutDownTimeLeft() const = 0; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index caf5ba8c8..c3ed6acd6 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1499,6 +1499,8 @@ void World::LoadConfigSettings(bool reload) _bool_configs[CONFIG_SPELL_QUEUE_ENABLED] = sConfigMgr->GetOption("SpellQueue.Enabled", true); _int_configs[CONFIG_SPELL_QUEUE_WINDOW] = sConfigMgr->GetOption("SpellQueue.Window", 400); + _int_configs[CONFIG_SUNSREACH_COUNTER_MAX] = sConfigMgr->GetOption("Sunsreach.CounterMax", 10000); + // call ScriptMgr if we're reloading the configuration sScriptMgr->OnAfterConfigLoad(reload); } @@ -1720,7 +1722,7 @@ void World::SetInitialWorldSettings() LoadRandomEnchantmentsTable(); LOG_INFO("server.loading", "Loading Disables"); - DisableMgr::LoadDisables(); // must be before loading quests and items + sDisableMgr->LoadDisables(); // must be before loading quests and items LOG_INFO("server.loading", "Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts sObjectMgr->LoadItemTemplates(); @@ -1801,7 +1803,7 @@ void World::SetInitialWorldSettings() sObjectMgr->LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables LOG_INFO("server.loading", "Checking Quest Disables"); - DisableMgr::CheckQuestDisables(); // must be after loading quests + sDisableMgr->CheckQuestDisables(); // must be after loading quests LOG_INFO("server.loading", "Loading Quest POI"); sObjectMgr->LoadQuestPOI(); @@ -2126,6 +2128,9 @@ void World::SetInitialWorldSettings() LOG_INFO("server.loading", " "); sGameEventMgr->StartArenaSeason(); + LOG_INFO("server.loading", "Loading WorldState..."); + sWorldState->Load(); + sTicketMgr->Initialize(); ///- Initialize Battlegrounds @@ -2571,7 +2576,8 @@ namespace Acore explicit WorldWorldTextBuilder(uint32 textId, va_list* args = nullptr) : i_textId(textId), i_args(args) {} void operator()(WorldPacketList& data_list, LocaleConstant loc_idx) { - char const* text = sObjectMgr->GetAcoreString(i_textId, loc_idx); + std::string strtext = sObjectMgr->GetAcoreString(i_textId, loc_idx); + char const* text = strtext.c_str(); if (i_args) { @@ -2630,10 +2636,10 @@ bool World::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession } /// Send a System Message to all players in the zone (except self if mentioned) -void World::SendZoneText(uint32 zone, const char* text, WorldSession* self, TeamId teamId) +void World::SendZoneText(uint32 zone, std::string text, WorldSession* self, TeamId teamId) { WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text); + ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text.c_str()); SendZoneMessage(zone, &data, self, teamId); } diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 071a69195..3593ee1bf 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -239,7 +239,7 @@ public: void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; - void SendZoneText(uint32 zone, const char* text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; + void SendZoneText(uint32 zone, std::string text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr) override; /// Are we in the middle of a shutdown? diff --git a/src/server/game/World/WorldState.cpp b/src/server/game/World/WorldState.cpp index 174e468f4..a17ac7a11 100644 --- a/src/server/game/World/WorldState.cpp +++ b/src/server/game/World/WorldState.cpp @@ -15,9 +15,11 @@ * with this program. If not, see . */ +#include "GameEventMgr.h" #include "MapMgr.h" #include "Player.h" #include "SharedDefines.h" +#include "Weather.h" #include "WorldState.h" WorldState* WorldState::instance() @@ -37,6 +39,82 @@ WorldState::~WorldState() { } +void WorldState::Load() +{ + QueryResult result = CharacterDatabase.Query("SELECT Id, Data FROM world_state"); + if (result) + { + do + { + Field* fields = result->Fetch(); + uint32 id = fields[0].Get(); + std::string data = fields[1].Get(); + std::istringstream loadStream(data); + + switch (id) + { + case SAVE_ID_QUEL_DANAS: + { + if (data.size()) + { + try + { + loadStream >> m_sunsReachData.m_phase >> m_sunsReachData.m_subphaseMask; + for (uint32 i = 0; i < COUNTERS_MAX; ++i) + loadStream >> m_sunsReachData.m_sunsReachReclamationCounters[i]; + loadStream >> m_sunsReachData.m_gate; + for (uint32 i = 0; i < COUNTERS_MAX_GATES; ++i) + loadStream >> m_sunsReachData.m_gateCounters[i]; + } + catch (std::exception& e) + { + LOG_ERROR("scripts", "WorldState::Load: Exception reading SunsReach data {}", e.what()); + m_sunsReachData.m_phase = 0; + m_sunsReachData.m_subphaseMask = 0; + memset(m_sunsReachData.m_sunsReachReclamationCounters, 0, sizeof(m_sunsReachData.m_sunsReachReclamationCounters)); + m_sunsReachData.m_gate = SUNWELL_ALL_GATES_CLOSED; + memset(m_sunsReachData.m_gateCounters, 0, sizeof(m_sunsReachData.m_gateCounters)); + } + } + else + { + m_sunsReachData.m_phase = 0; + m_sunsReachData.m_subphaseMask = 0; + memset(m_sunsReachData.m_sunsReachReclamationCounters, 0, sizeof(m_sunsReachData.m_sunsReachReclamationCounters)); + m_sunsReachData.m_gate = SUNWELL_ALL_GATES_CLOSED; + memset(m_sunsReachData.m_gateCounters, 0, sizeof(m_sunsReachData.m_gateCounters)); + } + break; + } + } + } while (result->NextRow()); + } + StartSunsReachPhase(true); + StartSunwellGatePhase(); + HandleSunsReachSubPhaseTransition(m_sunsReachData.m_subphaseMask, true); +} + +void WorldState::Save(WorldStateSaveIds saveId) +{ + switch (saveId) + { + case SAVE_ID_QUEL_DANAS: + { + std::string expansionData = m_sunsReachData.GetData(); + SaveHelper(expansionData, SAVE_ID_QUEL_DANAS); + break; + } + default: + break; + } +} + +void WorldState::SaveHelper(std::string& stringToSave, WorldStateSaveIds saveId) +{ + CharacterDatabase.Execute("DELETE FROM world_state WHERE Id='{}'", saveId); + CharacterDatabase.Execute("INSERT INTO world_state(Id,Data) VALUES('{}','{}')", saveId, stringToSave.data()); +} + bool WorldState::IsConditionFulfilled(WorldStateCondition conditionId, WorldStateConditionState state) const { switch (conditionId) @@ -140,6 +218,16 @@ void WorldState::HandlePlayerEnterZone(Player* player, WorldStateZoneId zoneId) else if (_isMagtheridonHeadSpawnedHorde && player->GetTeamId() == TEAM_HORDE) player->CastSpell(player, SPELL_NAZGRELS_FAVOR, true); break; + case ZONEID_ISLE_OF_QUEL_DANAS: + case ZONEID_MAGISTERS_TERRACE: + case ZONEID_SUNWELL_PLATEAU: + { + std::lock_guard guard(m_sunsReachData.m_sunsReachReclamationMutex); + m_sunsReachData.m_sunsReachReclamationPlayers.push_back(player->GetGUID()); + if (m_sunsReachData.m_subphaseMask == SUBPHASE_ALL) + player->CastSpell(player, SPELL_KIRU_SONG_OF_VICTORY, true); + break; + } default: break; } @@ -167,6 +255,17 @@ void WorldState::HandlePlayerLeaveZone(Player* player, WorldStateZoneId zoneId) else if (player->GetTeamId() == TEAM_HORDE) player->RemoveAurasDueToSpell(SPELL_NAZGRELS_FAVOR); break; + case ZONEID_ISLE_OF_QUEL_DANAS: + case ZONEID_MAGISTERS_TERRACE: + case ZONEID_SUNWELL_PLATEAU: + { + std::lock_guard guard(m_sunsReachData.m_sunsReachReclamationMutex); + player->RemoveAurasDueToSpell(SPELL_KIRU_SONG_OF_VICTORY); + auto position = std::find(m_sunsReachData.m_sunsReachReclamationPlayers.begin(), m_sunsReachData.m_sunsReachReclamationPlayers.end(), player->GetGUID()); + if (position != m_sunsReachData.m_sunsReachReclamationPlayers.end()) + m_sunsReachData.m_sunsReachReclamationPlayers.erase(position); + break; + } default: break; } @@ -291,3 +390,699 @@ void WorldState::DispelAdalsSongOfBattle() } }); } + +void WorldState::SendWorldstateUpdate(std::mutex& mutex, GuidVector const& guids, uint32 value, uint32 worldStateId) +{ + std::lock_guard guard(mutex); + for (ObjectGuid const& guid : guids) + if (Player* player = ObjectAccessor::FindPlayer(guid)) + player->SendUpdateWorldState(worldStateId, value); +} + +enum WorldStateSunsReachQuests +{ + QUEST_ERRATIC_BEHAVIOR = 11524, + QUEST_SANCTUM_WARDS = 11496, + QUEST_BATTLE_FOR_THE_SUNS_REACH_ARMORY = 11538, + QUEST_DISTRACTION_AT_THE_DEAD_SCAR = 11532, + QUEST_INTERCEPTING_THE_MANA_CELLS = 11513, + QUEST_INTERCEPT_THE_REINFORCEMENTS = 11542, + QUEST_TAKING_THE_HARBOR = 11539, + QUEST_MAKING_READY = 11535, + QUEST_DISCOVERING_YOUR_ROOTS = 11520, + QUEST_A_CHARITABLE_DONATION = 11545, + QUEST_A_MAGNANIMOUS_BENEFACTOR = 11549, + COUNTER_MAX_VAL_REQ = 10000, +}; + +void WorldState::AddSunsReachProgress(uint32 questId) +{ + uint32 counter = 0; + int32 otherCounter = -1; + int32 worldState = 0; + uint32 subPhaseMask = 0; + uint32 addedValue = 1; + switch (questId) + { + case QUEST_ERRATIC_BEHAVIOR: + counter = COUNTER_ERRATIC_BEHAVIOR; + otherCounter = COUNTER_SANCTUM_WARDS; + worldState = WORLD_STATE_QUEL_DANAS_SANCTUM; + break; + case QUEST_SANCTUM_WARDS: + counter = COUNTER_SANCTUM_WARDS; + otherCounter = COUNTER_SANCTUM_WARDS; + worldState = WORLD_STATE_QUEL_DANAS_SANCTUM; + break; + case QUEST_BATTLE_FOR_THE_SUNS_REACH_ARMORY: + counter = COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY; + otherCounter = COUNTER_DISTRACTION_AT_THE_DEAD_SCAR; + worldState = WORLD_STATE_QUEL_DANAS_ARMORY; + break; + case QUEST_DISTRACTION_AT_THE_DEAD_SCAR: + counter = COUNTER_DISTRACTION_AT_THE_DEAD_SCAR; + otherCounter = COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY; + worldState = WORLD_STATE_QUEL_DANAS_ARMORY; + break; + case QUEST_INTERCEPTING_THE_MANA_CELLS: + counter = COUNTER_INTERCEPTING_THE_MANA_CELLS; + subPhaseMask = SUBPHASE_PORTAL; + worldState = WORLD_STATE_QUEL_DANAS_PORTAL; + break; + case QUEST_INTERCEPT_THE_REINFORCEMENTS: + counter = COUNTER_INTERCEPT_THE_REINFORCEMENTS; + otherCounter = COUNTER_TAKING_THE_HARBOR; + worldState = WORLD_STATE_QUEL_DANAS_HARBOR; + break; + case QUEST_TAKING_THE_HARBOR: + counter = COUNTER_TAKING_THE_HARBOR; + otherCounter = COUNTER_INTERCEPT_THE_REINFORCEMENTS; + worldState = WORLD_STATE_QUEL_DANAS_HARBOR; + break; + case QUEST_MAKING_READY: + counter = COUNTER_MAKING_READY; + subPhaseMask = SUBPHASE_ANVIL; + worldState = WORLD_STATE_QUEL_DANAS_ANVIL; + break; + case QUEST_DISCOVERING_YOUR_ROOTS: + counter = COUNTER_DISCOVERING_YOUR_ROOTS; + subPhaseMask = SUBPHASE_ALCHEMY_LAB; + worldState = WORLD_STATE_QUEL_DANAS_ALCHEMY_LAB; + break; + case QUEST_A_CHARITABLE_DONATION: + counter = COUNTER_A_CHARITABLE_DONATION; + subPhaseMask = SUBPHASE_MONUMENT; + worldState = WORLD_STATE_QUEL_DANAS_MONUMENT; + break; + case QUEST_A_MAGNANIMOUS_BENEFACTOR: + counter = COUNTER_A_CHARITABLE_DONATION; + subPhaseMask = SUBPHASE_MONUMENT; + worldState = WORLD_STATE_QUEL_DANAS_MONUMENT; + addedValue = 150; + break; + default: + return; + } + + uint32 previousValue = 0; + uint32 newValue = 0; + + if (!subPhaseMask) + previousValue = m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase); + else + previousValue = m_sunsReachData.GetSubPhasePercentage(subPhaseMask); + m_sunsReachData.m_sunsReachReclamationCounters[counter] += addedValue; + if (!subPhaseMask) + newValue = m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase); + else + newValue = m_sunsReachData.GetSubPhasePercentage(subPhaseMask); + if (previousValue != newValue) + SendWorldstateUpdate(m_sunsReachData.m_sunsReachReclamationMutex, m_sunsReachData.m_sunsReachReclamationPlayers, newValue, worldState); + + bool save = true; + uint32 counterValue = m_sunsReachData.m_sunsReachReclamationCounters[counter]; + uint32 modifier = 1; + if (otherCounter != -1) + { + modifier = 2; + counterValue += m_sunsReachData.m_sunsReachReclamationCounters[otherCounter]; + } + if (counterValue >= sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX) * modifier) + { + save = false; + switch (questId) + { + case QUEST_ERRATIC_BEHAVIOR: + case QUEST_SANCTUM_WARDS: + { + if (m_sunsReachData.m_phase == SUNS_REACH_PHASE_1_STAGING_AREA) + HandleSunsReachPhaseTransition(SUNS_REACH_PHASE_2_SANCTUM); + break; + } + case QUEST_BATTLE_FOR_THE_SUNS_REACH_ARMORY: + case QUEST_DISTRACTION_AT_THE_DEAD_SCAR: + { + if (m_sunsReachData.m_phase == SUNS_REACH_PHASE_2_SANCTUM) + HandleSunsReachPhaseTransition(SUNS_REACH_PHASE_3_ARMORY); + break; + } + case QUEST_INTERCEPTING_THE_MANA_CELLS: + { + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_PORTAL) == 0) + HandleSunsReachSubPhaseTransition(SUBPHASE_PORTAL); + break; + } + case QUEST_INTERCEPT_THE_REINFORCEMENTS: + case QUEST_TAKING_THE_HARBOR: + { + if (m_sunsReachData.m_phase == SUNS_REACH_PHASE_3_ARMORY) + HandleSunsReachPhaseTransition(SUNS_REACH_PHASE_4_HARBOR); + break; + } + case QUEST_MAKING_READY: + { + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ANVIL) == 0) + HandleSunsReachSubPhaseTransition(SUBPHASE_ANVIL); + break; + } + case QUEST_DISCOVERING_YOUR_ROOTS: + { + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALCHEMY_LAB) == 0) + HandleSunsReachSubPhaseTransition(SUBPHASE_ALCHEMY_LAB); + break; + } + case QUEST_A_CHARITABLE_DONATION: + case QUEST_A_MAGNANIMOUS_BENEFACTOR: + { + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_MONUMENT) == 0) + HandleSunsReachSubPhaseTransition(SUBPHASE_MONUMENT); + break; + } + } + } + if (save) + Save(SAVE_ID_QUEL_DANAS); +} + +void WorldState::HandleSunsReachPhaseTransition(uint32 newPhase) +{ + if (newPhase < m_sunsReachData.m_phase) + { + while (newPhase != m_sunsReachData.m_phase) + { + StopSunsReachPhase(newPhase > m_sunsReachData.m_phase); + --m_sunsReachData.m_phase; + } + StartSunsReachPhase(); + } + else + { + StopSunsReachPhase(newPhase > m_sunsReachData.m_phase); + bool moreThanOne = newPhase > m_sunsReachData.m_phase + 1; // custom command case + m_sunsReachData.m_phase = newPhase; + StartSunsReachPhase(moreThanOne); + } + switch (m_sunsReachData.m_phase) + { + case SUNS_REACH_PHASE_2_SANCTUM: if ((m_sunsReachData.m_subphaseMask & SUBPHASE_PORTAL) == 0) sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_NO_PORTAL); break; + case SUNS_REACH_PHASE_3_ARMORY: if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ANVIL) == 0) sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_NO_ANVIL); break; + case SUNS_REACH_PHASE_4_HARBOR: + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALCHEMY_LAB) == 0) sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_NO_MONUMENT); + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_MONUMENT) == 0) sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_NO_ALCHEMY_LAB); + break; + default: break; + } + SendWorldstateUpdate(m_sunsReachData.m_sunsReachReclamationMutex, m_sunsReachData.m_sunsReachReclamationPlayers, m_sunsReachData.m_phase, WORLD_STATE_QUEL_DANAS_MUSIC); + Save(SAVE_ID_QUEL_DANAS); +} + +void WorldState::HandleSunsReachSubPhaseTransition(int32 subPhaseMask, bool initial) +{ + bool start = true; + if (subPhaseMask < 0) + { + start = false; + subPhaseMask = -subPhaseMask; + } + bool all = false; + if (start) + { + m_sunsReachData.m_subphaseMask |= subPhaseMask; + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALL) == SUBPHASE_ALL) + all = true; + } + else + { + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALL) == SUBPHASE_ALL) + all = true; + m_sunsReachData.m_subphaseMask &= ~subPhaseMask; + } + if (initial) + { + if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_2_SANCTUM) + if ((subPhaseMask & SUBPHASE_PORTAL) == 0) + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_NO_PORTAL); + if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_3_ARMORY) + if ((subPhaseMask & SUBPHASE_ANVIL) == 0) + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_NO_ANVIL); + if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_4_HARBOR) + { + if ((subPhaseMask & SUBPHASE_ALCHEMY_LAB) == 0) + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_NO_ALCHEMY_LAB); + if ((subPhaseMask & SUBPHASE_MONUMENT) == 0) + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_NO_MONUMENT); + } + } + if ((subPhaseMask & SUBPHASE_PORTAL)) + { + uint32 first = GAME_EVENT_QUEL_DANAS_PHASE_2_NO_PORTAL; + uint32 second = GAME_EVENT_QUEL_DANAS_PHASE_2_PORTAL; + if (start) + { + sGameEventMgr->StopEvent(first); + sGameEventMgr->StartEvent(second); + } + else + { + sGameEventMgr->StopEvent(second); + sGameEventMgr->StartEvent(first); + } + } + if ((subPhaseMask & SUBPHASE_ANVIL)) + { + uint32 first = GAME_EVENT_QUEL_DANAS_PHASE_3_NO_ANVIL; + uint32 second = GAME_EVENT_QUEL_DANAS_PHASE_3_ANVIL; + if (start) + { + sGameEventMgr->StopEvent(first); + sGameEventMgr->StartEvent(second); + } + else + { + sGameEventMgr->StopEvent(second); + sGameEventMgr->StartEvent(first); + } + } + if ((subPhaseMask & SUBPHASE_ALCHEMY_LAB)) + { + uint32 first = GAME_EVENT_QUEL_DANAS_PHASE_4_NO_ALCHEMY_LAB; + uint32 second = GAME_EVENT_QUEL_DANAS_PHASE_4_ALCHEMY_LAB; + if (start) + { + sGameEventMgr->StopEvent(first); + sGameEventMgr->StartEvent(second); + } + else + { + sGameEventMgr->StopEvent(second); + sGameEventMgr->StartEvent(first); + } + } + if ((subPhaseMask & SUBPHASE_MONUMENT)) + { + uint32 first = GAME_EVENT_QUEL_DANAS_PHASE_4_NO_MONUMENT; + uint32 second = GAME_EVENT_QUEL_DANAS_PHASE_4_MONUMENT; + if (start) + { + sGameEventMgr->StopEvent(first); + sGameEventMgr->StartEvent(second); + } + else + { + sGameEventMgr->StopEvent(second); + sGameEventMgr->StartEvent(first); + } + } + if (all) + { + if (start) + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_KIRU); + else + sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_4_KIRU); + + if (!initial) + { + std::lock_guard guard(m_sunsReachData.m_sunsReachReclamationMutex); + for (ObjectGuid& guid : m_sunsReachData.m_sunsReachReclamationPlayers) + if (Player* player = ObjectAccessor::FindPlayer(guid)) + { + if (start) + player->CastSpell(player, SPELL_KIRU_SONG_OF_VICTORY, true); + else + player->RemoveAurasDueToSpell(SPELL_KIRU_SONG_OF_VICTORY); + } + } + } + if (!initial) + Save(SAVE_ID_QUEL_DANAS); +} + +void WorldState::HandleSunwellGateTransition(uint32 newGate) +{ + if (newGate < m_sunsReachData.m_gate) + { + while (newGate != m_sunsReachData.m_gate) + { + StopSunwellGatePhase(); + --m_sunsReachData.m_gate; + } + StartSunwellGatePhase(); + } + else + { + StopSunwellGatePhase(); + m_sunsReachData.m_gate = newGate; + StartSunwellGatePhase(); + } + int32 worldState = 0; + switch (newGate) + { + case SUNWELL_AGAMATH_GATE1_OPEN: worldState = WORLD_STATE_AGAMATH_THE_FIRST_GATE_HEALTH; break; + case SUNWELL_ROHENDOR_GATE2_OPEN: worldState = WORLD_STATE_ROHENDOR_THE_SECOND_GATE_HEALTH; break; + case SUNWELL_ARCHONISUS_GATE3_OPEN: worldState = WORLD_STATE_ARCHONISUS_THE_FINAL_GATE_HEALTH; break; + } + if (worldState) + SendWorldstateUpdate(m_sunsReachData.m_sunsReachReclamationMutex, m_sunsReachData.m_sunsReachReclamationPlayers, m_sunsReachData.m_gate, worldState); + + Save(SAVE_ID_QUEL_DANAS); +} + +void WorldState::SetSunsReachCounter(SunsReachCounters index, uint32 value) +{ + m_sunsReachData.m_sunsReachReclamationCounters[index] = value; +} + +void WorldState::StopSunsReachPhase(bool forward) +{ + switch (m_sunsReachData.m_phase) + { + case SUNS_REACH_PHASE_1_STAGING_AREA: sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_1); break; + case SUNS_REACH_PHASE_2_SANCTUM: sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_ONLY); if (!forward) sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT); break; + case SUNS_REACH_PHASE_3_ARMORY: sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_ONLY); if (!forward) sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_PERMANENT); break; + case SUNS_REACH_PHASE_4_HARBOR: sGameEventMgr->StopEvent(GAME_EVENT_QUEL_DANAS_PHASE_4); break; + default: break; + } +} + +void WorldState::StartSunsReachPhase(bool initial) +{ + switch (m_sunsReachData.m_phase) + { + case SUNS_REACH_PHASE_1_STAGING_AREA: + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_1); + if (Map* map = sMapMgr->FindBaseNonInstanceMap(530)) + map->SetZoneWeather(ZONEID_ISLE_OF_QUEL_DANAS, WEATHER_STATE_MEDIUM_RAIN, 0.75f); + break; + case SUNS_REACH_PHASE_2_SANCTUM: + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_ONLY); + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT); + if (Map* map = sMapMgr->FindBaseNonInstanceMap(530)) + map->SetZoneWeather(ZONEID_ISLE_OF_QUEL_DANAS, WEATHER_STATE_LIGHT_RAIN, 0.5f); + break; + case SUNS_REACH_PHASE_3_ARMORY: + if (initial) + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT); + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_ONLY); sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_PERMANENT); + // TODO: Should be id 2 0.25f? + if (Map* map = sMapMgr->FindBaseNonInstanceMap(530)) + map->SetZoneWeather(ZONEID_ISLE_OF_QUEL_DANAS, WEATHER_STATE_LIGHT_RAIN, 0.25f); + break; + case SUNS_REACH_PHASE_4_HARBOR: + if (initial) + { + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT); + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_3_PERMANENT); + } + sGameEventMgr->StartEvent(GAME_EVENT_QUEL_DANAS_PHASE_4); + if (Map* map = sMapMgr->FindBaseNonInstanceMap(530)) + map->SetZoneWeather(ZONEID_ISLE_OF_QUEL_DANAS, WEATHER_STATE_FINE, 0.0f); + break; + default: break; + } +} + +std::string WorldState::GetSunsReachPrintout() +{ + auto formatPhase = [this]() -> std::string { + std::string name; + switch (m_sunsReachData.m_phase) + { + case SUNS_REACH_PHASE_1_STAGING_AREA: name = "Phase 1: Staging Area"; break; + case SUNS_REACH_PHASE_2_SANCTUM: name = "Phase 2: Sanctum"; break; + case SUNS_REACH_PHASE_3_ARMORY: name = "Phase 3: Armory"; break; + case SUNS_REACH_PHASE_4_HARBOR: name = "Phase 4: Harbor"; break; + default: name = "Unknown"; break; + } + return "Phase: " + std::to_string(m_sunsReachData.m_phase) + " (" + name + ") " + std::to_string(m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase)) + "%\n"; + }; + + auto formatSubPhase = [this](uint32 subPhase) -> std::string { + std::string name; + switch (subPhase) + { + case SUBPHASE_PORTAL: name = "Portal"; break; + case SUBPHASE_ANVIL: name = "Anvil"; break; + case SUBPHASE_ALCHEMY_LAB: name = "Alchemy Lab"; break; + case SUBPHASE_MONUMENT: name = "Monument"; break; + default: name = "Unknown"; break; + } + return name + ": " + (m_sunsReachData.m_subphaseMask & subPhase ? "100%" : std::to_string(m_sunsReachData.GetSubPhasePercentage(subPhase)) + "%"); + }; + + auto formatCounter = [](uint32 counter, uint32 value) -> std::string { + switch (counter) + { + case COUNTER_ERRATIC_BEHAVIOR: + return "Erratic Behavior: " + std::to_string(value) + " (counts towards Phase 2: Sanctum)"; + case COUNTER_SANCTUM_WARDS: + return "Sanctum Wards: " + std::to_string(value) + " (counts towards Phase 2: Sanctum)"; + case COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY: + return "Battle for the Sun's Reach Armory: " + std::to_string(value) + " (counts towards Phase 3: Armory)"; + case COUNTER_DISTRACTION_AT_THE_DEAD_SCAR: + return "Distraction at the Dead Scar: " + std::to_string(value) + " (counts towards Phase 3: Armory)"; + case COUNTER_INTERCEPTING_THE_MANA_CELLS: + return "Intercepting the Mana Cells: " + std::to_string(value) + " (counts towards Subphase: Portal)"; + case COUNTER_INTERCEPT_THE_REINFORCEMENTS: + return "Intercept the Reinforcements: " + std::to_string(value) + " (counts towards Phase 4: Harbor)"; + case COUNTER_TAKING_THE_HARBOR: + return "Taking the Harbor: " + std::to_string(value) + " (counts towards Phase 4: Harbor)"; + case COUNTER_MAKING_READY: + return "Making Ready: " + std::to_string(value) + " (counts towards Subphase: Anvil)"; + case COUNTER_DISCOVERING_YOUR_ROOTS: + return "Discovering Your Roots: " + std::to_string(value) + " (counts towards Subphase: Alchemy Lab)"; + case COUNTER_A_CHARITABLE_DONATION: + return "A Charitable Donation: " + std::to_string(value) + " (counts towards Subphase: Monument)"; + default: + return "Unknown: " + std::to_string(value) + " (Unknown goal)"; + } + }; + + std::string output = formatPhase(); + output += "Subphase mask: " + std::to_string(m_sunsReachData.m_subphaseMask) + "\n"; + for (uint32 i = 0; i < 4; ++i) + { + uint32 subPhaseMask = 1 << i; + output += " " + formatSubPhase(subPhaseMask) + "\n"; + } + output += "Counters:\n"; + output += " Sunsreach.CounterMax = " + std::to_string(sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)) + "\n"; + for (uint32 i = 0; i < COUNTERS_MAX; ++i) + output += " " + std::to_string(i) + ". " + formatCounter(i, m_sunsReachData.m_sunsReachReclamationCounters[i]) + "\n"; + + // Sunwell Gates + auto formatGatePhase = [](uint32 gate) -> std::string { + switch (gate) + { + case SUNWELL_ALL_GATES_CLOSED: return "All Gates Closed"; break; + case SUNWELL_AGAMATH_GATE1_OPEN: return "Gate 1 Agamath Open"; break; + case SUNWELL_ROHENDOR_GATE2_OPEN: return "Gate 2 Rohendar Open"; break; + case SUNWELL_ARCHONISUS_GATE3_OPEN: return "Gate 3 Archonisus Open"; break; + default: return "Unknown"; break; + } + }; + output += "Sunwell Plateau Gate Phase " + std::to_string(m_sunsReachData.m_gate) + " (" + formatGatePhase(m_sunsReachData.m_gate) + ")" + ":\n"; + output += " 0. Gate 1 (Agamath): " + std::string(m_sunsReachData.m_gate >= SUNWELL_AGAMATH_GATE1_OPEN ? "Open " : "Closed ") + std::to_string(m_sunsReachData.m_sunsReachReclamationCounters[COUNTER_AGAMATH_THE_FIRST_GATE]) + " (" + std::to_string(m_sunsReachData.GetSunwellGatePercentage(SUNWELL_ALL_GATES_CLOSED)) + "%)\n"; + output += " 1. Gate 2 (Rohendor): " + std::string(m_sunsReachData.m_gate >= SUNWELL_ROHENDOR_GATE2_OPEN ? "Open " : "Closed ") + std::to_string(m_sunsReachData.m_sunsReachReclamationCounters[COUNTER_ROHENDOR_THE_SECOND_GATE]) + " (" + std::to_string(m_sunsReachData.GetSunwellGatePercentage(SUNWELL_AGAMATH_GATE1_OPEN)) + "%)\n"; + output += " 2. Gate 3 (Archonisus): " + std::string(m_sunsReachData.m_gate >= SUNWELL_ARCHONISUS_GATE3_OPEN ? "Open " : "Closed ") + std::to_string(m_sunsReachData.m_sunsReachReclamationCounters[COUNTER_ARCHONISUS_THE_FINAL_GATE]) + " (" + std::to_string(m_sunsReachData.GetSunwellGatePercentage(SUNWELL_ROHENDOR_GATE2_OPEN)) + "%)\n"; + return output; +} + +std::string SunsReachReclamationData::GetData() +{ + std::string output = std::to_string(m_phase) + " " + std::to_string(m_subphaseMask); + for (uint32 value : m_sunsReachReclamationCounters) + output += " " + std::to_string(value); + output += " " + std::to_string(m_gate); + for (uint32 value : m_gateCounters) + output += " " + std::to_string(value); + return output; +} + +uint32 SunsReachReclamationData::GetPhasePercentage(uint32 phase) +{ + switch (phase) + { + case SUNS_REACH_PHASE_1_STAGING_AREA: return uint32((m_sunsReachReclamationCounters[COUNTER_ERRATIC_BEHAVIOR] + m_sunsReachReclamationCounters[COUNTER_SANCTUM_WARDS]) * 100 / (2 * sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX))); + case SUNS_REACH_PHASE_2_SANCTUM: return uint32((m_sunsReachReclamationCounters[COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY] + m_sunsReachReclamationCounters[COUNTER_DISTRACTION_AT_THE_DEAD_SCAR]) * 100 / (2 * sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX))); + case SUNS_REACH_PHASE_3_ARMORY: return uint32((m_sunsReachReclamationCounters[COUNTER_INTERCEPT_THE_REINFORCEMENTS] + m_sunsReachReclamationCounters[COUNTER_TAKING_THE_HARBOR]) * 100 / (2 * sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX))); + default: return 0; + } +} + +uint32 SunsReachReclamationData::GetSubPhasePercentage(uint32 subPhase) +{ + switch (subPhase) + { + case SUBPHASE_PORTAL: return uint32(m_sunsReachReclamationCounters[COUNTER_INTERCEPTING_THE_MANA_CELLS] * 100 / sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)); + case SUBPHASE_ANVIL: return uint32(m_sunsReachReclamationCounters[COUNTER_MAKING_READY] * 100 / sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)); + case SUBPHASE_ALCHEMY_LAB: return uint32(m_sunsReachReclamationCounters[COUNTER_DISCOVERING_YOUR_ROOTS] * 100 / sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)); + case SUBPHASE_MONUMENT: return uint32(m_sunsReachReclamationCounters[COUNTER_A_CHARITABLE_DONATION] * 100 / sWorld->getIntConfig(CONFIG_SUNSREACH_COUNTER_MAX)); + default: return 0; + } +} + +enum WorldStateSunwellGateQuests +{ + // Sunwell Plateau PTR progressive release gates + QUEST_AGAMATH_THE_FIRST_GATE = 11551, + QUEST_ROHENDOR_THE_SECOND_GATE = 11552, + QUEST_ARCHONISUS_THE_FINAL_GATE = 11553, + COUNTER_MAX_VAL_REQ_SWP_GATES = 80, +}; + +void WorldState::AddSunwellGateProgress(uint32 questId) +{ + uint32 counter = 0; + int32 worldState = 0; + uint32 addedValue = 1; + switch (questId) + { + case QUEST_AGAMATH_THE_FIRST_GATE: + case QUEST_ROHENDOR_THE_SECOND_GATE: + case QUEST_ARCHONISUS_THE_FINAL_GATE: + break; + default: return; + } + switch (m_sunsReachData.m_gate) + { + case SUNWELL_ALL_GATES_CLOSED: counter = COUNTER_AGAMATH_THE_FIRST_GATE; worldState = WORLD_STATE_AGAMATH_THE_FIRST_GATE_HEALTH; break; + case SUNWELL_AGAMATH_GATE1_OPEN: counter = COUNTER_ROHENDOR_THE_SECOND_GATE; worldState = WORLD_STATE_ROHENDOR_THE_SECOND_GATE_HEALTH; break; + case SUNWELL_ROHENDOR_GATE2_OPEN: counter = COUNTER_ARCHONISUS_THE_FINAL_GATE; worldState = WORLD_STATE_ARCHONISUS_THE_FINAL_GATE_HEALTH; break; + default: return; + } + uint32 previousValue = m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate); + uint32 newValue = 0; + m_sunsReachData.m_gateCounters[counter] += addedValue; + newValue = m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate); + if (previousValue != newValue) + SendWorldstateUpdate(m_sunsReachData.m_sunsReachReclamationMutex, m_sunsReachData.m_sunsReachReclamationPlayers, newValue, worldState); + bool save = true; + if (m_sunsReachData.m_gateCounters[counter] >= COUNTER_MAX_VAL_REQ_SWP_GATES) + { + save = false; + switch (questId) + { + case QUEST_AGAMATH_THE_FIRST_GATE: + { + if (m_sunsReachData.m_gate == SUNWELL_ALL_GATES_CLOSED) + HandleSunwellGateTransition(SUNWELL_AGAMATH_GATE1_OPEN); + break; + } + case QUEST_ROHENDOR_THE_SECOND_GATE: + { + if (m_sunsReachData.m_gate == SUNWELL_AGAMATH_GATE1_OPEN) + HandleSunwellGateTransition(SUNWELL_ROHENDOR_GATE2_OPEN); + break; + } + case QUEST_ARCHONISUS_THE_FINAL_GATE: + { + if (m_sunsReachData.m_gate == SUNWELL_ROHENDOR_GATE2_OPEN) + HandleSunwellGateTransition(SUNWELL_ARCHONISUS_GATE3_OPEN); + break; + } + } + } + if (save) + Save(SAVE_ID_QUEL_DANAS); +} + +void WorldState::SetSunwellGateCounter(SunwellGateCounters index, uint32 value) +{ + m_sunsReachData.m_gateCounters[index] = value; +} + +void WorldState::StartSunwellGatePhase() +{ + switch (m_sunsReachData.m_gate) + { + case SUNWELL_ALL_GATES_CLOSED: sGameEventMgr->StartEvent(GAME_EVENT_SWP_GATES_PHASE_0); break; + case SUNWELL_AGAMATH_GATE1_OPEN: sGameEventMgr->StartEvent(GAME_EVENT_SWP_GATES_PHASE_1); break; + case SUNWELL_ROHENDOR_GATE2_OPEN: sGameEventMgr->StartEvent(GAME_EVENT_SWP_GATES_PHASE_2); break; + case SUNWELL_ARCHONISUS_GATE3_OPEN: sGameEventMgr->StartEvent(GAME_EVENT_SWP_GATES_PHASE_3); break; + default: break; + } +} + +void WorldState::StopSunwellGatePhase() +{ + switch (m_sunsReachData.m_gate) + { + case SUNWELL_ALL_GATES_CLOSED: sGameEventMgr->StopEvent(GAME_EVENT_SWP_GATES_PHASE_0); break; + case SUNWELL_AGAMATH_GATE1_OPEN: sGameEventMgr->StopEvent(GAME_EVENT_SWP_GATES_PHASE_1); break; + case SUNWELL_ROHENDOR_GATE2_OPEN: sGameEventMgr->StopEvent(GAME_EVENT_SWP_GATES_PHASE_2); break; + case SUNWELL_ARCHONISUS_GATE3_OPEN: sGameEventMgr->StopEvent(GAME_EVENT_SWP_GATES_PHASE_3); break; + default: break; + } +} + +uint32 SunsReachReclamationData::GetSunwellGatePercentage(uint32 gate) +{ + int32 percentage = 0; + switch (gate) + { + case SUNWELL_ALL_GATES_CLOSED: + percentage = 100 - int32(m_gateCounters[COUNTER_AGAMATH_THE_FIRST_GATE] * 100 / COUNTER_MAX_VAL_REQ_SWP_GATES); + break; + case SUNWELL_AGAMATH_GATE1_OPEN: + percentage = 100 - int32(m_gateCounters[COUNTER_ROHENDOR_THE_SECOND_GATE] * 100 / COUNTER_MAX_VAL_REQ_SWP_GATES); + break; + case SUNWELL_ROHENDOR_GATE2_OPEN: + percentage = 100 - int32(m_gateCounters[COUNTER_ARCHONISUS_THE_FINAL_GATE] * 100 / COUNTER_MAX_VAL_REQ_SWP_GATES); + break; + default: + return 0; + } + return percentage < 0 ? 0 : uint32(percentage); +} + +void WorldState::FillInitialWorldStates(ByteBuffer& data, uint32 zoneId, uint32 /*areaId*/) +{ + switch (zoneId) + { + case ZONEID_ISLE_OF_QUEL_DANAS: + case ZONEID_MAGISTERS_TERRACE: + case ZONEID_SUNWELL_PLATEAU: + case ZONEID_SHATTRATH: + { + // Sunwell Reclamation + switch (m_sunsReachData.m_phase) + { + case SUNS_REACH_PHASE_1_STAGING_AREA: + data << WORLD_STATE_QUEL_DANAS_SANCTUM << m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase); + break; + case SUNS_REACH_PHASE_2_SANCTUM: + data << WORLD_STATE_QUEL_DANAS_ARMORY << m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase); + break; + case SUNS_REACH_PHASE_3_ARMORY: + data << WORLD_STATE_QUEL_DANAS_HARBOR << m_sunsReachData.GetPhasePercentage(m_sunsReachData.m_phase); + break; + case SUNS_REACH_PHASE_4_HARBOR: + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_ALCHEMY_LAB) == 0) + data << WORLD_STATE_QUEL_DANAS_ALCHEMY_LAB << m_sunsReachData.GetSubPhasePercentage(SUBPHASE_ALCHEMY_LAB); + if ((m_sunsReachData.m_subphaseMask & SUBPHASE_MONUMENT) == 0) + data << WORLD_STATE_QUEL_DANAS_MONUMENT << m_sunsReachData.GetSubPhasePercentage(SUBPHASE_MONUMENT); + break; + } + if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_2_SANCTUM && (m_sunsReachData.m_subphaseMask & SUBPHASE_PORTAL) == 0) + data << WORLD_STATE_QUEL_DANAS_PORTAL << m_sunsReachData.GetSubPhasePercentage(SUBPHASE_PORTAL); + if (m_sunsReachData.m_phase >= SUNS_REACH_PHASE_3_ARMORY && (m_sunsReachData.m_subphaseMask & SUBPHASE_ANVIL) == 0) + data << WORLD_STATE_QUEL_DANAS_ANVIL << m_sunsReachData.GetSubPhasePercentage(SUBPHASE_ANVIL); + data << WORLD_STATE_QUEL_DANAS_MUSIC << m_sunsReachData.m_phase; + + // Sunwell Gates + switch (m_sunsReachData.m_gate) + { + case SUNWELL_ALL_GATES_CLOSED: + data << WORLD_STATE_AGAMATH_THE_FIRST_GATE_HEALTH << m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate); + break; + case SUNWELL_AGAMATH_GATE1_OPEN: + data << WORLD_STATE_ROHENDOR_THE_SECOND_GATE_HEALTH << m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate); + break; + case SUNWELL_ROHENDOR_GATE2_OPEN: + data << WORLD_STATE_ARCHONISUS_THE_FINAL_GATE_HEALTH << m_sunsReachData.GetSunwellGatePercentage(m_sunsReachData.m_gate); + break; + } + break; + } + } +} diff --git a/src/server/game/World/WorldState.h b/src/server/game/World/WorldState.h index d708bdcaf..81a084e34 100644 --- a/src/server/game/World/WorldState.h +++ b/src/server/game/World/WorldState.h @@ -21,6 +21,24 @@ #include "Player.h" #include +// TODO: Move these to WorldStateDefines.h +enum WorldStateWorldStates +{ + // Sun's Reach Reclamation + WORLD_STATE_QUEL_DANAS_MUSIC = 3426, + WORLD_STATE_QUEL_DANAS_HARBOR = 3238, + WORLD_STATE_QUEL_DANAS_ALCHEMY_LAB = 3223, + WORLD_STATE_QUEL_DANAS_ARMORY = 3233, + WORLD_STATE_QUEL_DANAS_SANCTUM = 3244, + WORLD_STATE_QUEL_DANAS_PORTAL = 3269, + WORLD_STATE_QUEL_DANAS_ANVIL = 3228, + WORLD_STATE_QUEL_DANAS_MONUMENT = 3275, + // Sunwell Gate + WORLD_STATE_AGAMATH_THE_FIRST_GATE_HEALTH = 3253, // guessed, potentially wrong + WORLD_STATE_ROHENDOR_THE_SECOND_GATE_HEALTH = 3255, + WORLD_STATE_ARCHONISUS_THE_FINAL_GATE_HEALTH = 3257, +}; + enum WorldStateCondition { WORLD_STATE_CONDITION_TROLLBANES_COMMAND = 39911, @@ -56,6 +74,10 @@ enum WorldStateZoneId ZONEID_BLOOD_FURNACE = 3713, ZONEID_SHATTERED_HALLS = 3714, ZONEID_MAGTHERIDON_LAIR = 3836, + + ZONEID_ISLE_OF_QUEL_DANAS = 4080, + ZONEID_MAGISTERS_TERRACE = 4131, + ZONEID_SUNWELL_PLATEAU = 4075, }; enum WorldStateSpells @@ -64,6 +86,105 @@ enum WorldStateSpells SPELL_TROLLBANES_COMMAND = 39911, SPELL_NAZGRELS_FAVOR = 39913, + + SPELL_KIRU_SONG_OF_VICTORY = 46302, +}; + +enum WorldStateSaveIds +{ + SAVE_ID_QUEL_DANAS = 20, +}; + +enum WorldStateGameEvents +{ + // Isle phases + GAME_EVENT_QUEL_DANAS_PHASE_1 = 101, + GAME_EVENT_QUEL_DANAS_PHASE_2_ONLY = 102, + GAME_EVENT_QUEL_DANAS_PHASE_2_PERMANENT = 103, + GAME_EVENT_QUEL_DANAS_PHASE_2_NO_PORTAL = 104, + GAME_EVENT_QUEL_DANAS_PHASE_2_PORTAL = 105, + GAME_EVENT_QUEL_DANAS_PHASE_3_ONLY = 106, + GAME_EVENT_QUEL_DANAS_PHASE_3_PERMANENT = 107, + GAME_EVENT_QUEL_DANAS_PHASE_3_NO_ANVIL = 108, + GAME_EVENT_QUEL_DANAS_PHASE_3_ANVIL = 109, + GAME_EVENT_QUEL_DANAS_PHASE_4 = 110, + GAME_EVENT_QUEL_DANAS_PHASE_4_NO_MONUMENT = 111, + GAME_EVENT_QUEL_DANAS_PHASE_4_MONUMENT = 112, + GAME_EVENT_QUEL_DANAS_PHASE_4_NO_ALCHEMY_LAB= 113, + GAME_EVENT_QUEL_DANAS_PHASE_4_ALCHEMY_LAB = 114, + GAME_EVENT_QUEL_DANAS_PHASE_4_KIRU = 115, + // SWP Phases + GAME_EVENT_SWP_GATES_PHASE_0 = 116, // All Gates Closed + GAME_EVENT_SWP_GATES_PHASE_1 = 117, // First Gate Open + GAME_EVENT_SWP_GATES_PHASE_2 = 118, // Second Gate Open + GAME_EVENT_SWP_GATES_PHASE_3 = 119, // All Gates Open +}; + +enum SunsReachPhases +{ + SUNS_REACH_PHASE_1_STAGING_AREA, + SUNS_REACH_PHASE_2_SANCTUM, + SUNS_REACH_PHASE_3_ARMORY, + SUNS_REACH_PHASE_4_HARBOR, +}; + +enum SunsReachSubPhases +{ + SUBPHASE_PORTAL = 0x01, + SUBPHASE_ANVIL = 0x02, + SUBPHASE_ALCHEMY_LAB = 0x04, + SUBPHASE_MONUMENT = 0x08, + SUBPHASE_ALL = SUBPHASE_PORTAL | SUBPHASE_ANVIL | SUBPHASE_ALCHEMY_LAB | SUBPHASE_MONUMENT, +}; + +enum SunsReachCounters +{ + COUNTER_ERRATIC_BEHAVIOR, + COUNTER_SANCTUM_WARDS, + COUNTER_BATTLE_FOR_THE_SUNS_REACH_ARMORY, + COUNTER_DISTRACTION_AT_THE_DEAD_SCAR, + COUNTER_INTERCEPTING_THE_MANA_CELLS, + COUNTER_INTERCEPT_THE_REINFORCEMENTS, + COUNTER_TAKING_THE_HARBOR, + COUNTER_MAKING_READY, + COUNTER_DISCOVERING_YOUR_ROOTS, + COUNTER_A_CHARITABLE_DONATION, + COUNTERS_MAX, +}; + +enum SunwellGates +{ + SUNWELL_ALL_GATES_CLOSED, + SUNWELL_AGAMATH_GATE1_OPEN, + SUNWELL_ROHENDOR_GATE2_OPEN, + SUNWELL_ARCHONISUS_GATE3_OPEN, +}; +enum SunwellGateCounters +{ + COUNTER_AGAMATH_THE_FIRST_GATE, + COUNTER_ROHENDOR_THE_SECOND_GATE, + COUNTER_ARCHONISUS_THE_FINAL_GATE, + COUNTERS_MAX_GATES, +}; + +struct SunsReachReclamationData +{ + uint32 m_phase; + uint32 m_subphaseMask; + uint32 m_sunsReachReclamationCounters[COUNTERS_MAX]; + GuidVector m_sunsReachReclamationPlayers; + std::mutex m_sunsReachReclamationMutex; + uint32 m_gate; + uint32 m_gateCounters[COUNTERS_MAX_GATES]; + SunsReachReclamationData() : m_phase(SUNS_REACH_PHASE_1_STAGING_AREA), m_subphaseMask(0), m_gate(SUNWELL_ALL_GATES_CLOSED) + { + memset(m_sunsReachReclamationCounters, 0, sizeof(m_sunsReachReclamationCounters)); + memset(m_gateCounters, 0, sizeof(m_gateCounters)); + } + std::string GetData(); + uint32 GetPhasePercentage(uint32 phase); + uint32 GetSubPhasePercentage(uint32 subPhase); + uint32 GetSunwellGatePercentage(uint32 gate); }; // Intended for implementing server wide scripts, note: all behaviour must be safeguarded towards multithreading @@ -73,13 +194,30 @@ class WorldState WorldState(); virtual ~WorldState(); static WorldState* instance(); + void Load(); + void Save(WorldStateSaveIds saveId); + void SaveHelper(std::string& stringToSave, WorldStateSaveIds saveId); void HandlePlayerEnterZone(Player* player, WorldStateZoneId zoneId); void HandlePlayerLeaveZone(Player* player, WorldStateZoneId zoneId); bool IsConditionFulfilled(WorldStateCondition conditionId, WorldStateConditionState state = WORLD_STATE_CONDITION_STATE_NONE) const; void HandleConditionStateChange(WorldStateCondition conditionId, WorldStateConditionState state); void HandleExternalEvent(WorldStateEvent eventId, uint32 param); void Update(uint32 diff); + void AddSunwellGateProgress(uint32 questId); + void AddSunsReachProgress(uint32 questId); + std::string GetSunsReachPrintout(); + void FillInitialWorldStates(ByteBuffer& data, uint32 zoneId, uint32 areaId); + void HandleSunsReachPhaseTransition(uint32 newPhase); + void HandleSunsReachSubPhaseTransition(int32 subPhaseMask, bool initial = false); + void SetSunsReachCounter(SunsReachCounters index, uint32 value); + void HandleSunwellGateTransition(uint32 newGate); + void SetSunwellGateCounter(SunwellGateCounters index, uint32 value); private: + void SendWorldstateUpdate(std::mutex& mutex, GuidVector const& guids, uint32 value, uint32 worldStateId); + void StopSunsReachPhase(bool forward); + void StartSunsReachPhase(bool initial = false); + void StartSunwellGatePhase(); + void StopSunwellGatePhase(); void BuffAdalsSongOfBattle(); void DispelAdalsSongOfBattle(); uint32 _adalSongOfBattleTimer; @@ -87,6 +225,7 @@ class WorldState void DispelMagtheridonTeam(TeamId team); bool _isMagtheridonHeadSpawnedHorde; bool _isMagtheridonHeadSpawnedAlliance; + SunsReachReclamationData m_sunsReachData; std::map> _transportStates; // atomic to avoid having to lock std::mutex _mutex; // all World State operations are threat unsafe }; diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 6aa610ef5..d8d1ff962 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -292,7 +292,7 @@ public: Player const* target = player->GetConnectedPlayer(); LocaleConstant loc = handler->GetSessionDbcLocale(); - char const* knownStr = handler->GetAcoreString(LANG_KNOWN); + std::string knownStr = handler->GetAcoreString(LANG_KNOWN); // Search in CharTitles.dbc for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) @@ -308,7 +308,7 @@ public: if (!*name) continue; - char const* activeStr = ""; + std::string activeStr = ""; if (target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index) activeStr = handler->GetAcoreString(LANG_ACTIVE); diff --git a/src/server/scripts/Commands/cs_event.cpp b/src/server/scripts/Commands/cs_event.cpp index 45dffdd7e..d8cfdde57 100644 --- a/src/server/scripts/Commands/cs_event.cpp +++ b/src/server/scripts/Commands/cs_event.cpp @@ -61,28 +61,22 @@ public: GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList(); - char const* active = handler->GetAcoreString(LANG_ACTIVE); + std::string active = handler->GetAcoreString(LANG_ACTIVE); for (uint16 eventId : activeEvents) { GameEventData const& eventData = events[eventId]; if (handler->GetSession()) - { handler->PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, eventId, eventId, eventData.description, active); - } else - { handler->PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, eventId, eventData.description, active); - } ++counter; } if (counter == 0) - { handler->SendSysMessage(LANG_NOEVENTFOUND); - } handler->SetSentErrorMessage(true); @@ -108,7 +102,7 @@ public: GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr->GetActiveEventList(); bool active = activeEvents.find(eventId) != activeEvents.end(); - char const* activeStr = active ? handler->GetAcoreString(LANG_ACTIVE) : ""; + std::string activeStr = active ? handler->GetAcoreString(LANG_ACTIVE) : ""; std::string startTimeStr = Acore::Time::TimeToTimestampStr(Seconds(eventData.start)); std::string endTimeStr = Acore::Time::TimeToTimestampStr(Seconds(eventData.end)); diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index bb66e326c..9d3b45e88 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -460,8 +460,8 @@ public: wstrToLower(namePart); - char const* talentStr = handler->GetAcoreString(LANG_TALENT); - char const* passiveStr = handler->GetAcoreString(LANG_PASSIVE); + std::string talentStr = handler->GetAcoreString(LANG_TALENT); + std::string passiveStr = handler->GetAcoreString(LANG_PASSIVE); Unit::AuraApplicationMap const& auras = unit->GetAppliedAuras(); handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, auras.size()); diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index d64065bcc..27ba9f67d 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -308,7 +308,7 @@ public: return true; } - char const* active = activeEvents.find(id) != activeEvents.end() ? handler->GetAcoreString(LANG_ACTIVE) : ""; + std::string active = activeEvents.find(id) != activeEvents.end() ? handler->GetAcoreString(LANG_ACTIVE) : ""; if (handler->GetSession()) { @@ -806,7 +806,7 @@ public: return true; } - char const* statusStr = ""; + std::string statusStr = ""; if (target) { @@ -862,7 +862,7 @@ public: return true; } - char const* statusStr = ""; + std::string statusStr = ""; if (target) { @@ -1498,20 +1498,16 @@ public: return true; } - char const* knownStr = target && target->HasTitle(titleInfo) ? handler->GetAcoreString(LANG_KNOWN) : ""; - char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index ? handler->GetAcoreString(LANG_ACTIVE) : ""; + std::string knownStr = target && target->HasTitle(titleInfo) ? handler->GetAcoreString(LANG_KNOWN) : ""; + std::string activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index ? handler->GetAcoreString(LANG_ACTIVE) : ""; std::string titleNameStr = Acore::StringFormat(name, targetName); // send title in "id (idx:idx) - [namedlink locale]" format if (handler->GetSession()) - { handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, titleInfo->ID, titleInfo->bit_index, titleInfo->ID, titleNameStr, localeNames[locale], knownStr, activeStr); - } else - { handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, titleInfo->ID, titleInfo->bit_index, titleNameStr, localeNames[locale], knownStr, activeStr); - } ++counter; } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 096e8fb62..3e6a56e50 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1992,8 +1992,8 @@ public: uint32 mapId; uint32 areaId; uint32 phase = 0; - char const* areaName = nullptr; - char const* zoneName = nullptr; + std::string areaName = ""; + std::string zoneName = ""; // Guild data print variables defined so that they exist, but are not necessarily used uint32 guildId = 0; @@ -2325,19 +2325,13 @@ public: } } - if (!zoneName) - { + if (zoneName.empty()) zoneName = handler->GetAcoreString(LANG_UNKNOWN); - } - if (areaName) - { + if (!areaName.empty()) handler->PSendSysMessage(LANG_PINFO_CHR_MAP_WITH_AREA, map->name[locale], zoneName, areaName); - } else - { handler->PSendSysMessage(LANG_PINFO_CHR_MAP, map->name[locale], zoneName); - } // Output XVII. - XVIX. if they are not empty if (!guildName.empty()) @@ -3022,18 +3016,9 @@ public: return false; } - const char* str = sObjectMgr->GetAcoreString(id, locale ? static_cast(*locale) : DEFAULT_LOCALE); - - if (!strcmp(str, "")) - { - handler->PSendSysMessage(LANG_NO_ACORE_STRING_FOUND, id); - return true; - } - else - { - handler->SendSysMessage(str); - return true; - } + std::string str = sObjectMgr->GetAcoreString(id, locale ? static_cast(*locale) : DEFAULT_LOCALE); + handler->SendSysMessage(str); + return true; } static bool HandleOpenDoorCommand(ChatHandler* handler, Optional range) diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 76201a55c..130ec7686 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -217,8 +217,7 @@ public: static bool HandleMmapStatsCommand(ChatHandler* handler) { handler->PSendSysMessage("mmap stats:"); - //handler->PSendSysMessage(" global mmap pathfinding is {}abled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis"); - + //handler->PSendSysMessage(" global mmap pathfinding is {}abled", sDisableMgr->IsPathfindingEnabled(mapId) ? "en" : "dis"); MMAP::MMapMgr* manager = MMAP::MMapFactory::createOrGetMMapMgr(); handler->PSendSysMessage(" {} maps loaded with {} tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index b11eb2c1e..62bfe7712 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -1063,9 +1063,9 @@ public: static bool HandleReloadDisablesCommand(ChatHandler* handler) { LOG_INFO("server.loading", "Reloading disables table..."); - DisableMgr::LoadDisables(); + sDisableMgr->LoadDisables(); LOG_INFO("server.loading", "Checking quest disables..."); - DisableMgr::CheckQuestDisables(); + sDisableMgr->CheckQuestDisables(); handler->SendGlobalGMSysMessage("DB table `disables` reloaded."); return true; } diff --git a/src/server/scripts/Commands/cs_script_loader.cpp b/src/server/scripts/Commands/cs_script_loader.cpp index 4c7433b6b..eeb4eb4f6 100644 --- a/src/server/scripts/Commands/cs_script_loader.cpp +++ b/src/server/scripts/Commands/cs_script_loader.cpp @@ -62,6 +62,7 @@ void AddSC_wp_commandscript(); void AddSC_cache_commandscript(); void AddSC_item_commandscript(); void AddSC_player_settings_commandscript(); +void AddSC_worldstate_commandscript(); // The name of this function should match: // void Add${NameOfDirectory}Scripts() @@ -113,4 +114,5 @@ void AddCommandsScripts() AddSC_cache_commandscript(); AddSC_item_commandscript(); AddSC_player_settings_commandscript(); + AddSC_worldstate_commandscript(); } diff --git a/src/server/scripts/Commands/cs_worldstate.cpp b/src/server/scripts/Commands/cs_worldstate.cpp new file mode 100644 index 000000000..7c1887b1c --- /dev/null +++ b/src/server/scripts/Commands/cs_worldstate.cpp @@ -0,0 +1,133 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + + /* ScriptData + Name: worldstate_commandscript + %Complete: 100 + Comment: All worldstate related commands + Category: commandscripts + EndScriptData */ + +#include "Chat.h" +#include "CommandScript.h" +#include "Common.h" +#include "WorldState.h" + +using namespace Acore::ChatCommands; + +class worldstate_commandscript : public CommandScript +{ +public: + worldstate_commandscript() : CommandScript("worldstate_commandscript") { } + + ChatCommandTable GetCommands() const override + { + static ChatCommandTable sunsreachCommandTable = + { + { "status", HandleSunsReachReclamationStatusCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "phase", HandleSunsReachReclamationPhaseCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "subphase", HandleSunsReachReclamationSubPhaseCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "counter", HandleSunsReachReclamationCounterCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "gate", HandleSunwellGateCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "gatecounter", HandleSunwellGateCounterCommand, SEC_ADMINISTRATOR, Console::Yes }, + }; + + static ChatCommandTable worldStateCommandTable = + { + { "sunsreach", sunsreachCommandTable } + }; + + static ChatCommandTable commandTable = + { + { "worldstate", worldStateCommandTable } + }; + return commandTable; + } + + static bool HandleSunsReachReclamationStatusCommand(ChatHandler* handler ) + { + handler->PSendSysMessage(sWorldState->GetSunsReachPrintout()); + return true; + } + + static bool HandleSunsReachReclamationPhaseCommand(ChatHandler* handler, uint32 phase) + { + if (phase > SUNS_REACH_PHASE_4_HARBOR) + { + handler->PSendSysMessage("Invalid phase, see \".worldstate sunsreach phase\" for usage"); + return false; + } + sWorldState->HandleSunsReachPhaseTransition(phase); + handler->PSendSysMessage(sWorldState->GetSunsReachPrintout()); + return true; + } + + static bool HandleSunsReachReclamationSubPhaseCommand(ChatHandler* handler, uint32 subphase) + { + if (subphase > SUBPHASE_ALL) + { + handler->PSendSysMessage("Invalid subphase, see \".worldstate sunsreach subphase\" for usage"); + return false; + } + sWorldState->HandleSunsReachSubPhaseTransition(subphase);; + handler->PSendSysMessage(sWorldState->GetSunsReachPrintout()); + return true; + } + + static bool HandleSunsReachReclamationCounterCommand(ChatHandler* handler, Optional index, Optional value) + { + if (!index || !value || index.value() >= COUNTERS_MAX) + { + handler->PSendSysMessage("Syntax: .worldstate sunsreach counter ."); + handler->PSendSysMessage(sWorldState->GetSunsReachPrintout()); + return true; + } + sWorldState->SetSunsReachCounter(SunsReachCounters(index.value()), value.value()); + handler->PSendSysMessage(sWorldState->GetSunsReachPrintout()); + return true; + } + + static bool HandleSunwellGateCommand(ChatHandler* handler, uint32 newGate) + { + if (newGate > SUNWELL_ARCHONISUS_GATE3_OPEN) + { + handler->PSendSysMessage("Invalid phase, see \".worldstate sunsreach gate\" for usage"); + return false; + } + sWorldState->HandleSunwellGateTransition(newGate); + handler->PSendSysMessage(sWorldState->GetSunsReachPrintout()); + return true; + } + + static bool HandleSunwellGateCounterCommand(ChatHandler* handler, Optional index, Optional value) + { + if (!index || !value || index.value() >= COUNTERS_MAX_GATES) + { + handler->PSendSysMessage("Syntax: .worldstate sunsreach gatecounter ."); + handler->PSendSysMessage(sWorldState->GetSunsReachPrintout()); + return true; + } + sWorldState->SetSunwellGateCounter(SunwellGateCounters(index.value()), value.value()); + handler->PSendSysMessage(sWorldState->GetSunsReachPrintout()); + return true; + } +}; + +void AddSC_worldstate_commandscript() +{ + new worldstate_commandscript(); +} diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp index a8d515dee..403782eed 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp @@ -21,102 +21,120 @@ enum Yells { - SAY_AGGRO = 0, - SAY_ENERGY = 1, - SAY_OVERLOAD = 2, - SAY_KILL = 3, - EMOTE_DISCHARGE_ENERGY = 4 + SAY_AGGRO = 0, // Combat start + SAY_ENERGY = 1, // Pure energy spawn + SAY_OVERLOAD = 2, // Final phase + SAY_KILL = 3, // Player kill + EMOTE_DISCHARGE_ENERGY = 4, // Energy discharge warning + EMOTE_OVERLOAD = 5 // Overload emote }; enum Spells { - // Pure energy spell info - SPELL_ENERGY_FEEDBACK_CHANNEL = 44328, - SPELL_ENERGY_FEEDBACK = 44335, - - // Vexallus spell info - SPELL_CHAIN_LIGHTNING = 44318, - SPELL_OVERLOAD = 44352, - SPELL_ARCANE_SHOCK = 44319, - - SPELL_SUMMON_PURE_ENERGY_N = 44322, - SPELL_SUMMON_PURE_ENERGY_H1 = 46154, - SPELL_SUMMON_PURE_ENERGY_H2 = 46159 -}; - -enum Misc -{ - NPC_PURE_ENERGY = 24745 + SPELL_ENERGY_FEEDBACK_CHANNEL = 44328, // Pure energy channel + SPELL_ENERGY_FEEDBACK = 44335, // Pure energy death effect + SPELL_CHAIN_LIGHTNING = 44318, // Basic attack + SPELL_OVERLOAD = 44352, // Enrage ability + SPELL_ARCANE_SHOCK = 44319, // Basic attack + SPELL_SUMMON_PURE_ENERGY_N = 44322, // Normal mode summon + SPELL_SUMMON_PURE_ENERGY_H1 = 46154, // Heroic mode summon 1 + SPELL_SUMMON_PURE_ENERGY_H2 = 46159 // Heroic mode summon 2 }; struct boss_vexallus : public BossAI { - boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS), _energyCooldown(false) { } + boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS), _energyCooldown(false), _energyCount(0) { } void Reset() override { _Reset(); _energyCooldown = false; + _energyCount = 0; ScheduleHealthCheckEvent({ 85, 70, 55, 40, 25 }, [&] { - if (!_energyCooldown) + scheduler.Schedule(1s, [this](TaskContext context) { - Talk(SAY_ENERGY); - Talk(EMOTE_DISCHARGE_ENERGY); - - if (IsHeroic()) + if (!_energyCooldown) { - DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1); - DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2); + Talk(SAY_ENERGY); + 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; + ++_energyCount; + + me->m_Events.AddEventAtOffset([&] + { + _energyCooldown = false; + }, 5s); } else - DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N); + context.Repeat(5s); - _energyCooldown = true; - scheduler.Schedule(5s, [this](TaskContext) - { - _energyCooldown = false; - }); - } + }); }); ScheduleHealthCheckEvent(20, [&] { - scheduler.CancelAll(); - DoCastSelf(SPELL_OVERLOAD, true); + scheduler.Schedule(1s, [this](TaskContext context) + { + if (_energyCount == 5 && !_energyCooldown) + { + scheduler.CancelAll(); + Talk(SAY_OVERLOAD); + Talk(EMOTE_OVERLOAD); + DoCastSelf(SPELL_OVERLOAD, true); + } + else + context.Repeat(5s); + }); }); } + void JustDied(Unit*) override + { + _JustDied(); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ENERGY_FEEDBACK); + } + void KilledUnit(Unit* victim) override { if (victim->IsPlayer()) Talk(SAY_KILL); } - void JustEngagedWith(Unit* /*who*/) override + void JustEngagedWith(Unit*) override { _JustEngagedWith(); Talk(SAY_AGGRO); - ScheduleTimedEvent(8s, [&] + ScheduleTimedEvent(5s, [&] { DoCastRandomTarget(SPELL_CHAIN_LIGHTNING); - }, 8s, 8s); + }, 8s); ScheduleTimedEvent(5s, [&] { DoCastRandomTarget(SPELL_ARCANE_SHOCK); - }, 8s, 8s); + }, 5s); } void JustSummoned(Creature* summon) override { if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) { + summon->SetReactState(REACT_PASSIVE); summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f); summon->CastSpell(target, SPELL_ENERGY_FEEDBACK_CHANNEL, false); } + summons.Summon(summon); } @@ -130,6 +148,7 @@ struct boss_vexallus : public BossAI private: bool _energyCooldown; + uint8 _energyCount; }; void AddSC_boss_vexallus() diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp index 2201e5160..a37aa61c4 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp @@ -96,14 +96,6 @@ public: if (GameObject* gobj = GetGameObject(DATA_ICEBARRIER)) gobj->SendUpdateToPlayer(player); } - - void OnCreatureCreate(Creature* creature) override - { - if (creature->GetSpawnId() > 0 || !creature->GetOwnerGUID().IsPlayer()) - creature->CastSpell(creature, SPELL_SUNWELL_RADIANCE, true); - - InstanceScript::OnCreatureCreate(creature); - } }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h index e40dfc057..83f8705a4 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h @@ -106,11 +106,6 @@ enum GameObjectIds GO_ORB_OF_THE_BLUE_DRAGONFLIGHT4 = 188116 }; -enum SpellIds -{ - SPELL_SUNWELL_RADIANCE = 45769, -}; - template inline AI* GetSunwellPlateauAI(T* obj) { diff --git a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp index 685b749c6..20843574e 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp @@ -115,11 +115,13 @@ public: for (uint8 i = 0; i < RAND_VENDOR; ++i) RandVendor[i] = NOT_STARTED; + + StorePersistentData(DATA_TIMED_RUN, 0); } void OnPlayerEnter(Player* /*player*/) override { - if (!scheduler.IsGroupScheduled(GROUP_TIMED_RUN)) + if (!scheduler.IsGroupScheduled(GROUP_TIMED_RUN) && GetPersistentData(DATA_TIMED_RUN)) DoAction(ACTION_START_TIMED_RUN); } @@ -293,53 +295,36 @@ public: if (!InstanceScript::SetBossState(type, state)) return false; - switch (type) + if (state == DONE) { - case DATA_NALORAKK: - if (state == DONE) - { + switch (type) + { + case DATA_NALORAKK: if (uint32 timer = GetPersistentData(DATA_TIMED_RUN)) { StorePersistentData(DATA_TIMED_RUN, timer += 15); DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer); } - SummonHostage(0); - } - break; - case DATA_AKILZON: - if (state == DONE) - { + SummonHostage(type); + break; + case DATA_AKILZON: if (uint32 timer = GetPersistentData(DATA_TIMED_RUN)) { StorePersistentData(DATA_TIMED_RUN, timer += 10); DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, timer); } - SummonHostage(1); - } - break; - case DATA_JANALAI: - if (state == DONE) - SummonHostage(2); - break; - case DATA_HALAZZI: - if (state == DONE) - SummonHostage(3); - break; - case DATA_HEXLORD: - if (state == IN_PROGRESS) - HandleGameObject(ObjectGuid::Empty, false, GetGameObject(DATA_HEXLORD_GATE)); - else if (state == NOT_STARTED) - CheckInstanceStatus(); - else if (state == DONE) - { + SummonHostage(type); + break; + case DATA_JANALAI: + case DATA_HALAZZI: + SummonHostage(type); + break; + case DATA_HEXLORD: if (GameObject* zuljinGate = GetGameObject(DATA_ZULJIN_GATE)) zuljinGate->RemoveGameObjectFlag(GO_FLAG_LOCKED); - } - break; - } + break; + } - if (state == DONE) - { if (GetPersistentData(DATA_TIMED_RUN) && AllBossesDone({ DATA_NALORAKK, DATA_AKILZON, DATA_JANALAI, DATA_HALAZZI })) { StorePersistentData(DATA_TIMED_RUN, 0); @@ -348,6 +333,16 @@ public: CheckInstanceStatus(); } + else + { + if (type == DATA_HEXLORD) + { + if (state == IN_PROGRESS) + HandleGameObject(ObjectGuid::Empty, false, GetGameObject(DATA_HEXLORD_GATE)); + else if (state == NOT_STARTED) + CheckInstanceStatus(); + } + } return true; } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp index c0c95f6c7..2c6a3d06b 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp @@ -191,7 +191,7 @@ public: if (creature->IsSummon() && _bossWave != TO_BE_DECIDED) { if (_currentWave == 0) - creature->SetDisableReputationGain(true); + creature->SetReputationRewardDisabled(true); DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, ++trash); // Update the instance wave count on new trash spawn _encounterNPCs.insert(creature->GetGUID()); // Used for despawning on wipe } diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp index 9807f0244..217e1915d 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp @@ -107,7 +107,7 @@ public: InstanceScript* pInstance; EventMap events; - bool lock; + bool lock, inCenter; float x, y, z; int32 releaseLockTimer; @@ -134,6 +134,7 @@ public: me->CastSpell(me, SPELL_EVOCATION, true); events.Reset(); lock = false; + inCenter = false; x = 0.0f; y = 0.0f; z = 0.0f; @@ -222,9 +223,14 @@ public: { pInstance->SetData(DATA_UROM, DONE); } - me->SetCanFly(false); - me->SetDisableGravity(false); - me->NearTeleportTo(x, y, z, 0.0f); + + // Body teleportation required only when boss is flying in the center + if (inCenter) + { + me->SetCanFly(false); + me->SetDisableGravity(false); + me->NearTeleportTo(x, y, z, 0.0f); + } } void KilledUnit(Unit* /*victim*/) override @@ -281,6 +287,7 @@ public: me->SetCanFly(true); me->SetDisableGravity(true); me->NearTeleportTo(1103.69f, 1048.76f, 512.279f, 1.16f); + inCenter = true; Talk(SAY_ARCANE_EXPLOSION); Talk(EMOTE_ARCANE_EXPLOSION); @@ -356,6 +363,7 @@ public: me->SetControlled(false, UNIT_STATE_ROOT); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->GetMotionMaster()->MoveChase(me->GetVictim()); + inCenter = false; break; } } @@ -365,6 +373,7 @@ public: me->SetCanFly(false); me->SetDisableGravity(false); me->SetControlled(false, UNIT_STATE_ROOT); + inCenter = false; ScriptedAI::EnterEvadeMode(why); } }; diff --git a/src/server/scripts/World/suns_reach_reclamation.cpp b/src/server/scripts/World/suns_reach_reclamation.cpp new file mode 100644 index 000000000..4a81e3537 --- /dev/null +++ b/src/server/scripts/World/suns_reach_reclamation.cpp @@ -0,0 +1,49 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "CreatureScript.h" +#include "WorldState.h" + +class npc_suns_reach_reclamation : public CreatureScript +{ +public: + npc_suns_reach_reclamation() : CreatureScript("npc_suns_reach_reclamation") { } + + bool OnQuestReward(Player* /*player*/, Creature* /*creature*/, const Quest* quest, uint32 /*slot*/) override + { + sWorldState->AddSunsReachProgress(quest->GetQuestId()); + return true; + } +}; + +class npc_sunwell_gate : public CreatureScript +{ +public: + npc_sunwell_gate() : CreatureScript("npc_sunwell_gate") { } + + bool OnQuestReward(Player* /*player*/, Creature* /*creature*/, const Quest* quest, uint32 /*slot*/) override + { + sWorldState->AddSunwellGateProgress(quest->GetQuestId()); + return true; + } +}; + +void AddSC_suns_reach_reclamation() +{ + new npc_suns_reach_reclamation(); + new npc_sunwell_gate(); +} diff --git a/src/server/scripts/World/world_script_loader.cpp b/src/server/scripts/World/world_script_loader.cpp index 21813fd4c..66b168e4f 100644 --- a/src/server/scripts/World/world_script_loader.cpp +++ b/src/server/scripts/World/world_script_loader.cpp @@ -33,6 +33,7 @@ void AddSC_player_scripts(); void AddSC_npc_stave_of_ancients(); void AddSC_server_mail(); void AddSC_transport_zeppelins(); +void AddSC_suns_reach_reclamation(); // The name of this function should match: // void Add${NameOfDirectory}Scripts() @@ -55,4 +56,5 @@ void AddWorldScripts() AddSC_npc_stave_of_ancients(); AddSC_server_mail(); AddSC_transport_zeppelins(); + AddSC_suns_reach_reclamation(); } diff --git a/src/test/mocks/WorldMock.h b/src/test/mocks/WorldMock.h index 9a3423e59..11823fcf3 100644 --- a/src/test/mocks/WorldMock.h +++ b/src/test/mocks/WorldMock.h @@ -75,7 +75,7 @@ public: MOCK_METHOD(void, SendGlobalMessage, (WorldPacket const* packet, WorldSession* self, TeamId teamId), ()); MOCK_METHOD(void, SendGlobalGMMessage, (WorldPacket const* packet, WorldSession* self, TeamId teamId), ()); MOCK_METHOD(bool, SendZoneMessage, (uint32 zone, WorldPacket const* packet, WorldSession* self, TeamId teamId), ()); - MOCK_METHOD(void, SendZoneText, (uint32 zone, const char* text, WorldSession* self, TeamId teamId), ()); + MOCK_METHOD(void, SendZoneText, (uint32 zone, std::string text, WorldSession* self, TeamId teamId), ()); MOCK_METHOD(void, SendServerMessage, (ServerMessageType messageID, std::string stringParam, Player* player)); MOCK_METHOD(bool, IsShuttingDown, (), (const)); MOCK_METHOD(uint32, GetShutDownTimeLeft, (), (const));