From c2986977d9767dc1c183ab2ba151dd55cf92f060 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Tue, 11 Feb 2025 17:23:01 +0100 Subject: [PATCH 01/97] fix(Core/Items): Fix duplication exploit where a player could loot infinitely from bags containing gold. (#21394) --- src/server/game/Loot/LootItemStorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/Loot/LootItemStorage.cpp b/src/server/game/Loot/LootItemStorage.cpp index d453e08cd..e5b6de588 100644 --- a/src/server/game/Loot/LootItemStorage.cpp +++ b/src/server/game/Loot/LootItemStorage.cpp @@ -249,7 +249,7 @@ void LootItemStorage::RemoveStoredLootItem(ObjectGuid containerGUID, uint32 item // loot with empty itemList but unlootedCount > 0 // must be deleted manually by the player or traded - if (!loot->unlootedCount) + if (!loot->unlootedCount && !loot->gold) lootItemStore.erase(itr); } From 07cb5c880c90cbb325d2ed20d99863a0ab248c09 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Tue, 11 Feb 2025 17:24:56 +0100 Subject: [PATCH 02/97] fix(Core/SQLField): Fix heap-buffer-overflow issue when interacting with mysql field value. (#21393) --- src/server/database/Database/Field.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/database/Database/Field.cpp b/src/server/database/Database/Field.cpp index 1120b754e..83158aab9 100644 --- a/src/server/database/Database/Field.cpp +++ b/src/server/database/Database/Field.cpp @@ -212,7 +212,7 @@ T Field::GetData() const if (data.raw) result = *reinterpret_cast(data.value); else - result = Acore::StringTo(data.value); + result = Acore::StringTo(std::string_view(data.value, data.length)); // Correct double fields... this undefined behavior :/ if constexpr (std::is_same_v) @@ -220,7 +220,7 @@ T Field::GetData() const if (data.raw && !IsType(DatabaseFieldTypes::Decimal)) result = *reinterpret_cast(data.value); else - result = Acore::StringTo(data.value); + result = Acore::StringTo(std::string_view(data.value, data.length)); } // Check -1 for *_dbc db tables @@ -230,7 +230,7 @@ T Field::GetData() const if (!tableName.empty() && tableName.size() > 4) { - auto signedResult = Acore::StringTo(data.value); + auto signedResult = Acore::StringTo(std::string_view(data.value, data.length)); if (signedResult && !result && tableName.substr(tableName.length() - 4) == "_dbc") { From 24dd7dfc2125fed1e2300d14848c752f184750c2 Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Wed, 12 Feb 2025 02:45:47 +0100 Subject: [PATCH 03/97] refactor(Misc): improve issue templates (#21391) --- .../{bug_report.yml => aa_game_issues.yml} | 5 +- .github/ISSUE_TEMPLATE/bb_crash_issues.yml | 86 +++++++++++++++++++ .github/ISSUE_TEMPLATE/cc_bta_issues.yml | 75 ++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 5 +- ...ure_request.yml => dd_feature_request.yml} | 2 +- .github/ISSUE_TEMPLATE/ee_cc.yml | 12 +++ 6 files changed, 177 insertions(+), 8 deletions(-) rename .github/ISSUE_TEMPLATE/{bug_report.yml => aa_game_issues.yml} (94%) create mode 100644 .github/ISSUE_TEMPLATE/bb_crash_issues.yml create mode 100644 .github/ISSUE_TEMPLATE/cc_bta_issues.yml rename .github/ISSUE_TEMPLATE/{feature_request.yml => dd_feature_request.yml} (98%) create mode 100644 .github/ISSUE_TEMPLATE/ee_cc.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/aa_game_issues.yml similarity index 94% rename from .github/ISSUE_TEMPLATE/bug_report.yml rename to .github/ISSUE_TEMPLATE/aa_game_issues.yml index 40185aa1b..6c6625105 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/aa_game_issues.yml @@ -1,4 +1,4 @@ -name: Bug report +name: Game issues description: Create a bug report to help us improve. body: - type: markdown @@ -14,14 +14,13 @@ body: description: | Description of the problem or issue here. Include entries of affected creatures / items / quests / spells etc. - If this is a crash, post the crashlog (upload to https://gist.github.com/) and include the link here. Never upload files! Use GIST for text and YouTube for videos! validations: required: true - type: textarea id: expected attributes: - label: Expected Blizzlike Behaviour + label: Expected Behaviour description: | Tell us what should happen instead. validations: diff --git a/.github/ISSUE_TEMPLATE/bb_crash_issues.yml b/.github/ISSUE_TEMPLATE/bb_crash_issues.yml new file mode 100644 index 000000000..43b07bf79 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bb_crash_issues.yml @@ -0,0 +1,86 @@ +name: Crash / Server Crash issues +description: Did your server crash? Post an issue here! +title: "Crash: " +labels: ["Priority-Critical", "HasBacktrace"] +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to fill out a bug report. Remember to fill out all fields including the title above. + An issue that is not properly filled out will be closed. + - type: textarea + id: current + attributes: + label: Steps to Reproduce + description: | + If possible provide detailed steps to reproduce the crash. + placeholder: | + 1. Provide the exact steps to trigger the crash. + 2. Include any relevant configurations or commands. + 3. Mention if the crash is consistent or intermittent. + validations: + required: false + - type: markdown + attributes: + value: | + NOTE: Make sure your server was compiled in RelWithDebug or Debug mode as crashlogs from Release do not contain enough information. + - type: textarea + id: logs + attributes: + label: Logs and Screenshots + description: | + Do you have any logs or screenshots that can be useful? + Crash logs in text are preffered over screenshots. + If you have logs in text form please upload them to [Gist](https://gist.github.com/) or PasteBin and upload the link. + validations: + required: false + - type: input + id: os + attributes: + label: Operating System + description: | + The Operating System you are having issues on. + i.e. Windows 11 x64, Debian 10 x64, macOS 12, Ubuntu 20.04 + validations: + required: true + - type: textarea + id: deps + attributes: + label: Dependencies & versions + description: | + Relevant information about dependencies and their versions that can be useful to debug the issue. + Example: + - OpenSSL ver ... + - Boost ver ... + - MySQL ver ... + - Visual Studio ver ... + - GCC ver ... + - Clang ver ... + - CMake ver ... + validations: + required: true + - type: input + id: commit + attributes: + label: Commit + description: | + Which commit hash are you using. + validations: + required: true + - type: textarea + id: extra + attributes: + label: Additional Context + description: | + Do you have any other relevant information about the issue? + validations: + required: false + - type: markdown + attributes: + value: | + Thank you for your contribution. + If you use AzerothCore regularly, we really NEED your help to: + - Test our fixes: https://www.azerothcore.org/wiki/How-to-test-a-PR + - Report issues or suggestions: https://github.com/azerothcore/azerothcore-wotlk/issues/new/choose + - Improve the documentation/wiki: https://www.azerothcore.org/wiki/home + With your help, the project can evolve much quicker! diff --git a/.github/ISSUE_TEMPLATE/cc_bta_issues.yml b/.github/ISSUE_TEMPLATE/cc_bta_issues.yml new file mode 100644 index 000000000..16077c1ec --- /dev/null +++ b/.github/ISSUE_TEMPLATE/cc_bta_issues.yml @@ -0,0 +1,75 @@ +name: Build/Tools/Apps issues +description: Got an issue with build, tools or apps? Create an issue to let us know! +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to fill out a bug report. Remember to fill out all fields including the title above. + An issue that is not properly filled out will be closed. + - type: textarea + id: current + attributes: + label: Current Behaviour + description: | + What actually happens and how do we reproduce it? + validations: + required: true + - type: textarea + id: logs + attributes: + label: Logs and Screenshots + description: | + Do you have any logs or screenshots that can be useful? + If you have logs in text form please upload them to [Gist](https://gist.github.com/) or PasteBin and upload the link. + validations: + required: false + - type: input + id: os + attributes: + label: Operating System + description: | + The Operating System you are having issues on. + i.e. Windows 11 x64, Debian 10 x64, macOS 12, Ubuntu 20.04 + validations: + required: true + - type: textarea + id: deps + attributes: + label: Dependencies & versions + description: | + Relevant information about dependencies and their versions that can be useful to debug the issue. + Example: + - OpenSSL ver ... + - Boost ver ... + - MySQL ver ... + - Visual Studio ver ... + - GCC ver ... + - Clang ver ... + - CMake ver ... + validations: + required: true + - type: input + id: commit + attributes: + label: Commit + description: | + Which commit hash are you using. + validations: + required: true + - type: textarea + id: extra + attributes: + label: Additional Context + description: | + Do you have any other relevant information about the issue? + validations: + required: false + - type: markdown + attributes: + value: | + Thank you for your contribution. + If you use AzerothCore regularly, we really NEED your help to: + - Test our fixes: https://www.azerothcore.org/wiki/How-to-test-a-PR + - Report issues or suggestions: https://github.com/azerothcore/azerothcore-wotlk/issues/new/choose + - Improve the documentation/wiki: https://www.azerothcore.org/wiki/home + With your help, the project can evolve much quicker! diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 54c4e4e79..30195f877 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,4 @@ -blank_issues_enabled: true +blank_issues_enabled: false contact_links: - name: Website url: https://www.azerothcore.org @@ -6,9 +6,6 @@ contact_links: - name: Wiki url: https://www.azerothcore.org/wiki about: You can find plenty of information on our Wiki. - - name: How to ask for help - url: https://www.azerothcore.org/wiki/How-to-ask-for-help - about: Before submitting an issue we'd love if you take a minute to read this. - name: FAQ url: https://www.azerothcore.org/wiki/faq about: Frequently asked questions. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/dd_feature_request.yml similarity index 98% rename from .github/ISSUE_TEMPLATE/feature_request.yml rename to .github/ISSUE_TEMPLATE/dd_feature_request.yml index 8103861f7..e3e54f9de 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/dd_feature_request.yml @@ -1,7 +1,7 @@ name: Feature request description: Suggest an idea for this project title: "Feature: " -type: "Feature" +labels: "Feature" body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/ee_cc.yml b/.github/ISSUE_TEMPLATE/ee_cc.yml new file mode 100644 index 000000000..4ed34e08e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/ee_cc.yml @@ -0,0 +1,12 @@ +name: CC Triage +description: This template is only used for ChromieCraft +labels: ["ChromieCraft Generic"] +body: + - type: textarea + id: current + attributes: + label: Triage + description: | + Paste the issue from ChromieCraft here. + validations: + required: true From f6a043329710d12a77b99691511cf5884c30b80b Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Wed, 12 Feb 2025 11:09:31 +0100 Subject: [PATCH 04/97] feat(Core/Arena): Add support for arena seasons completion with progression in runtime. (#19858) Co-authored-by: Winfidonarleyan --- .../active_arena_season.sql | 10 + .../rev_1725301496947122000.sql | 95 ++++++++ .../apps/worldserver/worldserver.conf.dist | 15 -- .../ArenaSeason/ArenaSeasonMgr.cpp | 224 ++++++++++++++++++ .../ArenaSeason/ArenaSeasonMgr.h | 126 ++++++++++ .../ArenaSeasonRewardsDistributor.cpp | 166 +++++++++++++ .../ArenaSeasonRewardsDistributor.h | 54 +++++ .../ArenaSeason/ArenaTeamFilter.h | 113 +++++++++ src/server/game/Battlegrounds/ArenaTeam.cpp | 3 +- .../game/Battlegrounds/ArenaTeamMgr.cpp | 21 ++ src/server/game/Battlegrounds/ArenaTeamMgr.h | 2 + .../game/Battlegrounds/BattlegroundMgr.cpp | 12 + .../game/Battlegrounds/BattlegroundMgr.h | 1 + src/server/game/Entities/Player/Player.cpp | 5 +- src/server/game/Events/GameEventMgr.cpp | 28 --- src/server/game/Events/GameEventMgr.h | 9 +- .../game/Handlers/BattleGroundHandler.cpp | 3 +- src/server/game/World/IWorld.h | 2 - src/server/game/World/World.cpp | 10 +- src/server/scripts/Commands/cs_arena.cpp | 90 +++++++ .../ArenaSeasonRewardDistributorTest.cpp | 207 ++++++++++++++++ .../ArenaSeason/ArenaTeamFilterTest.cpp | 113 +++++++++ 22 files changed, 1250 insertions(+), 59 deletions(-) create mode 100644 data/sql/updates/pending_db_characters/active_arena_season.sql create mode 100644 data/sql/updates/pending_db_world/rev_1725301496947122000.sql create mode 100644 src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonMgr.cpp create mode 100644 src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonMgr.h create mode 100644 src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardsDistributor.cpp create mode 100644 src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardsDistributor.h create mode 100644 src/server/game/Battlegrounds/ArenaSeason/ArenaTeamFilter.h create mode 100644 src/test/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardDistributorTest.cpp create mode 100644 src/test/server/game/Battlegrounds/ArenaSeason/ArenaTeamFilterTest.cpp diff --git a/data/sql/updates/pending_db_characters/active_arena_season.sql b/data/sql/updates/pending_db_characters/active_arena_season.sql new file mode 100644 index 000000000..726662af3 --- /dev/null +++ b/data/sql/updates/pending_db_characters/active_arena_season.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS `active_arena_season`; +CREATE TABLE `active_arena_season` ( + `season_id` TINYINT UNSIGNED NOT NULL, + `season_state` TINYINT UNSIGNED NOT NULL COMMENT 'Supported 2 states: 0 - disabled; 1 - in progress.' +) +CHARSET = utf8mb4 +COLLATE = utf8mb4_unicode_ci +ENGINE = InnoDB; + +INSERT INTO `active_arena_season` (`season_id`, `season_state`) VALUES (8, 1); diff --git a/data/sql/updates/pending_db_world/rev_1725301496947122000.sql b/data/sql/updates/pending_db_world/rev_1725301496947122000.sql new file mode 100644 index 000000000..7a70fd82e --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1725301496947122000.sql @@ -0,0 +1,95 @@ +DROP TABLE IF EXISTS `arena_season_reward_group`; +CREATE TABLE `arena_season_reward_group` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `arena_season` TINYINT UNSIGNED NOT NULL, + `criteria_type` ENUM('pct', 'abs') NOT NULL DEFAULT 'pct' COMMENT 'Determines how rankings are evaluated: "pct" - percentage-based (e.g., top 20% of the ladder), "abs" - absolute position-based (e.g., top 10 players).', + `min_criteria` FLOAT NOT NULL, + `max_criteria` FLOAT NOT NULL, + `reward_mail_template_id` INT UNSIGNED, + `reward_mail_subject` VARCHAR(255), + `reward_mail_body` TEXT, + `gold_reward` INT UNSIGNED +) +CHARSET = utf8mb4 +COLLATE = utf8mb4_unicode_ci +ENGINE = InnoDB; + +-- Season 8 +INSERT INTO `arena_season_reward_group` (`id`, `arena_season`, `criteria_type`, `min_criteria`, `max_criteria`, `reward_mail_template_id`, `reward_mail_subject`, `reward_mail_body`, `gold_reward`) VALUES +(1, 8, 'abs', 1, 1, 0, '', '', 0), +(2, 8, 'pct', 0, 0.5, 287, '', '', 0), +(3, 8, 'pct', 0.5, 3, 0, '', '', 0), +(4, 8, 'pct', 3, 10, 0, '', '', 0), +(5, 8, 'pct', 10, 35, 0, '', '', 0), +-- Season 7 +(6, 7, 'abs', 1, 1, 0, '', '', 0), +(7, 7, 'pct', 0, 0.5, 286, '', '', 0), +(8, 7, 'pct', 0.5, 3, 0, '', '', 0), +(9, 7, 'pct', 3, 10, 0, '', '', 0), +(10, 7, 'pct', 10, 35, 0, '', '', 0), +-- Season 6 +(11, 6, 'abs', 1, 1, 0, '', '', 0), +(12, 6, 'pct', 0, 0.5, 267, '', '', 0), +(13, 6, 'pct', 0.5, 3, 0, '', '', 0), +(14, 6, 'pct', 3, 10, 0, '', '', 0), +(15, 6, 'pct', 10, 35, 0, '', '', 0), +-- Season 5 +(16, 5, 'abs', 1, 1, 0, '', '', 0), +(17, 5, 'pct', 0, 0.5, 266, '', '', 0), +(18, 5, 'pct', 0.5, 3, 0, '', '', 0), +(19, 5, 'pct', 3, 10, 0, '', '', 0), +(20, 5, 'pct', 10, 35, 0, '', '', 0); + +DROP TABLE IF EXISTS `arena_season_reward`; +CREATE TABLE `arena_season_reward` ( + `group_id` INT NOT NULL COMMENT 'id from arena_season_reward_group table', + `type` ENUM('achievement', 'item') NOT NULL DEFAULT 'achievement', + `entry` INT UNSIGNED NOT NULL COMMENT 'For item type - item entry, for achievement - achevement id.', + PRIMARY KEY (`group_id`, `type`, `entry`) +) +CHARSET = utf8mb4 +COLLATE = utf8mb4_unicode_ci +ENGINE = InnoDB; + +-- Season 8 +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (1, 'achievement', 3336); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (2, 'item', 50435); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (2, 'achievement', 2091); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (3, 'achievement', 2092); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (4, 'achievement', 2093); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (5, 'achievement', 2090); +-- Season 7 +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (6, 'achievement', 3336); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (7, 'item', 47840); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (7, 'achievement', 2091); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (8, 'achievement', 2092); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (9, 'achievement', 2093); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (10, 'achievement', 2090); +-- Season 6 +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (11, 'achievement', 3336); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (12, 'item', 46171); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (12, 'achievement', 2091); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (13, 'achievement', 2092); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (14, 'achievement', 2093); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (15, 'achievement', 2090); +-- Season 5 +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (16, 'achievement', 3336); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (17, 'item', 46708); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (17, 'achievement', 2091); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (18, 'achievement', 2092); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (19, 'achievement', 2093); +INSERT INTO `arena_season_reward` (`group_id`, `type`, `entry`) VALUES (20, 'achievement', 2090); + +DELETE FROM `command` WHERE `name` IN ('arena season start', 'arena season reward', 'arena season set state', 'arena season deleteteams'); +INSERT INTO `command` (`name`, `security`, `help`) VALUES ('arena season start', 3, 'Syntax: .arena season start $season_id\nStarts a new arena season, places the correct vendors, and sets the new season state to IN PROGRESS.'); +INSERT INTO `command` (`name`, `security`, `help`) VALUES ('arena season reward', 3, 'Syntax: .arena season reward $brackets\nBuilds a ladder by combining team brackets and provides rewards from the arena_season_reward table.\nExample usage:\n \n# Combine all brackets, build a ladder, and distribute rewards among them\n.arena season reward all\n \n# Build ladders separately for 2v2, 3v3, and 5v5 brackets so each bracket receives its own rewards\n.arena season reward 2\n.arena season reward 3\n.arena season reward 5\n \n# Combine 2v2 and 3v3 brackets and distribute rewards\n.arena season reward 2,3'); +INSERT INTO `command` (`name`, `security`, `help`) VALUES ('arena season deleteteams', 3, 'Syntax: .arena season deleteteams\nDeletes ALL arena teams.'); +INSERT INTO `command` (`name`, `security`, `help`) VALUES ('arena season set state', 3, 'Syntax: .arena season set state $state\nChanges the state for the current season.\nAvailable states:\n 0 - disabled. Players can\'t queue for the arena.\n 1 - in progress. Players can use arena-related functionality.'); + +DELETE FROM `achievement_reward` WHERE `ID` IN (3336, 2091, 2092, 2093, 2090); +INSERT INTO `achievement_reward` (`ID`, `TitleA`, `TitleH`, `ItemID`, `Sender`, `Subject`, `Body`, `MailTemplateID`) VALUES +(3336, 157, 157, 0, 0, '', '', 0), +(2091, 42, 42, 0, 0, '', '', 0), +(2092, 43, 43, 0, 0, '', '', 0), +(2093, 44, 44, 0, 0, '', '', 0), +(2090, 45, 45, 0, 0, '', '', 0); diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index df79e3bdc..9fd477413 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -3789,21 +3789,6 @@ Arena.QueueAnnouncer.PlayerOnly = 0 Arena.QueueAnnouncer.Detail = 3 -# -# Arena.ArenaSeason.ID -# Description: Current arena season id shown in clients. -# Default: 8 - -Arena.ArenaSeason.ID = 8 - -# -# Arena.ArenaSeason.InProgress -# Description: State of current arena season. -# Default: 1 - (Active) -# 0 - (Finished) - -Arena.ArenaSeason.InProgress = 1 - # # Arena.ArenaStartRating # Description: Start rating for new arena teams. diff --git a/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonMgr.cpp b/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonMgr.cpp new file mode 100644 index 000000000..e466eb718 --- /dev/null +++ b/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonMgr.cpp @@ -0,0 +1,224 @@ +/* + * 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 "ArenaSeasonMgr.h" +#include "ArenaTeamMgr.h" +#include "ArenaSeasonRewardsDistributor.h" +#include "BattlegroundMgr.h" +#include "GameEventMgr.h" +#include "MapMgr.h" +#include "Player.h" + +ArenaSeasonMgr* ArenaSeasonMgr::instance() +{ + static ArenaSeasonMgr instance; + return &instance; +} + +void ArenaSeasonMgr::LoadRewards() +{ + uint32 oldMSTime = getMSTime(); + + std::unordered_map stringToArenaSeasonRewardGroupCriteriaType = { + {"pct", ArenaSeasonRewardGroupCriteriaType::ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE}, + {"abs", ArenaSeasonRewardGroupCriteriaType::ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE} + }; + + QueryResult result = WorldDatabase.Query("SELECT id, arena_season, criteria_type, min_criteria, max_criteria, reward_mail_template_id, reward_mail_subject, reward_mail_body, gold_reward FROM arena_season_reward_group"); + + if (!result) + { + LOG_WARN("server.loading", ">> Loaded 0 arena season rewards. DB table `arena_season_reward_group` is empty."); + LOG_INFO("server.loading", " "); + return; + } + + std::unordered_map groupsMap; + + do + { + Field* fields = result->Fetch(); + uint32 id = fields[0].Get(); + + ArenaSeasonRewardGroup group; + group.season = fields[1].Get(); + group.criteriaType = stringToArenaSeasonRewardGroupCriteriaType[fields[2].Get()]; + group.minCriteria = fields[3].Get(); + group.maxCriteria = fields[4].Get(); + group.rewardMailTemplateID = fields[5].Get(); + group.rewardMailSubject = fields[6].Get(); + group.rewardMailBody = fields[7].Get(); + group.goldReward = fields[8].Get(); + + groupsMap[id] = group; + } while (result->NextRow()); + + std::unordered_map stringToArenaSeasonRewardType = { + {"achievement", ArenaSeasonRewardType::ARENA_SEASON_REWARD_TYPE_ACHIEVEMENT}, + {"item", ArenaSeasonRewardType::ARENA_SEASON_REWARD_TYPE_ITEM} + }; + + result = WorldDatabase.Query("SELECT group_id, type, entry FROM arena_season_reward"); + + if (!result) + { + LOG_WARN("server.loading", ">> Loaded 0 arena season rewards. DB table `arena_season_reward` is empty."); + LOG_INFO("server.loading", " "); + return; + } + + do + { + Field* fields = result->Fetch(); + uint32 groupId = fields[0].Get(); + + ArenaSeasonReward reward; + reward.type = stringToArenaSeasonRewardType[fields[1].Get()]; + reward.entry = fields[2].Get(); + + auto itr = groupsMap.find(groupId); + ASSERT(itr != groupsMap.end(), "Unknown arena_season_reward_group ({}) in arena_season_reward", groupId); + + (reward.type == ARENA_SEASON_REWARD_TYPE_ITEM) ? + groupsMap[groupId].itemRewards.push_back(reward) : + groupsMap[groupId].achievementRewards.push_back(reward); + + } while (result->NextRow()); + + for (auto const& itr : groupsMap) + _arenaSeasonRewardGroupsStore[itr.second.season].push_back(itr.second); + + LOG_INFO("server.loading", ">> Loaded {} arena season rewards in {} ms", (uint32)groupsMap.size(), GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", " "); +} + +void ArenaSeasonMgr::LoadActiveSeason() +{ + QueryResult result = CharacterDatabase.Query("SELECT season_id, season_state FROM active_arena_season"); + ASSERT(result, "active_arena_season can't be empty"); + + Field* fields = result->Fetch(); + _currentSeason = fields[0].Get(); + _currentSeasonState = static_cast(fields[1].Get()); + + uint16 eventID = GameEventForArenaSeason(_currentSeason); + sGameEventMgr->StartEvent(eventID, true); + + LOG_INFO("server.loading", "Arena Season {} loaded...", _currentSeason); + LOG_INFO("server.loading", " "); +} + +void ArenaSeasonMgr::RewardTeamsForTheSeason(std::shared_ptr teamsFilter) +{ + ArenaSeasonTeamRewarderImpl rewarder = ArenaSeasonTeamRewarderImpl(); + ArenaSeasonRewardDistributor distributor = ArenaSeasonRewardDistributor(&rewarder); + std::vector rewards = _arenaSeasonRewardGroupsStore[GetCurrentSeason()]; + ArenaTeamMgr::ArenaTeamContainer filteredTeams = teamsFilter->Filter(sArenaTeamMgr->GetArenaTeams()); + distributor.DistributeRewards(filteredTeams, rewards); +} + +bool ArenaSeasonMgr::CanDeleteArenaTeams() +{ + std::vector rewards = _arenaSeasonRewardGroupsStore[GetCurrentSeason()]; + if (rewards.empty()) + return false; + + for (auto const& bg : sBattlegroundMgr->GetActiveBattlegrounds()) + if (bg->isRated()) + return false; + + return true; +} + +void ArenaSeasonMgr::DeleteArenaTeams() +{ + if (!CanDeleteArenaTeams()) + return; + + // Cleanup queue first. + std::vector arenasQueueTypes = {BATTLEGROUND_QUEUE_2v2, BATTLEGROUND_QUEUE_3v3, BATTLEGROUND_QUEUE_5v5}; + for (BattlegroundQueueTypeId queueType : arenasQueueTypes) + { + auto queue = sBattlegroundMgr->GetBattlegroundQueue(queueType); + for (auto const& [playerGUID, other] : queue.m_QueuedPlayers) + queue.RemovePlayer(playerGUID, true); + } + + sArenaTeamMgr->DeleteAllArenaTeams(); +} + +void ArenaSeasonMgr::ChangeCurrentSeason(uint8 season) +{ + if (_currentSeason == season) + return; + + uint16 currentEventID = GameEventForArenaSeason(_currentSeason); + sGameEventMgr->StopEvent(currentEventID, true); + + uint16 newEventID = GameEventForArenaSeason(season); + sGameEventMgr->StartEvent(newEventID, true); + + _currentSeason = season; + _currentSeasonState = ARENA_SEASON_STATE_IN_PROGRESS; + + CharacterDatabase.Execute("UPDATE active_arena_season SET season_id = {}, season_state = {}", _currentSeason, _currentSeasonState); + + BroadcastUpdatedWorldState(); +} + +void ArenaSeasonMgr::SetSeasonState(ArenaSeasonState state) +{ + if (_currentSeasonState == state) + return; + + _currentSeasonState = state; + + CharacterDatabase.Execute("UPDATE active_arena_season SET season_state = {}", _currentSeasonState); + + BroadcastUpdatedWorldState(); +} + +uint16 ArenaSeasonMgr::GameEventForArenaSeason(uint8 season) +{ + QueryResult result = WorldDatabase.Query("SELECT eventEntry FROM game_event_arena_seasons WHERE season = '{}'", season); + + if (!result) + { + LOG_ERROR("arenaseasonmgr", "ArenaSeason ({}) must be an existant Arena Season", season); + return 0; + } + + Field* fields = result->Fetch(); + return fields[0].Get(); +} + +void ArenaSeasonMgr::BroadcastUpdatedWorldState() +{ + sMapMgr->DoForAllMaps([](Map* map) + { + // Ignore instanceable maps, players will get a fresh state once they change the map. + if (map->Instanceable()) + return; + + map->DoForAllPlayers([&](Player* player) + { + uint32 currZone, currArea; + player->GetZoneAndAreaId(currZone, currArea); + player->SendInitWorldStates(currZone, currArea); + }); + }); +} diff --git a/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonMgr.h b/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonMgr.h new file mode 100644 index 000000000..7a1ee97c7 --- /dev/null +++ b/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonMgr.h @@ -0,0 +1,126 @@ +/* + * 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 . + */ + +#ifndef _ARENASEASONMGR_H +#define _ARENASEASONMGR_H + +#include "Common.h" +#include "ArenaTeamFilter.h" +#include +#include + +enum ArenaSeasonState +{ + ARENA_SEASON_STATE_DISABLED = 0, + ARENA_SEASON_STATE_IN_PROGRESS = 1 +}; + +enum ArenaSeasonRewardType +{ + ARENA_SEASON_REWARD_TYPE_ITEM, + ARENA_SEASON_REWARD_TYPE_ACHIEVEMENT +}; + +enum ArenaSeasonRewardGroupCriteriaType +{ + ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE, + ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE +}; + +// ArenaSeasonReward represents one reward, it can be an item or achievement. +struct ArenaSeasonReward +{ + ArenaSeasonReward() = default; + + // Item or acheivement entry. + uint32 entry{}; + + ArenaSeasonRewardType type{ARENA_SEASON_REWARD_TYPE_ITEM}; + + // Used in unit tests. + bool operator==(const ArenaSeasonReward& other) const + { + return entry == other.entry && type == other.type; + } +}; + +struct ArenaSeasonRewardGroup +{ + ArenaSeasonRewardGroup() = default; + + uint8 season{}; + + ArenaSeasonRewardGroupCriteriaType criteriaType; + + float minCriteria{}; + float maxCriteria{}; + + uint32 rewardMailTemplateID{}; + std::string rewardMailSubject{}; + std::string rewardMailBody{}; + uint32 goldReward{}; + + std::vector itemRewards; + std::vector achievementRewards; + + // Used in unit tests. + bool operator==(const ArenaSeasonRewardGroup& other) const + { + return minCriteria == other.minCriteria && + maxCriteria == other.maxCriteria && + criteriaType == other.criteriaType && + itemRewards == other.itemRewards && + achievementRewards == other.achievementRewards; + } +}; + +class ArenaSeasonMgr +{ +public: + static ArenaSeasonMgr* instance(); + + using ArenaSeasonRewardGroupsBySeasonContainer = std::unordered_map>; + + // Loading functions + void LoadRewards(); + void LoadActiveSeason(); + + // Season management functions + void ChangeCurrentSeason(uint8 season); + uint8 GetCurrentSeason() { return _currentSeason; } + + void SetSeasonState(ArenaSeasonState state); + ArenaSeasonState GetSeasonState() { return _currentSeasonState; } + + // Season completion functions + void RewardTeamsForTheSeason(std::shared_ptr teamsFilter); + bool CanDeleteArenaTeams(); + void DeleteArenaTeams(); + +private: + uint16 GameEventForArenaSeason(uint8 season); + void BroadcastUpdatedWorldState(); + + ArenaSeasonRewardGroupsBySeasonContainer _arenaSeasonRewardGroupsStore; + + uint8 _currentSeason{}; + ArenaSeasonState _currentSeasonState{}; +}; + +#define sArenaSeasonMgr ArenaSeasonMgr::instance() + +#endif // _ARENASEASONMGR_H diff --git a/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardsDistributor.cpp b/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardsDistributor.cpp new file mode 100644 index 000000000..dff7961a2 --- /dev/null +++ b/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardsDistributor.cpp @@ -0,0 +1,166 @@ +/* + * 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 "ArenaSeasonRewardsDistributor.h" +#include "AchievementMgr.h" +#include "CharacterDatabase.h" +#include "Mail.h" +#include "Player.h" +#include + +constexpr float minPctTeamGamesForMemberToGetReward = 30; + +void ArenaSeasonTeamRewarderImpl::RewardTeamWithRewardGroup(ArenaTeam *arenaTeam, const ArenaSeasonRewardGroup &rewardGroup) +{ + RewardWithMail(arenaTeam, rewardGroup); + RewardWithAchievements(arenaTeam, rewardGroup); +} + +void ArenaSeasonTeamRewarderImpl::RewardWithMail(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup) +{ + if (rewardGroup.itemRewards.empty() && rewardGroup.goldReward == 0) + return; + + const uint32 npcKingDondSender = 18897; + + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + for (auto const& member : arenaTeam->GetMembers()) + { + uint32 teamSeasonGames = arenaTeam->GetStats().SeasonGames; + // Avoid division by zero. + if (teamSeasonGames == 0) + continue; + + float memberParticipationPercentage = (static_cast(member.SeasonGames) / teamSeasonGames) * 100; + if (memberParticipationPercentage < minPctTeamGamesForMemberToGetReward) + continue; + + Player* player = ObjectAccessor::FindPlayer(member.Guid); + + auto draft = rewardGroup.rewardMailTemplateID > 0 ? + MailDraft(rewardGroup.rewardMailTemplateID, false) : + MailDraft(rewardGroup.rewardMailSubject, rewardGroup.rewardMailBody); + + if (rewardGroup.goldReward > 0) + draft.AddMoney(rewardGroup.goldReward); + + for (auto const& reward : rewardGroup.itemRewards) + if (Item* item = Item::CreateItem(reward.entry, 1)) + { + item->SaveToDB(trans); + draft.AddItem(item); + } + + draft.SendMailTo(trans, MailReceiver(player, member.Guid.GetCounter()), MailSender(npcKingDondSender)); + } + CharacterDatabase.CommitTransaction(trans); +} + +void ArenaSeasonTeamRewarderImpl::RewardWithAchievements(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup) +{ + if (rewardGroup.achievementRewards.empty()) + return; + + for (auto const& member : arenaTeam->GetMembers()) + { + uint32 teamSeasonGames = arenaTeam->GetStats().SeasonGames; + // Avoid division by zero. + if (teamSeasonGames == 0) + continue; + + float memberParticipationPercentage = (static_cast(member.SeasonGames) / teamSeasonGames) * 100; + if (memberParticipationPercentage < minPctTeamGamesForMemberToGetReward) + continue; + + Player* player = ObjectAccessor::FindPlayer(member.Guid); + for (auto const& reward : rewardGroup.achievementRewards) + { + AchievementEntry const* achievement = sAchievementStore.LookupEntry(reward.entry); + if (!achievement) + continue; + + if (player) + player->CompletedAchievement(achievement); + else + sAchievementMgr->CompletedAchievementForOfflinePlayer(member.Guid.GetCounter(), achievement); + } + } +} + +ArenaSeasonRewardDistributor::ArenaSeasonRewardDistributor(ArenaSeasonTeamRewarder* rewarder) + : _rewarder(rewarder) +{ +} + +void ArenaSeasonRewardDistributor::DistributeRewards(ArenaTeamMgr::ArenaTeamContainer &arenaTeams, std::vector &rewardGroups) +{ + std::vector sortedTeams; + sortedTeams.reserve(arenaTeams.size()); + + static constexpr uint16 minRequiredGames = 30; + + for (auto const& [id, team] : arenaTeams) + if (team->GetStats().SeasonGames >= minRequiredGames) + sortedTeams.push_back(team); + + std::sort(sortedTeams.begin(), sortedTeams.end(), [](ArenaTeam* a, ArenaTeam* b) { + return a->GetRating() > b->GetRating(); + }); + + std::vector pctRewardGroup; + std::vector absRewardGroup; + + for (auto const& reward : rewardGroups) + { + if (reward.criteriaType == ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE) + pctRewardGroup.push_back(reward); + else + absRewardGroup.push_back(reward); + } + + size_t totalTeams = sortedTeams.size(); + for (auto const& rewardGroup : pctRewardGroup) + { + size_t minIndex = static_cast(rewardGroup.minCriteria * totalTeams / 100); + size_t maxIndex = static_cast(rewardGroup.maxCriteria * totalTeams / 100); + + minIndex = std::min(minIndex, totalTeams); + maxIndex = std::min(maxIndex, totalTeams); + + for (size_t i = minIndex; i < maxIndex; ++i) + { + ArenaTeam* team = sortedTeams[i]; + _rewarder->RewardTeamWithRewardGroup(team, rewardGroup); + } + } + + for (auto const& rewardGroup : absRewardGroup) + { + size_t minIndex = rewardGroup.minCriteria-1; // Top 1 team is the team with index 0, so we need make -1. + size_t maxIndex = rewardGroup.maxCriteria; + + minIndex = std::max(minIndex, size_t(0)); + minIndex = std::min(minIndex, totalTeams); + maxIndex = std::min(maxIndex, totalTeams); + + for (size_t i = minIndex; i < maxIndex; ++i) + { + ArenaTeam* team = sortedTeams[i]; + _rewarder->RewardTeamWithRewardGroup(team, rewardGroup); + } + } +} diff --git a/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardsDistributor.h b/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardsDistributor.h new file mode 100644 index 000000000..144fae5ff --- /dev/null +++ b/src/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardsDistributor.h @@ -0,0 +1,54 @@ +/* + * 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 . + */ + +#ifndef _ARENASEASONREWARDDISTRIBUTOR_H +#define _ARENASEASONREWARDDISTRIBUTOR_H + +#include "ArenaSeasonMgr.h" +#include "ArenaTeam.h" +#include "ArenaTeamMgr.h" + +class ArenaSeasonTeamRewarder +{ +public: + virtual ~ArenaSeasonTeamRewarder() = default; + + virtual void RewardTeamWithRewardGroup(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup) = 0; +}; + +class ArenaSeasonTeamRewarderImpl: public ArenaSeasonTeamRewarder +{ +public: + void RewardTeamWithRewardGroup(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup) override; + +private: + void RewardWithMail(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup); + void RewardWithAchievements(ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const & rewardGroup); +}; + +class ArenaSeasonRewardDistributor +{ +public: + ArenaSeasonRewardDistributor(ArenaSeasonTeamRewarder* rewarder); + + void DistributeRewards(ArenaTeamMgr::ArenaTeamContainer& arenaTeams, std::vector& rewardGroups); + +private: + ArenaSeasonTeamRewarder* _rewarder; +}; + +#endif // _ARENASEASONREWARDDISTRIBUTOR_H diff --git a/src/server/game/Battlegrounds/ArenaSeason/ArenaTeamFilter.h b/src/server/game/Battlegrounds/ArenaSeason/ArenaTeamFilter.h new file mode 100644 index 000000000..2ac66344f --- /dev/null +++ b/src/server/game/Battlegrounds/ArenaSeason/ArenaTeamFilter.h @@ -0,0 +1,113 @@ +/* + * 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 . + */ + +#ifndef _ARENATEAMFILTER_H +#define _ARENATEAMFILTER_H + +#include "Common.h" +#include "ArenaTeamMgr.h" +#include "ArenaTeam.h" +#include "Tokenize.h" +#include "StringConvert.h" +#include +#include +#include +#include +#include +#include + +class ArenaTeamFilter +{ +public: + virtual ~ArenaTeamFilter() = default; + + virtual ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) = 0; +}; + +class ArenaTeamFilterByTypes : public ArenaTeamFilter +{ +public: + ArenaTeamFilterByTypes(std::vector validTypes) : _validTypes(validTypes) {} + + ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) override + { + ArenaTeamMgr::ArenaTeamContainer result; + + for (auto const& pair : teams) + { + ArenaTeam* team = pair.second; + for (uint8 arenaType : _validTypes) + { + if (team->GetType() == arenaType) + { + result[pair.first] = team; + break; + } + } + } + + return result; + } + +private: + std::vector _validTypes; +}; + +class ArenaTeamFilterAllTeams : public ArenaTeamFilter +{ +public: + ArenaTeamMgr::ArenaTeamContainer Filter(ArenaTeamMgr::ArenaTeamContainer teams) override + { + return teams; + } +}; + +class ArenaTeamFilterFactoryByUserInput +{ +public: + std::unique_ptr CreateFilterByUserInput(std::string userInput) + { + std::transform(userInput.begin(), userInput.end(), userInput.begin(), + [](unsigned char c) { return std::tolower(c); }); + + if (userInput == "all") + return std::make_unique(); + + // Parse the input string (e.g., "2,3") into valid types + std::vector validTypes = ParseTypes(userInput); + + if (!validTypes.empty()) + return std::make_unique(validTypes); + + return nullptr; + } + +private: + std::vector ParseTypes(std::string_view userInput) + { + std::vector validTypes; + auto tokens = Acore::Tokenize(userInput, ',', false); + + for (auto const& token : tokens) + if (auto typeOpt = Acore::StringTo(token)) + validTypes.push_back(*typeOpt); + + return validTypes; + } +}; + +#endif // _ARENATEAMFILTER_H diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index 552b229ad..b93822810 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -17,6 +17,7 @@ #include "ArenaTeam.h" #include "ArenaTeamMgr.h" +#include "ArenaSeasonMgr.h" #include "BattlegroundMgr.h" #include "CharacterCache.h" #include "Group.h" @@ -658,7 +659,7 @@ uint32 ArenaTeam::GetPoints(uint32 memberRating) if (rating <= 1500) { - if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) < 6 && !sWorld->getIntConfig(CONFIG_LEGACY_ARENA_POINTS_CALC)) + if (sArenaSeasonMgr->GetCurrentSeason() < 6 && !sWorld->getIntConfig(CONFIG_LEGACY_ARENA_POINTS_CALC)) points = (float)rating * 0.22f + 14.0f; else points = 344; diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp index e36b874ac..8ba0e3cd4 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp @@ -125,6 +125,27 @@ void ArenaTeamMgr::RemoveArenaTeam(uint32 arenaTeamId) ArenaTeamStore.erase(arenaTeamId); } +void ArenaTeamMgr::DeleteAllArenaTeams() +{ + for (auto const& [id, team] : ArenaTeamStore) + { + while (team->GetMembersSize() > 0) + team->DelMember(team->GetMembers().front().Guid, false); + + delete team; + } + + ArenaTeamStore.clear(); + + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + trans->Append("DELETE FROM arena_team_member"); + trans->Append("DELETE FROM arena_team"); + trans->Append("DELETE FROM character_arena_stats"); + CharacterDatabase.CommitTransaction(trans); + + NextArenaTeamId = 1; +} + uint32 ArenaTeamMgr::GenerateArenaTeamId() { if (NextArenaTeamId >= MAX_ARENA_TEAM_ID) diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.h b/src/server/game/Battlegrounds/ArenaTeamMgr.h index 06ee6bc01..6ca67b5f3 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.h +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.h @@ -43,6 +43,8 @@ public: void AddArenaTeam(ArenaTeam* arenaTeam); void RemoveArenaTeam(uint32 Id); + void DeleteAllArenaTeams(); + ArenaTeamContainer::iterator GetArenaTeamMapBegin() { return ArenaTeamStore.begin(); } ArenaTeamContainer::iterator GetArenaTeamMapEnd() { return ArenaTeamStore.end(); } ArenaTeamContainer& GetArenaTeams() { return ArenaTeamStore; } diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 8e91dd0d4..46bac265d 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -334,6 +334,18 @@ Battleground* BattlegroundMgr::GetBattlegroundTemplate(BattlegroundTypeId bgType return bgs.empty() ? nullptr : bgs.begin()->second; } +std::vector BattlegroundMgr::GetActiveBattlegrounds() +{ + std::vector result; + + for (auto const& [bgType, bgData] : bgDataStore) + for (auto const& [id, bg] : bgData._Battlegrounds) + if (bg->GetStatus() == STATUS_WAIT_JOIN || bg->GetStatus() == STATUS_IN_PROGRESS) + result.push_back(static_cast(bg)); + + return result; +} + uint32 BattlegroundMgr::CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id) { if (IsArenaType(bgTypeId)) diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h index 3b07a9fc7..36c8a30c3 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.h +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h @@ -82,6 +82,7 @@ public: Battleground* GetBattleground(uint32 instanceID, BattlegroundTypeId bgTypeId); Battleground* GetBattlegroundTemplate(BattlegroundTypeId bgTypeId); Battleground* CreateNewBattleground(BattlegroundTypeId bgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 arenaType, bool isRated); + std::vector GetActiveBattlegrounds(); void AddBattleground(Battleground* bg); void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index fac531f4b..5a51b10a4 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -21,6 +21,7 @@ #include "ArenaSpectator.h" #include "ArenaTeam.h" #include "ArenaTeamMgr.h" +#include "ArenaSeasonMgr.h" #include "Battlefield.h" #include "BattlefieldMgr.h" #include "BattlefieldWG.h" @@ -8243,9 +8244,9 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) data << uint32(0x8d4) << uint32(0x0); // 5 data << uint32(0x8d3) << uint32(0x0); // 6 // 7 1 - Arena season in progress, 0 - end of season - data << uint32(0xC77) << uint32(sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)); + data << uint32(0xC77) << uint32(sArenaSeasonMgr->GetSeasonState() == ARENA_SEASON_STATE_IN_PROGRESS); // 8 Arena season id - data << uint32(0xF3D) << uint32(sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID)); + data << uint32(0xF3D) << uint32(sArenaSeasonMgr->GetCurrentSeason()); if (mapid == 530) // Outland { diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index ce529ff24..b380b8399 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -1163,34 +1163,6 @@ uint32 GameEventMgr::StartSystem() // return the next return delay; } -void GameEventMgr::StartArenaSeason() -{ - uint8 season = sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID); - - WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_GAME_EVENT_ARENA_SEASON); - stmt->SetData(0, season); - PreparedQueryResult result = WorldDatabase.Query(stmt); - - if (!result) - { - LOG_ERROR("gameevent", "ArenaSeason ({}) must be an existant Arena Season", season); - return; - } - - Field* fields = result->Fetch(); - uint16 eventId = fields[0].Get(); - - if (eventId >= _gameEvent.size()) - { - LOG_ERROR("gameevent", "EventEntry {} for ArenaSeason ({}) does not exists", eventId, season); - return; - } - - StartEvent(eventId, true); - LOG_INFO("server.loading", "Arena Season {} started...", season); - LOG_INFO("server.loading", " "); -} - uint32 GameEventMgr::Update() // return the next event delay in ms { time_t currenttime = GameTime::GetGameTime().count(); diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index 390849269..9cc0adcb6 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -115,11 +115,10 @@ public: bool IsActiveEvent(uint16 eventId) { return (_activeEvents.find(eventId) != _activeEvents.end()); } uint32 StartSystem(); void Initialize(); - void StartArenaSeason(); - void StartInternalEvent(uint16 eventId); - bool StartEvent(uint16 eventId, bool overwrite = false); - void StopEvent(uint16 eventId, bool overwrite = false); - void HandleQuestComplete(uint32 questId); // called on world event type quest completions + void StartInternalEvent(uint16 event_id); + bool StartEvent(uint16 event_id, bool overwrite = false); + void StopEvent(uint16 event_id, bool overwrite = false); + void HandleQuestComplete(uint32 quest_id); // called on world event type quest completions uint32 GetNPCFlag(Creature* cr); // Load the game event npc vendor table from the DB void LoadEventVendors(); diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index c2aafae81..0735dd2d1 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -17,6 +17,7 @@ #include "ArenaTeam.h" #include "ArenaTeamMgr.h" +#include "ArenaSeasonMgr.h" #include "Battleground.h" #include "BattlegroundMgr.h" #include "Chat.h" @@ -812,7 +813,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData) if (isRated) { // pussywizard: for rated matches check if season is in progress! - if (!sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)) + if (sArenaSeasonMgr->GetSeasonState() == ARENA_SEASON_STATE_DISABLED) return; ateamId = _player->GetArenaTeamId(arenaslot); diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 8e6d35335..9cfcfd0b1 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -116,7 +116,6 @@ enum WorldBoolConfigs CONFIG_BATTLEGROUND_TRACK_DESERTERS, CONFIG_BG_XP_FOR_KILL, CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, - CONFIG_ARENA_SEASON_IN_PROGRESS, CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE, CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY, CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN, @@ -325,7 +324,6 @@ enum WorldIntConfigs CONFIG_ARENA_PREV_OPPONENTS_DISCARD_TIMER, CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, CONFIG_ARENA_GAMES_REQUIRED, - CONFIG_ARENA_SEASON_ID, CONFIG_ARENA_START_RATING, CONFIG_LEGACY_ARENA_POINTS_CALC, CONFIG_ARENA_START_PERSONAL_RATING, diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index e891444b9..d3df6afa0 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -24,6 +24,7 @@ #include "AchievementMgr.h" #include "AddonMgr.h" #include "ArenaTeamMgr.h" +#include "ArenaSeasonMgr.h" #include "AuctionHouseMgr.h" #include "AutobroadcastMgr.h" #include "BattlefieldMgr.h" @@ -1178,12 +1179,10 @@ void World::LoadConfigSettings(bool reload) _bool_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfigMgr->GetOption("Arena.AutoDistributePoints", false); _int_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfigMgr->GetOption("Arena.AutoDistributeInterval", 7); // pussywizard: spoiled by implementing constant day and hour, always 7 now _int_configs[CONFIG_ARENA_GAMES_REQUIRED] = sConfigMgr->GetOption("Arena.GamesRequired", 10); - _int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetOption("Arena.ArenaSeason.ID", 8); _int_configs[CONFIG_ARENA_START_RATING] = sConfigMgr->GetOption("Arena.ArenaStartRating", 0); _int_configs[CONFIG_LEGACY_ARENA_POINTS_CALC] = sConfigMgr->GetOption("Arena.LegacyArenaPoints", 0); _int_configs[CONFIG_ARENA_START_PERSONAL_RATING] = sConfigMgr->GetOption("Arena.ArenaStartPersonalRating", 0); _int_configs[CONFIG_ARENA_START_MATCHMAKER_RATING] = sConfigMgr->GetOption("Arena.ArenaStartMatchmakerRating", 1500); - _bool_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfigMgr->GetOption("Arena.ArenaSeason.InProgress", true); _float_configs[CONFIG_ARENA_WIN_RATING_MODIFIER_1] = sConfigMgr->GetOption("Arena.ArenaWinRatingModifier1", 48.0f); _float_configs[CONFIG_ARENA_WIN_RATING_MODIFIER_2] = sConfigMgr->GetOption("Arena.ArenaWinRatingModifier2", 24.0f); _float_configs[CONFIG_ARENA_LOSE_RATING_MODIFIER] = sConfigMgr->GetOption("Arena.ArenaLoseRatingModifier", 24.0f); @@ -2123,9 +2122,10 @@ void World::SetInitialWorldSettings() LOG_INFO("server.loading", "Initializing Opcodes..."); opcodeTable.Initialize(); - LOG_INFO("server.loading", "Starting Arena Season..."); - LOG_INFO("server.loading", " "); - sGameEventMgr->StartArenaSeason(); + LOG_INFO("server.loading", "Loading Arena Season Rewards..."); + sArenaSeasonMgr->LoadRewards(); + LOG_INFO("server.loading", "Loading Active Arena Season..."); + sArenaSeasonMgr->LoadActiveSeason(); LOG_INFO("server.loading", "Loading WorldState..."); sWorldState->Load(); diff --git a/src/server/scripts/Commands/cs_arena.cpp b/src/server/scripts/Commands/cs_arena.cpp index b556238e2..3e9882bab 100644 --- a/src/server/scripts/Commands/cs_arena.cpp +++ b/src/server/scripts/Commands/cs_arena.cpp @@ -23,6 +23,8 @@ Category: commandscripts EndScriptData */ #include "ArenaTeamMgr.h" +#include "ArenaSeasonMgr.h" +#include "ArenaTeamFilter.h" #include "Chat.h" #include "CommandScript.h" #include "Player.h" @@ -36,6 +38,19 @@ public: ChatCommandTable GetCommands() const override { + static ChatCommandTable arenaSeasonSetCommandTable = + { + { "state", HandleArenaSeasonSetStateCommand, SEC_ADMINISTRATOR, Console::Yes } + }; + + static ChatCommandTable arenaSeasonCommandTable = + { + { "reward", HandleArenaSeasonRewardCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "deleteteams", HandleArenaSeasonDeleteTeamsCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "start", HandleArenaSeasonStartCommand, SEC_ADMINISTRATOR, Console::Yes }, + { "set", arenaSeasonSetCommandTable } + }; + static ChatCommandTable arenaCommandTable = { { "create", HandleArenaCreateCommand, SEC_ADMINISTRATOR, Console::Yes }, @@ -44,6 +59,7 @@ public: { "captain", HandleArenaCaptainCommand, SEC_ADMINISTRATOR, Console::No }, { "info", HandleArenaInfoCommand, SEC_GAMEMASTER, Console::Yes }, { "lookup", HandleArenaLookupCommand, SEC_GAMEMASTER, Console::No }, + { "season", arenaSeasonCommandTable } }; static ChatCommandTable commandTable = @@ -229,6 +245,80 @@ public: return true; } + + static bool HandleArenaSeasonRewardCommand(ChatHandler* handler, std::string teamsFilterStr) + { + std::unique_ptr uniqueFilter = ArenaTeamFilterFactoryByUserInput().CreateFilterByUserInput(teamsFilterStr); + if (!uniqueFilter) + { + handler->PSendSysMessage("Invalid filter. Please check your input."); + return false; + } + + std::shared_ptr sharedFilter = std::move(uniqueFilter); + + if (!sArenaSeasonMgr->CanDeleteArenaTeams()) + { + handler->PSendSysMessage("Cannot proceed. Make sure there are no active arenas and that rewards exist for the current season."); + handler->PSendSysMessage("Hint: You can disable the arena queue using the following command: .arena season set state 0"); + return false; + } + + handler->PSendSysMessage("Distributing rewards for arena teams (types: "+teamsFilterStr+")..."); + sArenaSeasonMgr->RewardTeamsForTheSeason(sharedFilter); + handler->PSendSysMessage("Rewards distributed."); + return true; + } + + static bool HandleArenaSeasonDeleteTeamsCommand(ChatHandler* handler) + { + handler->PSendSysMessage("Deleting arena teams..."); + sArenaSeasonMgr->DeleteArenaTeams(); + handler->PSendSysMessage("Arena teams deleted."); + return true; + } + + static bool HandleArenaSeasonStartCommand(ChatHandler* handler, uint8 seasonId) + { + if (seasonId == sArenaSeasonMgr->GetCurrentSeason()) + { + sArenaSeasonMgr->SetSeasonState(ARENA_SEASON_STATE_IN_PROGRESS); + handler->PSendSysMessage("Arena season updated."); + return true; + } + + const uint8 maxSeasonId = 8; + if (seasonId > maxSeasonId) + { + handler->PSendSysMessage("Invalid season id."); + return false; + } + + sArenaSeasonMgr->ChangeCurrentSeason(seasonId); + handler->PSendSysMessage("Arena season changed to season {}.", seasonId); + return true; + } + + static bool HandleArenaSeasonSetStateCommand(ChatHandler* handler, uint8 state) + { + ArenaSeasonState seasonState; + switch (state) { + case ARENA_SEASON_STATE_DISABLED: + seasonState = ARENA_SEASON_STATE_DISABLED; + break; + case ARENA_SEASON_STATE_IN_PROGRESS: + seasonState = ARENA_SEASON_STATE_IN_PROGRESS; + break; + default: + handler->PSendSysMessage("Invalid state."); + return false; + } + + sArenaSeasonMgr->SetSeasonState(seasonState); + handler->PSendSysMessage("Arena season updated."); + return true; + } + }; void AddSC_arena_commandscript() diff --git a/src/test/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardDistributorTest.cpp b/src/test/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardDistributorTest.cpp new file mode 100644 index 000000000..300cfc4e0 --- /dev/null +++ b/src/test/server/game/Battlegrounds/ArenaSeason/ArenaSeasonRewardDistributorTest.cpp @@ -0,0 +1,207 @@ +/* + * 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 "Define.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "ArenaSeasonRewardsDistributor.h" + +class MockArenaSeasonTeamRewarder : public ArenaSeasonTeamRewarder +{ +public: + MOCK_METHOD(void, RewardTeamWithRewardGroup, (ArenaTeam* arenaTeam, ArenaSeasonRewardGroup const& rewardGroup), (override)); +}; + +class ArenaSeasonRewardDistributorTest : public ::testing::Test +{ +protected: + void SetUp() override + { + _mockRewarder = std::make_unique(); + _distributor = std::make_unique(_mockRewarder.get()); + } + + std::unique_ptr _mockRewarder; + std::unique_ptr _distributor; +}; + +ArenaTeam ArenaTeamWithRating(int rating, int gamesPlayed) +{ + ArenaTeamStats stats; + stats.Rating = rating; + stats.SeasonGames = gamesPlayed; + ArenaTeam team; + team.SetArenaTeamStats(stats); + return team; +} + +// This test verifies that a single team receives the correct reward group when multiple percent reward groups are defined. +TEST_F(ArenaSeasonRewardDistributorTest, SingleTeamMultiplePctRewardDistribution) +{ + ArenaTeamMgr::ArenaTeamContainer arenaTeams; + std::vector rewardGroups; + + ArenaTeam team = ArenaTeamWithRating(1500, 50); + arenaTeams[1] = &team; + + ArenaSeasonRewardGroup rewardGroup; + rewardGroup.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE; + rewardGroup.minCriteria = 0; + rewardGroup.maxCriteria = 0.5; + rewardGroups.push_back(rewardGroup); + ArenaSeasonRewardGroup rewardGroup2; + rewardGroup2.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE; + rewardGroup2.minCriteria = 0.5; + rewardGroup2.maxCriteria = 100; + rewardGroups.push_back(rewardGroup2); + + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&team, rewardGroup2)).Times(1); + + _distributor->DistributeRewards(arenaTeams, rewardGroups); +} + +// This test verifies that a single team receives the correct reward group when multiple abs percent reward groups are defined. +TEST_F(ArenaSeasonRewardDistributorTest, SingleTeamMultipleAbsRewardDistribution) +{ + ArenaTeamMgr::ArenaTeamContainer arenaTeams; + std::vector rewardGroups; + + ArenaTeam team = ArenaTeamWithRating(1500, 50); + arenaTeams[1] = &team; + + ArenaSeasonRewardGroup rewardGroup; + rewardGroup.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE; + rewardGroup.minCriteria = 1; + rewardGroup.maxCriteria = 1; + rewardGroups.push_back(rewardGroup); + ArenaSeasonRewardGroup rewardGroup2; + rewardGroup2.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE; + rewardGroup2.minCriteria = 2; + rewardGroup2.maxCriteria = 10; + rewardGroups.push_back(rewardGroup2); + + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&team, rewardGroup)).Times(1); + + _distributor->DistributeRewards(arenaTeams, rewardGroups); +} + +// Input: 1000 teams with incremental ratings and two reward groups with 0% - 0.5% and 0.5% - 3% percentage criteria. +// Purpose: Ensures that the top 0.5% of teams receive the first reward and the next 3% receive the second reward. +// Each team should be rewarded only once. +TEST_F(ArenaSeasonRewardDistributorTest, ManyTeamsTwoRewardsDistribution) +{ + ArenaTeamMgr::ArenaTeamContainer arenaTeams; + std::vector rewardGroups; + + const int numTeams = 1000; + ArenaTeam teams[numTeams + 1]; // used just to prevent teams deletion + for (int i = 1; i <= numTeams; i++) + { + teams[i] = ArenaTeamWithRating(i, 50); + arenaTeams[i] = &teams[i]; + } + + ArenaSeasonRewardGroup rewardGroup1; + rewardGroup1.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE; + rewardGroup1.minCriteria = 0.0; // 0% + rewardGroup1.maxCriteria = 0.5; // 0.5% of total teams + rewardGroups.push_back(rewardGroup1); + + ArenaSeasonRewardGroup rewardGroup2; + rewardGroup2.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE; + rewardGroup2.minCriteria = 0.5; // 0.5% (the top 0.5% of the teams) + rewardGroup2.maxCriteria = 3.0; // 3% of total teams + rewardGroups.push_back(rewardGroup2); + + ArenaSeasonRewardGroup rewardGroup3; + rewardGroup3.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE; + rewardGroup3.minCriteria = 3; + rewardGroup3.maxCriteria = 10; + rewardGroups.push_back(rewardGroup3); + + ArenaSeasonRewardGroup rewardGroup4; + rewardGroup4.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE; + rewardGroup4.minCriteria = 10; + rewardGroup4.maxCriteria = 35; + rewardGroups.push_back(rewardGroup4); + + // Top 1 + ArenaSeasonRewardGroup rewardGroup5; + rewardGroup5.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_ABSOLUTE_VALUE; + rewardGroup5.minCriteria = 1; + rewardGroup5.maxCriteria = 1; + rewardGroups.push_back(rewardGroup5); + + // Calculate expected reward distributions + int expectedTeamsInGroup1 = static_cast(0.005 * numTeams); // 0.5% of 1000 = 5 + int expectedTeamsInGroup2 = static_cast(0.03 * numTeams); // 3% of 1000 = 30 + int expectedTeamsInGroup3 = static_cast(0.10 * numTeams); // 10% of 1000 = 100 + int expectedTeamsInGroup4 = static_cast(0.35 * numTeams); // 35% of 1000 = 350 + + int teamsIndexCounter = numTeams; + + // Expectation for rewardGroup1 (top 0.5% of teams) + for (; teamsIndexCounter > numTeams - expectedTeamsInGroup1; --teamsIndexCounter) + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&teams[teamsIndexCounter], rewardGroup1)).Times(1); + + // Expectation for rewardGroup2 (next 3% - 0.5% teams) + for (; teamsIndexCounter > numTeams - expectedTeamsInGroup2; --teamsIndexCounter) + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&teams[teamsIndexCounter], rewardGroup2)).Times(1); + + for (; teamsIndexCounter > numTeams - expectedTeamsInGroup3; --teamsIndexCounter) + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&teams[teamsIndexCounter], rewardGroup3)).Times(1); + + for (; teamsIndexCounter > numTeams - expectedTeamsInGroup4; --teamsIndexCounter) + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&teams[teamsIndexCounter], rewardGroup4)).Times(1); + + // Top 1 + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&teams[numTeams], rewardGroup5)).Times(1); + + _distributor->DistributeRewards(arenaTeams, rewardGroups); +} + +// Input: Three teams where one has fewer than the minimum required games and two have enough games. +// Purpose: Ensures that only teams meeting the minimum required games threshold are eligible for rewards. +TEST_F(ArenaSeasonRewardDistributorTest, MinimumRequiredGamesFilter) +{ + ArenaTeamMgr::ArenaTeamContainer arenaTeams; + std::vector rewardGroups; + + // Creating three teams: one below and two above the minRequiredGames threshold (30 games) + ArenaTeam team1 = ArenaTeamWithRating(1500, 50); // Eligible, as it has 50 games + ArenaTeam team2 = ArenaTeamWithRating(1100, 20); // Not eligible, as it has only 20 games + ArenaTeam team3 = ArenaTeamWithRating(1300, 40); // Eligible, as it has 40 games + + // Adding teams to the container + arenaTeams[1] = &team1; + arenaTeams[2] = &team2; + arenaTeams[3] = &team3; + + // Creating a single reward group covering all teams + ArenaSeasonRewardGroup rewardGroup; + rewardGroup.criteriaType = ARENA_SEASON_REWARD_CRITERIA_TYPE_PERCENT_VALUE; + rewardGroup.minCriteria = 0.0; + rewardGroup.maxCriteria = 100; + rewardGroups.push_back(rewardGroup); + + // We expect the rewarder to be called for team1 and team3, but not for team2. + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&team1, rewardGroup)).Times(1); + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&team3, rewardGroup)).Times(1); + EXPECT_CALL(*_mockRewarder, RewardTeamWithRewardGroup(&team2, rewardGroup)).Times(0); + + _distributor->DistributeRewards(arenaTeams, rewardGroups); +} diff --git a/src/test/server/game/Battlegrounds/ArenaSeason/ArenaTeamFilterTest.cpp b/src/test/server/game/Battlegrounds/ArenaSeason/ArenaTeamFilterTest.cpp new file mode 100644 index 000000000..9db54f200 --- /dev/null +++ b/src/test/server/game/Battlegrounds/ArenaSeason/ArenaTeamFilterTest.cpp @@ -0,0 +1,113 @@ +/* + * 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 "Define.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "ArenaTeamFilter.h" +#include "ArenaTeamMgr.h" +#include "ArenaTeam.h" +#include + +// Used to expose Type property. +class ArenaTeamTest : public ArenaTeam +{ +public: + void SetType(uint8 type) + { + Type = type; + } +}; + +ArenaTeam* ArenaTeamWithType(uint8 type) +{ + ArenaTeamTest* team = new ArenaTeamTest(); + team->SetType(type); + return team; +} + +// Fixture for ArenaTeamFilter tests +class ArenaTeamFilterTest : public ::testing::Test +{ +protected: + void SetUp() override + { + team1 = ArenaTeamWithType(2); // 2v2 + team2 = ArenaTeamWithType(3); // 3v3 + team3 = ArenaTeamWithType(5); // 5v5 + + arenaTeams[1] = team1; + arenaTeams[2] = team2; + arenaTeams[3] = team3; + } + + void TearDown() override + { + delete team1; + delete team2; + delete team3; + } + + ArenaTeamMgr::ArenaTeamContainer arenaTeams; + ArenaTeam* team1; + ArenaTeam* team2; + ArenaTeam* team3; +}; + +// Test for ArenaTeamFilterAllTeams: it should return all teams without filtering +TEST_F(ArenaTeamFilterTest, AllTeamsFilter) +{ + ArenaTeamFilterAllTeams filter; + ArenaTeamMgr::ArenaTeamContainer result = filter.Filter(arenaTeams); + + EXPECT_EQ(result.size(), arenaTeams.size()); + EXPECT_EQ(result[1], team1); + EXPECT_EQ(result[2], team2); + EXPECT_EQ(result[3], team3); +} + +// Test for ArenaTeamFilterByTypes: should filter only teams matching the provided types +TEST_F(ArenaTeamFilterTest, FilterBySpecificTypes) +{ + std::vector validTypes = {2, 3}; // Filtering for 2v2 and 3v3 + ArenaTeamFilterByTypes filter(validTypes); + + ArenaTeamMgr::ArenaTeamContainer result = filter.Filter(arenaTeams); + + EXPECT_EQ(result.size(), 2); // Only 2v2 and 3v3 should pass + EXPECT_EQ(result[1], team1); // team1 is 2v2 + EXPECT_EQ(result[2], team2); // team2 is 3v3 + EXPECT_EQ(result.find(3), result.end()); // team3 (5v5) should be filtered out +} + +// Test for ArenaTeamFilterFactoryByUserInput: should create the correct filter based on input +TEST_F(ArenaTeamFilterTest, FabricCreatesFilterByInput) +{ + ArenaTeamFilterFactoryByUserInput fabric; + + // Test for "all" input + auto allTeamsFilter = fabric.CreateFilterByUserInput("all"); + ArenaTeamMgr::ArenaTeamContainer allTeamsResult = allTeamsFilter->Filter(arenaTeams); + EXPECT_EQ(allTeamsResult.size(), arenaTeams.size()); // All teams should pass + + // Test for "2,3" input + auto specificTypesFilter = fabric.CreateFilterByUserInput("2,3"); + ArenaTeamMgr::ArenaTeamContainer filteredResult = specificTypesFilter->Filter(arenaTeams); + EXPECT_EQ(filteredResult.size(), 2); // Only 2v2 and 3v3 teams should pass + EXPECT_EQ(filteredResult[1], team1); // 2v2 + EXPECT_EQ(filteredResult[2], team2); // 3v3 +} From 3a41901154c31b54dc523f5dd4d7b30a8d44e51a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 12 Feb 2025 10:10:31 +0000 Subject: [PATCH 05/97] chore(DB): import pending files Referenced commit(s): f6a043329710d12a77b99691511cf5884c30b80b --- .../active_arena_season.sql => db_characters/2025_02_12_00.sql} | 1 + .../rev_1725301496947122000.sql => db_world/2025_02_12_00.sql} | 1 + 2 files changed, 2 insertions(+) rename data/sql/updates/{pending_db_characters/active_arena_season.sql => db_characters/2025_02_12_00.sql} (89%) rename data/sql/updates/{pending_db_world/rev_1725301496947122000.sql => db_world/2025_02_12_00.sql} (99%) diff --git a/data/sql/updates/pending_db_characters/active_arena_season.sql b/data/sql/updates/db_characters/2025_02_12_00.sql similarity index 89% rename from data/sql/updates/pending_db_characters/active_arena_season.sql rename to data/sql/updates/db_characters/2025_02_12_00.sql index 726662af3..142fbc78c 100644 --- a/data/sql/updates/pending_db_characters/active_arena_season.sql +++ b/data/sql/updates/db_characters/2025_02_12_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_01_31_00 -> 2025_02_12_00 DROP TABLE IF EXISTS `active_arena_season`; CREATE TABLE `active_arena_season` ( `season_id` TINYINT UNSIGNED NOT NULL, diff --git a/data/sql/updates/pending_db_world/rev_1725301496947122000.sql b/data/sql/updates/db_world/2025_02_12_00.sql similarity index 99% rename from data/sql/updates/pending_db_world/rev_1725301496947122000.sql rename to data/sql/updates/db_world/2025_02_12_00.sql index 7a70fd82e..2903ec2c3 100644 --- a/data/sql/updates/pending_db_world/rev_1725301496947122000.sql +++ b/data/sql/updates/db_world/2025_02_12_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_10_01 -> 2025_02_12_00 DROP TABLE IF EXISTS `arena_season_reward_group`; CREATE TABLE `arena_season_reward_group` ( `id` INT AUTO_INCREMENT PRIMARY KEY, From b17d69b33c175ab4cae38615c5697362e9cf9d69 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 12 Feb 2025 08:16:02 -0300 Subject: [PATCH 06/97] feat(Core/Unit): Add SpellSchoolMask info to the DamageDealt() hook (#21411) --- src/server/game/AI/CoreAI/UnitAI.h | 2 +- src/server/game/AI/SmartScripts/SmartAI.cpp | 2 +- src/server/game/AI/SmartScripts/SmartAI.h | 2 +- src/server/game/Entities/Unit/Unit.cpp | 2 +- .../scripts/EasternKingdoms/ZulAman/boss_janalai.cpp | 2 +- .../scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp | 2 +- .../IcecrownCitadel/boss_blood_prince_council.cpp | 8 ++++---- .../scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index aefb6a673..0a621407a 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -359,7 +359,7 @@ public: virtual void JustExitedCombat() { } /// @brief Called at any Damage to any victim (before damage apply) - virtual void DamageDealt(Unit* /*victim*/, uint32& /*damage*/, DamageEffectType /*damageType*/) { } + virtual void DamageDealt(Unit* /*victim*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) {} /** @brief Called at any Damage from any attacker (before damage apply) * diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 7110e858d..55ebd43d1 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -893,7 +893,7 @@ void SmartAI::IsSummonedBy(WorldObject* summoner) GetScript()->ProcessEventsFor(SMART_EVENT_JUST_SUMMONED, summoner->ToUnit(), 0, 0, false, nullptr, summoner->ToGameObject()); } -void SmartAI::DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType /*damagetype*/) +void SmartAI::DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) { GetScript()->ProcessEventsFor(SMART_EVENT_DAMAGED_TARGET, doneTo, damage); } diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index 19580b3d6..ede658a47 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -131,7 +131,7 @@ public: void IsSummonedBy(WorldObject* summoner) override; // Called at any Damage to any victim (before damage apply) - void DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType damagetyp) override; + void DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType damagetyp, SpellSchoolMask damageSchoolMask) override; // Called when a summoned creature dissapears (UnSommoned) void SummonedCreatureDespawn(Creature* unit) override; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a1ab5a9b8..f1fd08412 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -819,7 +819,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage victim->GetAI()->DamageTaken(attacker, damage, damagetype, damageSchoolMask); if (attacker && attacker->IsAIEnabled) - attacker->GetAI()->DamageDealt(victim, damage, damagetype); + attacker->GetAI()->DamageDealt(victim, damage, damagetype, damageSchoolMask); } // Hook for OnDamage Event diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp index b179c16d0..5caedf30b 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp @@ -173,7 +173,7 @@ struct boss_janalai : public BossAI BossAI::JustSummoned(summon); } - void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damagetype*/) override + void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override { if (_isFlameBreathing) { diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index f842715e4..e02c69e0f 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -294,7 +294,7 @@ public: } } - void DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType /*damagetype*/) override + void DamageDealt(Unit* doneTo, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override { if (doneTo && doneTo == me->GetVictim()) { diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index a77e1a66c..7f18b8474 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -342,7 +342,7 @@ public: } } - void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/) override + void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override { if (!target->IsPlayer()) return; @@ -612,7 +612,7 @@ public: } } - void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/) override + void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override { if (!target->IsPlayer()) return; @@ -906,7 +906,7 @@ public: } } - void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/) override + void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override { if (!target->IsPlayer()) return; @@ -1334,7 +1334,7 @@ public: me->DespawnOrUnsummon(1); } - void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/) override + void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override { if (!target->IsPlayer()) { diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index ae7d9d955..8aa696ac3 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -630,7 +630,7 @@ public: uint32 _timer; bool _damaged, justSpawned; - void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/) override + void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override { if (damage > 0 && !_damaged && me->GetInstanceScript()) { From 5421f13c1330af2e008ae264aabc77d09f8deae9 Mon Sep 17 00:00:00 2001 From: Takenbacon Date: Wed, 12 Feb 2025 05:40:04 -0800 Subject: [PATCH 07/97] fix(Core/Disables): Optimize DisableMgr container (#21416) --- src/server/game/Conditions/DisableMgr.cpp | 10 ++++------ src/server/game/Conditions/DisableMgr.h | 9 +++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp index e1019aee8..abb9681be 100644 --- a/src/server/game/Conditions/DisableMgr.cpp +++ b/src/server/game/Conditions/DisableMgr.cpp @@ -28,7 +28,7 @@ #include "VMapMgr2.h" #include "World.h" -std::map> DisableMgr::m_DisableMap; +DisableMgr::DisableMap DisableMgr::m_DisableMap; DisableMgr::DisableMgr() {} DisableMgr::~DisableMgr() {} @@ -44,10 +44,8 @@ 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(); + for (DisableTypeMap& disableTypeMap : m_DisableMap) + disableTypeMap.clear(); QueryResult result = WorldDatabase.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables"); @@ -99,7 +97,7 @@ void DisableMgr::LoadDisables() * @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) +void DisableMgr::AddDisable(DisableType type, uint32 entry, uint8 flags, std::string const& param0, std::string const& param1) { if (type >= MAX_DISABLE_TYPES) { diff --git a/src/server/game/Conditions/DisableMgr.h b/src/server/game/Conditions/DisableMgr.h index 1c7b7f2a6..bfad29a4d 100644 --- a/src/server/game/Conditions/DisableMgr.h +++ b/src/server/game/Conditions/DisableMgr.h @@ -20,6 +20,7 @@ #include "Define.h" #include "Map.h" + class Unit; enum DisableType @@ -68,19 +69,19 @@ public: static DisableMgr* instance(); void LoadDisables(); - void AddDisable(DisableType type, uint32 entry, uint8 flags, std::string param0, std::string param1); + void AddDisable(DisableType type, uint32 entry, uint8 flags, std::string const& param0, std::string const& 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; + typedef std::unordered_map DisableTypeMap; // global disable map by source - typedef std::map DisableMap; + typedef std::array DisableMap; +private: static DisableMap m_DisableMap; }; From 16fa25b7a9e5724a5715ac9ec8e51a675d0ba159 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 12 Feb 2025 15:06:42 -0300 Subject: [PATCH 08/97] feat(Core/Maps): Implement dynamic respawn rates (#21417) Co-authored-by: r00ty-tc Co-authored-by: Jelle Meeus Co-authored-by Treeston This is a partial cherry-pick of: https://github.com/TrinityCore/TrinityCore/pull/19056/commits/59db2eeea0a35028779fd76372ae06cc98c8086f --- .../apps/worldserver/worldserver.conf.dist | 41 +++++++++++++ .../game/Entities/Creature/Creature.cpp | 1 + .../game/Entities/GameObject/GameObject.cpp | 1 + .../game/Entities/Player/PlayerUpdates.cpp | 4 +- src/server/game/Maps/Map.cpp | 57 +++++++++++++++++++ src/server/game/Maps/Map.h | 5 ++ src/server/game/World/IWorld.h | 4 ++ src/server/game/World/World.cpp | 7 +++ 8 files changed, 118 insertions(+), 2 deletions(-) diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index 9fd477413..e0698fa55 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -67,6 +67,7 @@ # PLAYER DUMP # CUSTOM # DEBUG +# DYNAMIC RESPAWN SETTINGS # ################################################################################################### @@ -4467,6 +4468,46 @@ Debug.Arena = 0 # ################################################################################################### +################################################################################################### +# DYNAMIC RESPAWN SETTINGS +# +# +# Respawn.DynamicRateCreature +# Description: The rate at which the respawn time is adjusted for high player counts in a zone (for creatures). +# Up to this number of players, the respawn rate is unchanged. +# Does not affect instanced creatures, bosses or quest givers. +# At double this number in players, you get twice as many respawns, at three times this number, three times the respawns, and so forth. +# Default: 1 (Disabled) + +Respawn.DynamicRateCreature = 1 + +# +# Respawn.DynamicMinimumCreature +# Description: The minimum respawn time for a creature under dynamic scaling. +# Default: 10 - (10 seconds) + +Respawn.DynamicMinimumCreature = 10 + +# +# Respawn.DynamicRateGameObject +# Description: The rate at which the respawn time is adjusted for high player counts in a zone (for gameobjects). +# Up to this number of players, the respawn rate is unchanged. +# Does not affect instanced objects or quest givers. +# At double this number in players, you get twice as many respawns, at three times this number, three times the respawns, and so forth. +# Default: 1 (Disabled) + +Respawn.DynamicRateGameObject = 1 + +# +# Respawn.DynamicMinimumGameObject +# Description: The minimum respawn time for a gameobject under dynamic scaling. +# Default: 10 - (10 seconds) + +Respawn.DynamicMinimumGameObject = 10 + +# +################################################################################################### + ################################################################################################### # # # GAME SETTINGS END # diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f2e07c735..ad0cf07fe 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1974,6 +1974,7 @@ void Creature::setDeathState(DeathState state, bool despawn) if (state == DeathState::JustDied) { m_corpseRemoveTime = GameTime::GetGameTime().count() + m_corpseDelay; + GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelay); m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay + m_corpseDelay; // always save boss respawn time at death to prevent crash cheating diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 91778e42c..9ed685f9e 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -897,6 +897,7 @@ void GameObject::Update(uint32 diff) return; } + GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelayTime); m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelayTime; // if option not set then object will be saved at grid unload diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index b2a0b46a1..4ffd9efcf 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -1245,9 +1245,7 @@ void Player::UpdateArea(uint32 newArea) void Player::UpdateZone(uint32 newZone, uint32 newArea) { if (!newZone) - { return; - } if (m_zoneUpdateId != newZone) { @@ -1264,6 +1262,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) guild->UpdateMemberData(this, GUILD_MEMBER_DATA_ZONEID, newZone); } + GetMap()->UpdatePlayerZoneStats(m_zoneUpdateId, newZone); + // group update if (GetGroup()) SetGroupUpdateFlag(GROUP_UPDATE_FULL); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index fb13330f5..33e4a8a2c 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -59,6 +59,8 @@ u_map_magic MapLiquidMagic = { {'M', 'L', 'I', 'Q'} }; static uint16 const holetab_h[4] = { 0x1111, 0x2222, 0x4444, 0x8888 }; static uint16 const holetab_v[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 }; +#define MAP_INVALID_ZONE 0xFFFFFFFF + ZoneDynamicInfo::ZoneDynamicInfo() : MusicId(0), WeatherId(WEATHER_STATE_FINE), WeatherGrade(0.0f), OverrideLightId(0), LightFadeInTime(0) { } @@ -252,6 +254,8 @@ Map::Map(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent) : } } + _zonePlayerCountMap.clear(); + //lets initialize visibility distance for map Map::InitVisibilityDistance(); @@ -736,6 +740,23 @@ void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitorUpdateZone(MAP_INVALID_ZONE, 0); player->getHostileRefMgr().deleteReferences(true); // pussywizard: multithreading crashfix bool inWorld = player->IsInWorld(); @@ -2635,6 +2658,40 @@ void Map::SendObjectUpdates() } } +void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32& respawnDelay) const +{ + ASSERT(obj->GetMap() == this); + + float rate = sWorld->getFloatConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICRATE_CREATURE); + + if (rate == 1.0f) + return; + + // No instanced maps (dungeons, battlegrounds, arenas etc.) + if (obj->GetMap()->Instanceable()) + return; + + // No quest givers or world bosses + if (Creature const* creature = obj->ToCreature()) + if (creature->IsQuestGiver() || creature->isWorldBoss()) + return; + + auto it = _zonePlayerCountMap.find(obj->GetZoneId()); + if (it == _zonePlayerCountMap.end()) + return; + uint32 const playerCount = it->second; + if (!playerCount) + return; + double const adjustFactor = rate / playerCount; + if (adjustFactor >= 1.0) // nothing to do here + return; + uint32 const timeMinimum = sWorld->getIntConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE); + if (respawnDelay <= timeMinimum) + return; + + respawnDelay = std::max(std::ceil(respawnDelay * adjustFactor), timeMinimum); +} + void Map::DelayedUpdate(const uint32 t_diff) { for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();) diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index e6e10c26d..8763590e5 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -594,6 +594,9 @@ public: void DeleteRespawnTimes(); [[nodiscard]] time_t GetInstanceResetPeriod() const { return _instanceResetPeriod; } + void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone); + void ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32& respawnDelay) const; + TaskScheduler _creatureRespawnScheduler; void ScheduleCreatureRespawn(ObjectGuid /*creatureGuid*/, Milliseconds /*respawnTimer*/, Position pos = Position()); @@ -780,6 +783,8 @@ private: std::unordered_map _creatureRespawnTimes; std::unordered_map _goRespawnTimes; + std::unordered_map _zonePlayerCountMap; + ZoneDynamicInfoMap _zoneDynamicInfo; uint32 _defaultLight; diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 9cfcfd0b1..50e4dbfc3 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -201,6 +201,8 @@ enum WorldFloatConfigs CONFIG_ARENA_WIN_RATING_MODIFIER_2, CONFIG_ARENA_LOSE_RATING_MODIFIER, CONFIG_ARENA_MATCHMAKER_RATING_MODIFIER, + CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT, + CONFIG_RESPAWN_DYNAMICRATE_CREATURE, FLOAT_CONFIG_VALUE_COUNT }; @@ -420,6 +422,8 @@ enum WorldIntConfigs CONFIG_AUCTIONHOUSE_WORKERTHREADS, CONFIG_SPELL_QUEUE_WINDOW, CONFIG_SUNSREACH_COUNTER_MAX, + CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT, + CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE, INT_CONFIG_VALUE_COUNT }; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d3df6afa0..76c2075b4 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1295,6 +1295,13 @@ void World::LoadConfigSettings(bool reload) _int_configs[CONFIG_DAILY_RBG_MIN_LEVEL_AP_REWARD] = sConfigMgr->GetOption("DailyRBGArenaPoints.MinLevel", 71); + // Respawn + _float_configs[CONFIG_RESPAWN_DYNAMICRATE_CREATURE] = sConfigMgr->GetOption("Respawn.DynamicRateCreature", 1.0f); + _int_configs[CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE] = sConfigMgr->GetOption("Respawn.DynamicMinimumCreature", 10); + + _float_configs[CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT] = sConfigMgr->GetOption("Respawn.DynamicRateGameObject", 1.0f); + _int_configs[CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT] = sConfigMgr->GetOption("Respawn.DynamicMinimumGameObject", 10); + ///- Read the "Data" directory from the config file std::string dataPath = sConfigMgr->GetOption("DataDir", "./"); if (dataPath.empty() || (dataPath.at(dataPath.length() - 1) != '/' && dataPath.at(dataPath.length() - 1) != '\\')) From 00be3a417f68e2b2b3592c00826f8bdc3002dc39 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 12 Feb 2025 15:11:12 -0300 Subject: [PATCH 09/97] fix(DB/Creature): Sacrolash and Alythess should be taunt immune (#21418) --- data/sql/updates/pending_db_world/rev_1739377505525423100.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1739377505525423100.sql diff --git a/data/sql/updates/pending_db_world/rev_1739377505525423100.sql b/data/sql/updates/pending_db_world/rev_1739377505525423100.sql new file mode 100644 index 000000000..2a670a9ca --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1739377505525423100.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `flags_extra` = `flags_extra`|2147483648 WHERE `entry` IN (25166, 25165); From 076e32292f184eea6609d50d47be875859b6ec2e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 12 Feb 2025 18:12:13 +0000 Subject: [PATCH 10/97] chore(DB): import pending files Referenced commit(s): 00be3a417f68e2b2b3592c00826f8bdc3002dc39 --- .../rev_1739377505525423100.sql => db_world/2025_02_12_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1739377505525423100.sql => db_world/2025_02_12_01.sql} (71%) diff --git a/data/sql/updates/pending_db_world/rev_1739377505525423100.sql b/data/sql/updates/db_world/2025_02_12_01.sql similarity index 71% rename from data/sql/updates/pending_db_world/rev_1739377505525423100.sql rename to data/sql/updates/db_world/2025_02_12_01.sql index 2a670a9ca..bcb8ae37a 100644 --- a/data/sql/updates/pending_db_world/rev_1739377505525423100.sql +++ b/data/sql/updates/db_world/2025_02_12_01.sql @@ -1,2 +1,3 @@ +-- DB update 2025_02_12_00 -> 2025_02_12_01 -- UPDATE `creature_template` SET `flags_extra` = `flags_extra`|2147483648 WHERE `entry` IN (25166, 25165); From 47c524581b61f806cdcfc9c3097997ef840ed40e Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Wed, 12 Feb 2025 20:34:56 +0100 Subject: [PATCH 11/97] fix(Core/Scripts): Fix buffer-overflow errors in scripts. (#21419) --- .../BlackrockSpire/instance_blackrock_spire.cpp | 3 ++- .../BlackwingLair/instance_blackwing_lair.cpp | 5 +++-- src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp | 8 ++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp index 0bf609254..05a378899 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp @@ -62,7 +62,8 @@ enum Texts MinionData const minionData[] = { - { NPC_CHROMATIC_ELITE_GUARD, DATA_GENERAL_DRAKKISATH } + { NPC_CHROMATIC_ELITE_GUARD, DATA_GENERAL_DRAKKISATH }, + { 0, 0, } }; DoorData const doorData[] = diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp index e2db717c4..b84025f01 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp @@ -53,8 +53,9 @@ ObjectData const creatureData[] = ObjectData const objectData[] = { - { GO_PORTCULLIS_CHROMAGGUS, DATA_GO_CHROMAGGUS_DOOR }, - { GO_PORTCULLIS_CHROMAGGUS_EXIT, DATA_GO_CHROMAGGUS_DOOR_EXIT } + { GO_PORTCULLIS_CHROMAGGUS, DATA_GO_CHROMAGGUS_DOOR }, + { GO_PORTCULLIS_CHROMAGGUS_EXIT, DATA_GO_CHROMAGGUS_DOOR_EXIT }, + { 0, 0 } }; Position const SummonPosition[8] = diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp index 217e1915d..06a1823ed 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp @@ -80,12 +80,16 @@ float summons[3][4] = {NPC_PHANTASMAL_CLOUDSCRAPER, NPC_PHANTASMAL_CLOUDSCRAPER, NPC_PHANTASMAL_MAMMOTH, NPC_PHANTASMAL_WOLF} }; -float cords[4][4] = +float cords[5][4] = { {1177.47f, 937.722f, 527.405f, 2.21657f}, {968.66f, 1042.53f, 527.32f, 0.077f}, {1164.02f, 1170.85f, 527.321f, 3.66f}, - {1118.31f, 1080.377f, 508.361f, 4.25f} + {1118.31f, 1080.377f, 508.361f, 4.25f}, + // There are 4 phases but with the code like this: + // me->SetHomePosition(cords[phase + 1][0], cords[phase + 1][1], cords[phase + 1][2], cords[phase + 1][3]); + // lets provide fallback position. + {1177.47f, 937.722f, 527.405f, 2.21657f} }; class boss_urom : public CreatureScript From fe2627bc91eaf019b4bc9f856d4662551d131050 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Wed, 12 Feb 2025 21:34:30 +0100 Subject: [PATCH 12/97] fix(Core/Pet): Fix possible crash when using dangling pointer as pets spell target and fix possible memory leak. (#21420) --- src/server/game/Entities/Pet/Pet.cpp | 16 +++++++++------- src/server/game/Entities/Pet/Pet.h | 2 +- src/server/game/Handlers/PetHandler.cpp | 3 +++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 58d7be70e..1c3262654 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -47,7 +47,7 @@ Pet::Pet(Player* owner, PetType type) : Guardian(nullptr, owner ? owner->GetGUID m_auraRaidUpdateMask(0), m_loading(false), m_petRegenTimer(PET_FOCUS_REGEN_INTERVAL), - m_tempspellTarget(nullptr), + m_tempspellTarget(), m_tempoldTarget(), m_tempspellIsPositive(false), m_tempspell(0) @@ -716,9 +716,11 @@ void Pet::Update(uint32 diff) if (m_tempspell) { - Unit* tempspellTarget = m_tempspellTarget; - Unit* tempoldTarget = nullptr; + Unit* tempspellTarget = nullptr; + if (!m_tempspellTarget.IsEmpty()) + tempspellTarget = ObjectAccessor::GetUnit(*this, m_tempspellTarget); + Unit* tempoldTarget = nullptr; if (!m_tempoldTarget.IsEmpty()) tempoldTarget = ObjectAccessor::GetUnit(*this, m_tempoldTarget); @@ -758,7 +760,7 @@ void Pet::Update(uint32 diff) CastSpell(tempspellTarget, tempspell, false); m_tempspell = 0; - m_tempspellTarget = nullptr; + m_tempspellTarget = ObjectGuid::Empty; if (tempspellIsPositive) { @@ -798,7 +800,7 @@ void Pet::Update(uint32 diff) else { m_tempspell = 0; - m_tempspellTarget = nullptr; + m_tempspellTarget = ObjectGuid::Empty; m_tempoldTarget = ObjectGuid::Empty; m_tempspellIsPositive = false; @@ -2433,7 +2435,7 @@ void Pet::CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, ObjectGuid ol if (!spellTarget) return; - m_tempspellTarget = spellTarget; + m_tempspellTarget = spellTarget->GetGUID(); m_tempspell = spellid; m_tempspellIsPositive = spellIsPositive; @@ -2445,7 +2447,7 @@ void Pet::ClearCastWhenWillAvailable() { m_tempspellIsPositive = false; m_tempspell = 0; - m_tempspellTarget = nullptr; + m_tempspellTarget = ObjectGuid::Empty; m_tempoldTarget = ObjectGuid::Empty; } diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 9329a0b07..e737bab11 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -158,7 +158,7 @@ protected: std::unique_ptr m_declinedname; - Unit* m_tempspellTarget; + ObjectGuid m_tempspellTarget; ObjectGuid m_tempoldTarget; bool m_tempspellIsPositive; uint32 m_tempspell; diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 16d7a5458..e7c42cb57 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -441,7 +441,10 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe bool haspositiveeffect = false; if (!unit_target) + { + delete spell; return; + } // search positive effects for spell for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) From c92d50d6ec26f34a994ca80dc06e42cbd0eb9364 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Wed, 12 Feb 2025 22:23:57 +0100 Subject: [PATCH 13/97] fix(Core/Guild): Fix use of guild members' data after deletion. (#21421) --- src/server/game/Guilds/Guild.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 16473a2ac..f4440c5b5 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1556,11 +1556,14 @@ void Guild::HandleRemoveMember(WorldSession* session, std::string_view name) SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_RANK_TOO_HIGH_S, name); else { + // Copy values since everything will be deleted in DeleteMember(). ObjectGuid guid = member->GetGUID(); + std::string memberName = member->GetName(); + // After call to DeleteMember pointer to member becomes invalid DeleteMember(guid, false, true); _LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUID(), guid); - _BroadcastEvent(GE_REMOVED, ObjectGuid::Empty, member->GetName(), player->GetName()); + _BroadcastEvent(GE_REMOVED, ObjectGuid::Empty, memberName, player->GetName()); } } } From 3baa00ae06da1ffd5e095376d8c72e626a98247c Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Wed, 12 Feb 2025 22:24:56 +0100 Subject: [PATCH 14/97] fix(Core/Group): Fix use of a deleted pointer in the group invites list. (#21422) --- src/server/game/Server/WorldSession.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 3f8562362..c12b773a6 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -667,9 +667,10 @@ void WorldSession::LogoutPlayer(bool save) // there are some positive auras from boss encounters that can be kept by logging out and logging in after boss is dead, and may be used on next bosses _player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); - ///- If the player is in a group and LeaveGroupOnLogout is enabled or if the player is invited to a group, remove him. If the group is then only 1 person, disband the group. - if (!_player->GetGroup() || sWorld->getBoolConfig(CONFIG_LEAVE_GROUP_ON_LOGOUT)) - _player->UninviteFromGroup(); + if (Group *group = _player->GetGroupInvite()) + sWorld->getBoolConfig(CONFIG_LEAVE_GROUP_ON_LOGOUT) + ? _player->UninviteFromGroup() // Can disband group. + : group->RemoveInvite(_player); // Just removes invite. // remove player from the group if he is: // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) d) LeaveGroupOnLogout is enabled From 0f0b341d9dc7f78758a3730e5726f63c5af16252 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 12 Feb 2025 20:05:32 -0300 Subject: [PATCH 15/97] fix(Scripts/SunwellPlateau): Fix Brutallus burn timer (#21423) --- .../scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp index abd2df2d8..844e9fd47 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp @@ -91,10 +91,10 @@ struct boss_brutallus : public BossAI Talk(YELL_LOVE); }, 30s); - ScheduleTimedEvent(45s, [&] { + ScheduleTimedEvent(20s, [&] { if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true, true, -SPELL_BURN_DAMAGE)) DoCast(target, SPELL_BURN); - }, 1min); + }, 20s); me->m_Events.AddEventAtOffset([&] { DoCastSelf(SPELL_BERSERK, true); From edcfaeb845c312bf8759e27589b3aeee85975052 Mon Sep 17 00:00:00 2001 From: Takenbacon Date: Wed, 12 Feb 2025 22:04:38 -0800 Subject: [PATCH 16/97] refactor(Core/World): Create WorldSessionMgr to split session logic out of World (#21400) --- src/server/apps/worldserver/Main.cpp | 7 +- .../game/Achievements/AchievementMgr.cpp | 7 +- src/server/game/Battlefield/Battlefield.cpp | 3 +- src/server/game/Battlegrounds/Arena.cpp | 3 +- src/server/game/Cache/WhoListCacheMgr.cpp | 3 +- src/server/game/Chat/Chat.cpp | 9 +- .../game/Entities/Creature/Creature.cpp | 3 +- src/server/game/Entities/Player/Player.cpp | 5 +- src/server/game/Events/GameEventMgr.cpp | 3 +- src/server/game/Handlers/CharacterHandler.cpp | 15 +- src/server/game/Instances/InstanceSaveMgr.cpp | 5 +- src/server/game/Misc/BanMgr.cpp | 13 +- src/server/game/Server/WorldSessionMgr.cpp | 461 ++++++++++++++++ src/server/game/Server/WorldSessionMgr.h | 112 ++++ src/server/game/Server/WorldSocket.cpp | 3 +- src/server/game/Texts/CreatureTextMgr.cpp | 4 +- src/server/game/Texts/CreatureTextMgr.h | 5 +- src/server/game/Weather/Weather.cpp | 3 +- src/server/game/World/IWorld.h | 34 -- src/server/game/World/World.cpp | 491 +----------------- src/server/game/World/World.h | 68 --- src/server/scripts/Commands/cs_message.cpp | 7 +- src/server/scripts/Commands/cs_misc.cpp | 7 +- src/server/scripts/Commands/cs_reset.cpp | 3 +- src/server/scripts/Commands/cs_server.cpp | 9 +- .../scripts/OutdoorPvP/OutdoorPvPEP.cpp | 33 +- .../scripts/OutdoorPvP/OutdoorPvPHP.cpp | 9 +- .../scripts/OutdoorPvP/OutdoorPvPNA.cpp | 11 +- .../scripts/OutdoorPvP/OutdoorPvPSI.cpp | 5 +- .../scripts/OutdoorPvP/OutdoorPvPTF.cpp | 9 +- .../scripts/OutdoorPvP/OutdoorPvPZM.cpp | 17 +- src/test/mocks/WorldMock.h | 32 -- 32 files changed, 713 insertions(+), 686 deletions(-) create mode 100644 src/server/game/Server/WorldSessionMgr.cpp create mode 100644 src/server/game/Server/WorldSessionMgr.h diff --git a/src/server/apps/worldserver/Main.cpp b/src/server/apps/worldserver/Main.cpp index 0f5a96208..26a13985f 100644 --- a/src/server/apps/worldserver/Main.cpp +++ b/src/server/apps/worldserver/Main.cpp @@ -49,6 +49,7 @@ #include "SharedDefines.h" #include "SteadyTimer.h" #include "World.h" +#include "WorldSessionMgr.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" #include @@ -285,7 +286,7 @@ int main(int argc, char** argv) sMetric->Initialize(realm.Name, *ioContext, []() { - METRIC_VALUE("online_players", sWorld->GetPlayerCount()); + METRIC_VALUE("online_players", sWorldSessionMgr->GetPlayerCount()); METRIC_VALUE("db_queue_login", uint64(LoginDatabase.QueueSize())); METRIC_VALUE("db_queue_character", uint64(CharacterDatabase.QueueSize())); METRIC_VALUE("db_queue_world", uint64(WorldDatabase.QueueSize())); @@ -357,8 +358,8 @@ int main(int argc, char** argv) std::shared_ptr sWorldSocketMgrHandle(nullptr, [](void*) { - sWorld->KickAll(); // save and kick all players - sWorld->UpdateSessions(1); // real players unload required UpdateSessions call + sWorldSessionMgr->KickAll(); // save and kick all players + sWorldSessionMgr->UpdateSessions(1); // real players unload required UpdateSessions call sWorldSocketMgr.StopNetwork(); diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 13d989385..036621656 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -44,6 +44,7 @@ #include "SpellMgr.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) { @@ -728,7 +729,7 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) data << GetPlayer()->GetGUID(); data << uint32(achievement->ID); data << uint32(0); // display name as plain string in chat (always 0 for guild) - sWorld->SendGlobalMessage(&data); + sWorldSessionMgr->SendGlobalMessage(&data); } else { @@ -741,10 +742,10 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) data << uint32(achievement->ID); std::size_t linkTypePos = data.wpos(); data << uint32(1); // display name as clickable link in chat - sWorld->SendGlobalMessage(&data, nullptr, teamId); + sWorldSessionMgr->SendGlobalMessage(&data, nullptr, teamId); data.put(linkTypePos, 0); // display name as plain string in chat - sWorld->SendGlobalMessage(&data, nullptr, teamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE); + sWorldSessionMgr->SendGlobalMessage(&data, nullptr, teamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE); } } // if player is in world he can tell his friends about new achievement diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index ae10a9f9d..0b25e18d1 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -31,6 +31,7 @@ #include "ObjectMgr.h" #include "Transport.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" /// @todo: this import is not necessary for compilation and marked as unused by the IDE // however, for some reasons removing it would cause a damn linking issue @@ -143,7 +144,7 @@ bool Battlefield::Update(uint32 diff) { if (m_Timer <= diff) { - if (!IsEnabled() || (!IsWarTime() && sWorld->GetActiveSessionCount() > 3500)) // if WG is disabled or there is more than 3500 connections, switch automaticly + if (!IsEnabled() || (!IsWarTime() && sWorldSessionMgr->GetActiveSessionCount() > 3500)) // if WG is disabled or there is more than 3500 connections, switch automaticly { m_isActive = true; EndBattle(false); diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp index b0ecc3ab5..dc200abda 100644 --- a/src/server/game/Battlegrounds/Arena.cpp +++ b/src/server/game/Battlegrounds/Arena.cpp @@ -25,6 +25,7 @@ #include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" //#include "WorldStatePackets.h" void ArenaScore::AppendToPacket(WorldPacket& data) @@ -224,7 +225,7 @@ void Arena::EndBattleground(TeamId winnerTeamId) { // pussywizard: arena logs in database uint32 fightId = sArenaTeamMgr->GetNextArenaLogId(); - uint32 currOnline = sWorld->GetActiveSessionCount(); + uint32 currOnline = sWorldSessionMgr->GetActiveSessionCount(); CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); CharacterDatabasePreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_FIGHT); diff --git a/src/server/game/Cache/WhoListCacheMgr.cpp b/src/server/game/Cache/WhoListCacheMgr.cpp index 8225627f6..c92ff7919 100644 --- a/src/server/game/Cache/WhoListCacheMgr.cpp +++ b/src/server/game/Cache/WhoListCacheMgr.cpp @@ -19,6 +19,7 @@ #include "GuildMgr.h" #include "ObjectAccessor.h" #include "World.h" +#include "WorldSessionMgr.h" WhoListCacheMgr* WhoListCacheMgr::instance() { @@ -30,7 +31,7 @@ void WhoListCacheMgr::Update() { // clear current list _whoListStorage.clear(); - _whoListStorage.reserve(sWorld->GetPlayerCount() + 1); + _whoListStorage.reserve(sWorldSessionMgr->GetPlayerCount() + 1); for (auto const& [guid, player] : ObjectAccessor::GetPlayers()) { diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index d3de85c0d..26bfaf34c 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -30,6 +30,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include Player* ChatHandler::GetPlayer() const @@ -188,7 +189,7 @@ void ChatHandler::SendGlobalSysMessage(const char* str) for (std::string_view line : Acore::Tokenize(str, '\n', true)) { BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line); - sWorld->SendGlobalMessage(&data); + sWorldSessionMgr->SendGlobalMessage(&data); } } @@ -198,7 +199,7 @@ void ChatHandler::SendGlobalGMSysMessage(const char* str) for (std::string_view line : Acore::Tokenize(str, '\n', true)) { BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line); - sWorld->SendGlobalGMMessage(&data); + sWorldSessionMgr->SendGlobalGMMessage(&data); } } @@ -442,8 +443,8 @@ bool ChatHandler::HasSession() const void ChatHandler::DoForAllValidSessions(std::function exec) { - SessionMap::const_iterator itr; - for (itr = sWorld->GetAllSessions().begin(); itr != sWorld->GetAllSessions().end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (Player* player = itr->second->GetPlayer()) if (player->IsInWorld()) exec(player); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index ad0cf07fe..6b60457a9 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -47,6 +47,7 @@ #include "WaypointMovementGenerator.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" /// @todo: this import is not necessary for compilation and marked as unused by the IDE // however, for some reasons removing it would cause a damn linking issue @@ -2818,7 +2819,7 @@ void Creature::SendZoneUnderAttackMessage(Player* attacker) { WorldPacket data(SMSG_ZONE_UNDER_ATTACK, 4); data << (uint32)GetAreaId(); - sWorld->SendGlobalMessage(&data, nullptr, (attacker->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE)); + sWorldSessionMgr->SendGlobalMessage(&data, nullptr, (attacker->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE)); } /** diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 5a51b10a4..1787b8ccb 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -84,6 +84,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include "WorldState.h" #include @@ -363,7 +364,7 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this) m_ControlledByPlayer = true; - sWorld->IncreasePlayerCount(); + sWorldSessionMgr->IncreasePlayerCount(); m_ChampioningFaction = 0; @@ -447,7 +448,7 @@ Player::~Player() delete m_reputationMgr; delete _cinematicMgr; - sWorld->DecreasePlayerCount(); + sWorldSessionMgr->DecreasePlayerCount(); if (!m_isInSharedVisionOf.empty()) { diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index b380b8399..277d227e3 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -31,6 +31,7 @@ #include "Transport.h" #include "UnitAI.h" #include "World.h" +#include "WorldSessionMgr.h" #include "WorldStatePackets.h" #include @@ -1686,7 +1687,7 @@ void GameEventMgr::UpdateWorldStates(uint16 eventId, bool Activate) WorldPackets::WorldState::UpdateWorldState worldstate; worldstate.VariableID = bl->HolidayWorldStateId; worldstate.Value = Activate ? 1 : 0; - sWorld->SendGlobalMessage(worldstate.Write()); + sWorldSessionMgr->SendGlobalMessage(worldstate.Write()); } } } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index b5d85760e..a6478b461 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -57,6 +57,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" class LoginQueryHolder : public CharacterDatabaseQueryHolder { @@ -612,7 +613,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) uint32 initAccountId = GetAccountId(); // can't delete loaded character - if (ObjectAccessor::FindConnectedPlayer(guid) || sWorld->FindOfflineSessionForCharacterGUID(guid.GetCounter())) + if (ObjectAccessor::FindConnectedPlayer(guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(guid.GetCounter())) { sScriptMgr->OnPlayerFailedDelete(guid, initAccountId); return; @@ -698,14 +699,14 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData) }; // pussywizard: - if (WorldSession* sess = sWorld->FindOfflineSessionForCharacterGUID(playerGuid.GetCounter())) + if (WorldSession* sess = sWorldSessionMgr->FindOfflineSessionForCharacterGUID(playerGuid.GetCounter())) if (sess->GetAccountId() != GetAccountId()) { SendCharLogin(CHAR_LOGIN_DUPLICATE_CHARACTER); return; } // pussywizard: - if (WorldSession* sess = sWorld->FindOfflineSession(GetAccountId())) + if (WorldSession* sess = sWorldSessionMgr->FindOfflineSession(GetAccountId())) { Player* p = sess->GetPlayer(); if (!p || sess->IsKicked()) @@ -1101,7 +1102,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder) { bool isReferrer = pCurrChar->GetSession()->IsARecruiter(); - for (auto const& [accID, session] : sWorld->GetAllSessions()) + for (auto const& [accID, session] : sWorldSessionMgr->GetAllSessions()) { if (!session->GetRecruiterId() && !session->IsARecruiter()) continue; @@ -1390,7 +1391,7 @@ void WorldSession::HandleCharRenameCallBack(std::shared_ptr atLoginFlags &= ~AT_LOGIN_RENAME; // pussywizard: - if (ObjectAccessor::FindConnectedPlayer(ObjectGuid::Create(guidLow)) || sWorld->FindOfflineSessionForCharacterGUID(guidLow)) + if (ObjectAccessor::FindConnectedPlayer(ObjectGuid::Create(guidLow)) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(guidLow)) { SendCharRename(CHAR_CREATE_ERROR, renameInfo.get()); return; @@ -1626,7 +1627,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData) } // pussywizard: - if (ObjectAccessor::FindConnectedPlayer(customizeInfo->Guid) || sWorld->FindOfflineSessionForCharacterGUID(customizeInfo->Guid.GetCounter())) + if (ObjectAccessor::FindConnectedPlayer(customizeInfo->Guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(customizeInfo->Guid.GetCounter())) { recvData.rfinish(); WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); @@ -1928,7 +1929,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) >> factionChangeInfo->Race; // pussywizard: - if (ObjectAccessor::FindConnectedPlayer(factionChangeInfo->Guid) || sWorld->FindOfflineSessionForCharacterGUID(factionChangeInfo->Guid.GetCounter())) + if (ObjectAccessor::FindConnectedPlayer(factionChangeInfo->Guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(factionChangeInfo->Guid.GetCounter())) { SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get()); return; diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index cf9bd7967..5088742c8 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -32,6 +32,7 @@ #include "Timer.h" #include "Transport.h" #include "World.h" +#include "WorldSessionMgr.h" uint16 InstanceSaveMgr::ResetTimeDelay[] = {3600, 900, 300, 60, 0}; PlayerBindStorage InstanceSaveMgr::playerBindStorage; @@ -494,7 +495,9 @@ void InstanceSaveMgr::Update() { LOG_INFO("instance.save", "Instance ID reset occurred, sending updated calendar and raid info to all players!"); WorldPacket dummy; - for (SessionMap::const_iterator itr = sWorld->GetAllSessions().begin(); itr != sWorld->GetAllSessions().end(); ++itr) + + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (Player* plr = itr->second->GetPlayer()) { itr->second->HandleCalendarGetCalendar(dummy); diff --git a/src/server/game/Misc/BanMgr.cpp b/src/server/game/Misc/BanMgr.cpp index e3102c67e..70fcf80d3 100644 --- a/src/server/game/Misc/BanMgr.cpp +++ b/src/server/game/Misc/BanMgr.cpp @@ -26,6 +26,7 @@ #include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" BanMgr* BanMgr::instance() { @@ -69,11 +70,11 @@ BanReturn BanMgr::BanAccount(std::string const& AccountName, std::string const& stmt->SetData(3, Reason); trans->Append(stmt); - if (WorldSession* session = sWorld->FindSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban Account at condition 'FindSession(account)->GetPlayerName() != author'"); - if (WorldSession* session = sWorld->FindOfflineSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindOfflineSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban Account at condition 'FindOfflineSession(account)->GetPlayerName() != author'"); @@ -131,11 +132,11 @@ BanReturn BanMgr::BanAccountByPlayerName(std::string const& CharacterName, std:: stmt->SetData(3, Reason); trans->Append(stmt); - if (WorldSession* session = sWorld->FindSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban Account at condition 'FindSession(account)->GetPlayerName() != author'"); - if (WorldSession* session = sWorld->FindOfflineSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindOfflineSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban Account at condition 'FindOfflineSession(account)->GetPlayerName() != author'"); @@ -205,11 +206,11 @@ BanReturn BanMgr::BanIP(std::string const& IP, std::string const& Duration, std: Field* fields = resultAccounts->Fetch(); uint32 AccountID = fields[0].Get(); - if (WorldSession* session = sWorld->FindSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban IP at condition 'FindSession(account)->GetPlayerName() != author'"); - if (WorldSession* session = sWorld->FindOfflineSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindOfflineSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban IP at condition 'FindOfflineSession(account)->GetPlayerName() != author'"); } while (resultAccounts->NextRow()); diff --git a/src/server/game/Server/WorldSessionMgr.cpp b/src/server/game/Server/WorldSessionMgr.cpp new file mode 100644 index 000000000..5bad2e10a --- /dev/null +++ b/src/server/game/Server/WorldSessionMgr.cpp @@ -0,0 +1,461 @@ +/* + * 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 "Chat.h" +#include "ChatPackets.h" +#include "GameTime.h" +#include "Metric.h" +#include "Player.h" +#include "World.h" +#include "WorldSession.h" +#include "WorldSessionMgr.h" + +WorldSessionMgr* WorldSessionMgr::Instance() +{ + static WorldSessionMgr instance; + return &instance; +} + +WorldSessionMgr::WorldSessionMgr() +{ + _playerLimit = 0; + _maxActiveSessionCount = 0; + _maxQueuedSessionCount = 0; + _playerCount = 0; + _maxPlayerCount = 0; +} + +WorldSessionMgr::~WorldSessionMgr() +{ + ///- Empty the kicked session set + while (!_sessions.empty()) + { + // not remove from queue, prevent loading new sessions + delete _sessions.begin()->second; + _sessions.erase(_sessions.begin()); + } + + while (!_offlineSessions.empty()) + { + delete _offlineSessions.begin()->second; + _offlineSessions.erase(_offlineSessions.begin()); + } +} + +/// Find a session by its id +WorldSession* WorldSessionMgr::FindSession(uint32 id) const +{ + SessionMap::const_iterator itr = _sessions.find(id); + + if (itr != _sessions.end()) + return itr->second; // also can return nullptr for kicked session + else + return nullptr; +} + +WorldSession* WorldSessionMgr::FindOfflineSession(uint32 id) const +{ + SessionMap::const_iterator itr = _offlineSessions.find(id); + if (itr != _offlineSessions.end()) + return itr->second; + else + return nullptr; +} + +WorldSession* WorldSessionMgr::FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const +{ + if (_offlineSessions.empty()) + return nullptr; + + for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _offlineSessions.end(); ++itr) + if (itr->second->GetGuidLow() == guidLow) + return itr->second; + + return nullptr; +} + +void WorldSessionMgr::UpdateSessions(uint32 const diff) +{ + { + METRIC_DETAILED_NO_THRESHOLD_TIMER("world_update_time", + METRIC_TAG("type", "Add sessions"), + METRIC_TAG("parent_type", "Update sessions")); + + ///- Add new sessions + WorldSession* sess = nullptr; + while (_addSessQueue.next(sess)) + { + AddSession_(sess); + } + } + + ///- Then send an update signal to remaining ones + for (SessionMap::iterator itr = _sessions.begin(), next; itr != _sessions.end(); itr = next) + { + next = itr; + ++next; + + ///- and remove not active sessions from the list + WorldSession* pSession = itr->second; + WorldSessionFilter updater(pSession); + + // pussywizard: + if (pSession->HandleSocketClosed()) + { + if (!RemoveQueuedPlayer(pSession) && sWorld->getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) + _disconnects[pSession->GetAccountId()] = GameTime::GetGameTime().count(); + _sessions.erase(itr); + // there should be no offline session if current one is logged onto a character + SessionMap::iterator iter; + if ((iter = _offlineSessions.find(pSession->GetAccountId())) != _offlineSessions.end()) + { + WorldSession* tmp = iter->second; + _offlineSessions.erase(iter); + delete tmp; + } + pSession->SetOfflineTime(GameTime::GetGameTime().count()); + _offlineSessions[pSession->GetAccountId()] = pSession; + continue; + } + + [[maybe_unused]] uint32 currentSessionId = itr->first; + METRIC_DETAILED_TIMER("world_update_sessions_time", METRIC_TAG("account_id", std::to_string(currentSessionId))); + + if (!pSession->Update(diff, updater)) + { + if (!RemoveQueuedPlayer(pSession) && sWorld->getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) + _disconnects[pSession->GetAccountId()] = GameTime::GetGameTime().count(); + _sessions.erase(itr); + delete pSession; + } + } + + // pussywizard: + if (_offlineSessions.empty()) + return; + uint32 currTime = GameTime::GetGameTime().count(); + for (SessionMap::iterator itr = _offlineSessions.begin(), next; itr != _offlineSessions.end(); itr = next) + { + next = itr; + ++next; + WorldSession* pSession = itr->second; + if (!pSession->GetPlayer() || pSession->GetOfflineTime() + 60 < currTime || pSession->IsKicked()) + { + _offlineSessions.erase(itr); + delete pSession; + } + } +} + +/// Remove a given session +bool WorldSessionMgr::KickSession(uint32 id) +{ + ///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation + SessionMap::const_iterator itr = _sessions.find(id); + + if (itr != _sessions.end() && itr->second) + { + if (itr->second->PlayerLoading()) + return false; + + itr->second->KickPlayer("KickSession", false); + } + + return true; +} + +/// Kick (and save) all players +void WorldSessionMgr::KickAll() +{ + _queuedPlayer.clear(); // prevent send queue update packet and login queued sessions + + // session not removed at kick and will removed in next update tick + for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + itr->second->KickPlayer("KickAll sessions"); + + // pussywizard: kick offline sessions + for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _offlineSessions.end(); ++itr) + itr->second->KickPlayer("KickAll offline sessions"); +} + +/// Kick (and save) all players with security level less `sec` +void WorldSessionMgr::KickAllLess(AccountTypes sec) +{ + // session not removed at kick and will removed in next update tick + for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + if (itr->second->GetSecurity() < sec) + itr->second->KickPlayer("KickAllLess"); +} + +void WorldSessionMgr::AddSession(WorldSession* session) +{ + _addSessQueue.add(session); +} + +void WorldSessionMgr::AddQueuedPlayer(WorldSession* session) +{ + session->SetInQueue(true); + _queuedPlayer.push_back(session); + + // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. + session->SendAuthResponse(AUTH_WAIT_QUEUE, false, GetQueuePos(session)); +} + +bool WorldSessionMgr::RemoveQueuedPlayer(WorldSession* session) +{ + uint32 sessions = GetActiveSessionCount(); + + uint32 position = 1; + Queue::iterator iter = _queuedPlayer.begin(); + + // search to remove and count skipped positions + bool found = false; + + for (; iter != _queuedPlayer.end(); ++iter, ++position) + { + if (*iter == session) + { + session->SetInQueue(false); + session->ResetTimeOutTime(false); + iter = _queuedPlayer.erase(iter); + found = true; + break; + } + } + + // if session not queued then it was an active session + if (!found) + { + ASSERT(sessions > 0); + --sessions; + } + + // accept first in queue + if ((!GetPlayerAmountLimit() || sessions < GetPlayerAmountLimit()) && !_queuedPlayer.empty()) + { + WorldSession* pop_sess = _queuedPlayer.front(); + pop_sess->InitializeSession(); + _queuedPlayer.pop_front(); + + // update iter to point first queued socket or end() if queue is empty now + iter = _queuedPlayer.begin(); + position = 1; + } + + // update queue position from iter to end() + for (; iter != _queuedPlayer.end(); ++iter, ++position) + (*iter)->SendAuthWaitQueue(position); + + return found; +} + +int32 WorldSessionMgr::GetQueuePos(WorldSession* session) +{ + uint32 position = 1; + + for (Queue::const_iterator iter = _queuedPlayer.begin(); iter != _queuedPlayer.end(); ++iter, ++position) + if ((*iter) == session) + return position; + + return 0; +} + +void WorldSessionMgr::AddSession_(WorldSession* session) +{ + ASSERT(session); + + // kick existing session with same account (if any) + // if character on old session is being loaded, then return + if (!KickSession(session->GetAccountId())) + { + session->KickPlayer("kick existing session with same account"); + delete session; // session not added yet in session list, so not listed in queue + return; + } + + SessionMap::const_iterator old = _sessions.find(session->GetAccountId()); + if (old != _sessions.end()) + { + WorldSession* oldSession = old->second; + + if (!RemoveQueuedPlayer(oldSession) && sWorld->getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) + _disconnects[session->GetAccountId()] = GameTime::GetGameTime().count(); + + // pussywizard: + if (oldSession->HandleSocketClosed()) + { + // there should be no offline session if current one is logged onto a character + SessionMap::iterator iter; + if ((iter = _offlineSessions.find(oldSession->GetAccountId())) != _offlineSessions.end()) + { + WorldSession* tmp = iter->second; + _offlineSessions.erase(iter); + delete tmp; + } + oldSession->SetOfflineTime(GameTime::GetGameTime().count()); + _offlineSessions[oldSession->GetAccountId()] = oldSession; + } + else + { + delete oldSession; + } + } + + _sessions[session->GetAccountId()] = session; + + uint32 Sessions = GetActiveAndQueuedSessionCount(); + uint32 pLimit = GetPlayerAmountLimit(); + + // don't count this session when checking player limit + --Sessions; + + if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(session->GetSecurity()) && !session->CanSkipQueue() && !HasRecentlyDisconnected(session)) + { + AddQueuedPlayer(session); + UpdateMaxSessionCounters(); + return; + } + + session->InitializeSession(); + + UpdateMaxSessionCounters(); +} + +bool WorldSessionMgr::HasRecentlyDisconnected(WorldSession* session) +{ + if (!session) + return false; + + if (uint32 tolerance = sWorld->getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) + { + for (DisconnectMap::iterator i = _disconnects.begin(); i != _disconnects.end();) + { + if ((GameTime::GetGameTime().count() - i->second) < tolerance) + { + if (i->first == session->GetAccountId()) + return true; + ++i; + } + else + _disconnects.erase(i++); + } + } + return false; +} + +void WorldSessionMgr::UpdateMaxSessionCounters() +{ + _maxActiveSessionCount = std::max(_maxActiveSessionCount, uint32(_sessions.size() - _queuedPlayer.size())); + _maxQueuedSessionCount = std::max(_maxQueuedSessionCount, uint32(_queuedPlayer.size())); +} + +/// Send a packet to all players (except self if mentioned) +void WorldSessionMgr::SendGlobalMessage(WorldPacket const* packet, WorldSession* self, TeamId teamId) +{ + SessionMap::const_iterator itr; + for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) + { + if (itr->second && + itr->second->GetPlayer() && + itr->second->GetPlayer()->IsInWorld() && + itr->second != self && + (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) + { + itr->second->SendPacket(packet); + } + } +} + +/// Send a packet to all GMs (except self if mentioned) +void WorldSessionMgr::SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self, TeamId teamId) +{ + SessionMap::iterator itr; + for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) + { + if (itr->second && + itr->second->GetPlayer() && + itr->second->GetPlayer()->IsInWorld() && + itr->second != self && + !AccountMgr::IsPlayerAccount(itr->second->GetSecurity()) && + (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) + { + itr->second->SendPacket(packet); + } + } +} + +/// Send a packet to all players (or players selected team) in the zone (except self if mentioned) +bool WorldSessionMgr::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self, TeamId teamId) +{ + bool foundPlayerToSend = false; + SessionMap::const_iterator itr; + + for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) + { + if (itr->second && + itr->second->GetPlayer() && + itr->second->GetPlayer()->IsInWorld() && + itr->second->GetPlayer()->GetZoneId() == zone && + itr->second != self && + (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) + { + itr->second->SendPacket(packet); + foundPlayerToSend = true; + } + } + + return foundPlayerToSend; +} + +/// Send a server message to the user(s) +void WorldSessionMgr::SendServerMessage(ServerMessageType messageID, std::string stringParam /*= ""*/, Player* player /*= nullptr*/) +{ + WorldPackets::Chat::ChatServerMessage chatServerMessage; + chatServerMessage.MessageID = int32(messageID); + if (messageID <= SERVER_MSG_STRING) + chatServerMessage.StringParam = stringParam; + + if (player) + player->SendDirectMessage(chatServerMessage.Write()); + else + SendGlobalMessage(chatServerMessage.Write()); +} + +/// Send a System Message to all players in the zone (except self if mentioned) +void WorldSessionMgr::SendZoneText(uint32 zone, std::string text, WorldSession* self, TeamId teamId) +{ + WorldPacket data; + ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text.c_str()); + SendZoneMessage(zone, &data, self, teamId); +} + +void WorldSessionMgr::DoForAllOnlinePlayers(std::function exec) +{ + std::shared_lock lock(*HashMapHolder::GetLock()); + for (auto const& it : ObjectAccessor::GetPlayers()) + { + if (Player* player = it.second) + { + if (!player->IsInWorld()) + { + continue; + } + + exec(player); + } + } +} diff --git a/src/server/game/Server/WorldSessionMgr.h b/src/server/game/Server/WorldSessionMgr.h new file mode 100644 index 000000000..364dad1ed --- /dev/null +++ b/src/server/game/Server/WorldSessionMgr.h @@ -0,0 +1,112 @@ +/* + * 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 . + */ + +#ifndef __WORLDSESSIONMGR_H +#define __WORLDSESSIONMGR_H + +#include "Common.h" +#include "IWorld.h" +#include "LockedQueue.h" +#include "ObjectGuid.h" +#include +#include + +class Player; +class WorldPacket; +class WorldSession; + +class WorldSessionMgr +{ +public: + static WorldSessionMgr* Instance(); + + WorldSessionMgr(); + ~WorldSessionMgr(); + + WorldSession* FindSession(uint32 id) const; + WorldSession* FindOfflineSession(uint32 id) const; + WorldSession* FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const; + + void UpdateSessions(uint32 const diff); + + bool KickSession(uint32 id); + void KickAll(); + void KickAllLess(AccountTypes sec); + void AddSession(WorldSession* session); + + void AddQueuedPlayer(WorldSession* session); + bool RemoveQueuedPlayer(WorldSession* session); + int32 GetQueuePos(WorldSession* session); + bool HasRecentlyDisconnected(WorldSession* session); + + typedef std::unordered_map SessionMap; + SessionMap const& GetAllSessions() const { return _sessions; } + + /// Get the number of current active sessions + void UpdateMaxSessionCounters(); + uint32 GetActiveAndQueuedSessionCount() const { return _sessions.size(); } + uint32 GetActiveSessionCount() const { return _sessions.size() - _queuedPlayer.size(); } + uint32 GetQueuedSessionCount() const { return _queuedPlayer.size(); } + /// Get the maximum number of parallel sessions on the server since last reboot + uint32 GetMaxQueuedSessionCount() const { return _maxQueuedSessionCount; } + uint32 GetMaxActiveSessionCount() const { return _maxActiveSessionCount; } + /// Get number of players + inline uint32 GetPlayerCount() const { return _playerCount; } + inline uint32 GetMaxPlayerCount() const { return _maxPlayerCount; } + /// Active session server limit + void SetPlayerAmountLimit(uint32 limit) { _playerLimit = limit; } + uint32 GetPlayerAmountLimit() const { return _playerLimit; } + + /// Increase/Decrease number of players + inline void IncreasePlayerCount() + { + _playerCount++; + _maxPlayerCount = std::max(_maxPlayerCount, _playerCount); + } + inline void DecreasePlayerCount() { _playerCount--; } + + void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL); + void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL); + bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL); + void SendZoneText(uint32 zone, std::string text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL); + void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr); + + void DoForAllOnlinePlayers(std::function exec); + +private: + LockedQueue _addSessQueue; + void AddSession_(WorldSession* session); + + SessionMap _sessions; + SessionMap _offlineSessions; + + typedef std::unordered_map DisconnectMap; + DisconnectMap _disconnects; + + typedef std::list Queue; + Queue _queuedPlayer; + + uint32 _playerLimit; + uint32 _maxActiveSessionCount; + uint32 _maxQueuedSessionCount; + uint32 _playerCount; + uint32 _maxPlayerCount; +}; + +#define sWorldSessionMgr WorldSessionMgr::Instance() + +#endif diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index fefe24949..a745ecc65 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -30,6 +30,7 @@ #include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include "zlib.h" #include @@ -713,7 +714,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr authSes _worldSession->InitWarden(account.SessionKey, account.OS); } - sWorld->AddSession(_worldSession); + sWorldSessionMgr->AddSession(_worldSession); AsyncRead(); } diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp index aad55356b..c471c7815 100644 --- a/src/server/game/Texts/CreatureTextMgr.cpp +++ b/src/server/game/Texts/CreatureTextMgr.cpp @@ -387,8 +387,8 @@ void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket const* } case TEXT_RANGE_WORLD: { - SessionMap const& smap = sWorld->GetAllSessions(); - for (SessionMap::const_iterator itr = smap.begin(); itr != smap.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (Player* player = itr->second->GetPlayer()) if ((teamId == TEAM_NEUTRAL || player->GetTeamId() == teamId) && (!gmOnly || player->IsGameMaster())) player->GetSession()->SendPacket(data); diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h index 11b7c1569..f88179d45 100644 --- a/src/server/game/Texts/CreatureTextMgr.h +++ b/src/server/game/Texts/CreatureTextMgr.h @@ -23,6 +23,7 @@ #include "ObjectAccessor.h" #include "SharedDefines.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" enum CreatureTextRange { @@ -232,8 +233,8 @@ void CreatureTextMgr::SendChatPacket(WorldObject* source, Builder const& builder } case TEXT_RANGE_WORLD: { - SessionMap const& smap = sWorld->GetAllSessions(); - for (SessionMap::const_iterator itr = smap.begin(); itr != smap.end(); ++itr) + WorldSessionMgr::SessionMap const& smap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = smap.begin(); itr != smap.end(); ++itr) if (Player* player = itr->second->GetPlayer()) if ((teamId == TEAM_NEUTRAL || player->GetTeamId() == teamId) && (!gmOnly || player->IsGameMaster())) localizer(player); diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp index bfecc5c6a..bc22e7db6 100644 --- a/src/server/game/Weather/Weather.cpp +++ b/src/server/game/Weather/Weather.cpp @@ -25,6 +25,7 @@ #include "ScriptMgr.h" #include "Util.h" #include "World.h" +#include "WorldSessionMgr.h" /// Create the Weather object Weather::Weather(uint32 zone, WeatherData const* weatherChances) @@ -203,7 +204,7 @@ bool Weather::UpdateWeather() WorldPackets::Misc::Weather weather(state, m_grade); //- Returns false if there were no players found to update - if (!sWorld->SendZoneMessage(m_zone, weather.Write())) + if (!sWorldSessionMgr->SendZoneMessage(m_zone, weather.Write())) return false; ///- Log the event diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 50e4dbfc3..10f69f30b 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -48,8 +48,6 @@ private: CliCommandHolder& operator=(CliCommandHolder const& right) = delete; }; -typedef std::unordered_map SessionMap; - // ServerMessages.dbc enum ServerMessageType { @@ -531,34 +529,11 @@ class IWorld { public: virtual ~IWorld() = default; - [[nodiscard]] virtual WorldSession* FindSession(uint32 id) const = 0; - [[nodiscard]] virtual WorldSession* FindOfflineSession(uint32 id) const = 0; - [[nodiscard]] virtual WorldSession* FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const = 0; - virtual void AddSession(WorldSession* s) = 0; - virtual bool KickSession(uint32 id) = 0; - virtual void UpdateMaxSessionCounters() = 0; - [[nodiscard]] virtual const SessionMap& GetAllSessions() const = 0; - [[nodiscard]] virtual uint32 GetActiveAndQueuedSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetActiveSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetQueuedSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetMaxQueuedSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetMaxActiveSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetPlayerCount() const = 0; - [[nodiscard]] virtual uint32 GetMaxPlayerCount() const = 0; - virtual void IncreasePlayerCount() = 0; - virtual void DecreasePlayerCount() = 0; - virtual Player* FindPlayerInZone(uint32 zone) = 0; [[nodiscard]] virtual bool IsClosed() const = 0; virtual void SetClosed(bool val) = 0; [[nodiscard]] virtual AccountTypes GetPlayerSecurityLimit() const = 0; virtual void SetPlayerSecurityLimit(AccountTypes sec) = 0; virtual void LoadDBAllowedSecurityLevel() = 0; - virtual void SetPlayerAmountLimit(uint32 limit) = 0; - [[nodiscard]] virtual uint32 GetPlayerAmountLimit() const = 0; - virtual void AddQueuedPlayer(WorldSession*) = 0; - virtual bool RemoveQueuedPlayer(WorldSession* session) = 0; - virtual int32 GetQueuePos(WorldSession*) = 0; - virtual bool HasRecentlyDisconnected(WorldSession*) = 0; [[nodiscard]] virtual bool getAllowMovement() const = 0; virtual void SetAllowMovement(bool allow) = 0; virtual void SetNewCharString(std::string const& str) = 0; @@ -571,18 +546,12 @@ public: [[nodiscard]] virtual uint16 GetConfigMaxSkillValue() const = 0; virtual void SetInitialWorldSettings() = 0; virtual void LoadConfigSettings(bool reload = false) = 0; - 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, 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; virtual void ShutdownServ(uint32 time, uint32 options, uint8 exitcode, const std::string& reason = std::string()) = 0; virtual void ShutdownCancel() = 0; virtual void ShutdownMsg(bool show = false, Player* player = nullptr, const std::string& reason = std::string()) = 0; virtual void Update(uint32 diff) = 0; - virtual void UpdateSessions(uint32 diff) = 0; virtual void setRate(Rates rate, float value) = 0; [[nodiscard]] virtual float getRate(Rates rate) const = 0; virtual void setBoolConfig(WorldBoolConfigs index, bool value) = 0; @@ -596,8 +565,6 @@ public: virtual void LoadWorldStates() = 0; [[nodiscard]] virtual bool IsPvPRealm() const = 0; [[nodiscard]] virtual bool IsFFAPvPRealm() const = 0; - virtual void KickAll() = 0; - virtual void KickAllLess(AccountTypes sec) = 0; virtual uint32 GetNextWhoListUpdateDelaySecs() = 0; virtual void ProcessCliCommands() = 0; virtual void QueueCliCommand(CliCommandHolder* commandHolder) = 0; @@ -613,7 +580,6 @@ public: [[nodiscard]] virtual std::string const& GetRealmName() const = 0; virtual void SetRealmName(std::string name) = 0; virtual void RemoveOldCorpses() = 0; - virtual void DoForAllOnlinePlayers(std::function exec) = 0; }; #endif //AZEROTHCORE_IWORLD_H diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 76c2075b4..c4282b112 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -92,6 +92,7 @@ #include "WhoListCacheMgr.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include "WorldState.h" #include #include @@ -109,15 +110,10 @@ Realm realm; /// World constructor World::World() { - _playerLimit = 0; _allowedSecurityLevel = SEC_PLAYER; _allowMovement = true; _shutdownMask = 0; _shutdownTimer = 0; - _maxActiveSessionCount = 0; - _maxQueuedSessionCount = 0; - _playerCount = 0; - _maxPlayerCount = 0; _nextDailyQuestReset = 0s; _nextWeeklyQuestReset = 0s; _nextMonthlyQuestReset = 0s; @@ -138,28 +134,12 @@ World::World() /// World destructor World::~World() { - ///- Empty the kicked session set - while (!_sessions.empty()) - { - // not remove from queue, prevent loading new sessions - delete _sessions.begin()->second; - _sessions.erase(_sessions.begin()); - } - - while (!_offlineSessions.empty()) - { - delete _offlineSessions.begin()->second; - _offlineSessions.erase(_offlineSessions.begin()); - } - CliCommandHolder* command = nullptr; while (_cliCmdQueue.next(command)) delete command; VMAP::VMapFactory::clear(); MMAP::MMapFactory::clear(); - - //TODO free addSessQueue } std::unique_ptr& getWorldInstance() @@ -168,26 +148,6 @@ std::unique_ptr& getWorldInstance() return instance; } -/// Find a player in a specified zone -Player* World::FindPlayerInZone(uint32 zone) -{ - ///- circle through active sessions and return the first player found in the zone - SessionMap::const_iterator itr; - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) - { - if (!itr->second) - continue; - - Player* player = itr->second->GetPlayer(); - if (!player) - continue; - - if (player->IsInWorld() && player->GetZoneId() == zone) - return player; - } - return nullptr; -} - bool World::IsClosed() const { return _isClosed; @@ -201,211 +161,6 @@ void World::SetClosed(bool val) sScriptMgr->OnOpenStateChange(!val); } -/// Find a session by its id -WorldSession* World::FindSession(uint32 id) const -{ - SessionMap::const_iterator itr = _sessions.find(id); - - if (itr != _sessions.end()) - return itr->second; // also can return nullptr for kicked session - else - return nullptr; -} - -WorldSession* World::FindOfflineSession(uint32 id) const -{ - SessionMap::const_iterator itr = _offlineSessions.find(id); - if (itr != _offlineSessions.end()) - return itr->second; - else - return nullptr; -} - -WorldSession* World::FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const -{ - if (_offlineSessions.empty()) - return nullptr; - - for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _offlineSessions.end(); ++itr) - if (itr->second->GetGuidLow() == guidLow) - return itr->second; - - return nullptr; -} - -/// Remove a given session -bool World::KickSession(uint32 id) -{ - ///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation - SessionMap::const_iterator itr = _sessions.find(id); - - if (itr != _sessions.end() && itr->second) - { - if (itr->second->PlayerLoading()) - return false; - - itr->second->KickPlayer("KickSession", false); - } - - return true; -} - -void World::AddSession(WorldSession* s) -{ - _addSessQueue.add(s); -} - -void World::AddSession_(WorldSession* s) -{ - ASSERT (s); - - // kick existing session with same account (if any) - // if character on old session is being loaded, then return - if (!KickSession(s->GetAccountId())) - { - s->KickPlayer("kick existing session with same account"); - delete s; // session not added yet in session list, so not listed in queue - return; - } - - SessionMap::const_iterator old = _sessions.find(s->GetAccountId()); - if (old != _sessions.end()) - { - WorldSession* oldSession = old->second; - - if (!RemoveQueuedPlayer(oldSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) - _disconnects[s->GetAccountId()] = GameTime::GetGameTime().count(); - - // pussywizard: - if (oldSession->HandleSocketClosed()) - { - // there should be no offline session if current one is logged onto a character - SessionMap::iterator iter; - if ((iter = _offlineSessions.find(oldSession->GetAccountId())) != _offlineSessions.end()) - { - WorldSession* tmp = iter->second; - _offlineSessions.erase(iter); - delete tmp; - } - oldSession->SetOfflineTime(GameTime::GetGameTime().count()); - _offlineSessions[oldSession->GetAccountId()] = oldSession; - } - else - { - delete oldSession; - } - } - - _sessions[s->GetAccountId()] = s; - - uint32 Sessions = GetActiveAndQueuedSessionCount(); - uint32 pLimit = GetPlayerAmountLimit(); - - // don't count this session when checking player limit - --Sessions; - - if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(s->GetSecurity()) && !s->CanSkipQueue() && !HasRecentlyDisconnected(s)) - { - AddQueuedPlayer(s); - UpdateMaxSessionCounters(); - return; - } - - s->InitializeSession(); - - UpdateMaxSessionCounters(); -} - -bool World::HasRecentlyDisconnected(WorldSession* session) -{ - if (!session) - return false; - - if (uint32 tolerance = getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) - { - for (DisconnectMap::iterator i = _disconnects.begin(); i != _disconnects.end();) - { - if ((GameTime::GetGameTime().count() - i->second) < tolerance) - { - if (i->first == session->GetAccountId()) - return true; - ++i; - } - else - _disconnects.erase(i++); - } - } - return false; -} - -int32 World::GetQueuePos(WorldSession* sess) -{ - uint32 position = 1; - - for (Queue::const_iterator iter = _queuedPlayer.begin(); iter != _queuedPlayer.end(); ++iter, ++position) - if ((*iter) == sess) - return position; - - return 0; -} - -void World::AddQueuedPlayer(WorldSession* sess) -{ - sess->SetInQueue(true); - _queuedPlayer.push_back(sess); - - // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. - sess->SendAuthResponse(AUTH_WAIT_QUEUE, false, GetQueuePos(sess)); -} - -bool World::RemoveQueuedPlayer(WorldSession* sess) -{ - uint32 sessions = GetActiveSessionCount(); - - uint32 position = 1; - Queue::iterator iter = _queuedPlayer.begin(); - - // search to remove and count skipped positions - bool found = false; - - for (; iter != _queuedPlayer.end(); ++iter, ++position) - { - if (*iter == sess) - { - sess->SetInQueue(false); - sess->ResetTimeOutTime(false); - iter = _queuedPlayer.erase(iter); - found = true; - break; - } - } - - // if session not queued then it was an active session - if (!found) - { - ASSERT(sessions > 0); - --sessions; - } - - // accept first in queue - if ((!GetPlayerAmountLimit() || sessions < GetPlayerAmountLimit()) && !_queuedPlayer.empty()) - { - WorldSession* pop_sess = _queuedPlayer.front(); - pop_sess->InitializeSession(); - _queuedPlayer.pop_front(); - - // update iter to point first queued socket or end() if queue is empty now - iter = _queuedPlayer.begin(); - position = 1; - } - - // update queue position from iter to end() - for (; iter != _queuedPlayer.end(); ++iter, ++position) - (*iter)->SendAuthWaitQueue(position); - - return found; -} - /// Initialize config values void World::LoadConfigSettings(bool reload) { @@ -431,9 +186,7 @@ void World::LoadConfigSettings(bool reload) ///- Read the player limit and the Message of the day from the config file if (!reload) - { - SetPlayerAmountLimit(sConfigMgr->GetOption("PlayerLimit", 1000)); - } + sWorldSessionMgr->SetPlayerAmountLimit(sConfigMgr->GetOption("PlayerLimit", 1000)); ///- Read ticket system setting from the config file _bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetOption("AllowTickets", true); @@ -2293,9 +2046,9 @@ void World::Update(uint32 diff) sWorldUpdateTime.UpdateWithDiff(diff); // Record update if recording set in log and diff is greater then minimum set in log - sWorldUpdateTime.RecordUpdateTime(GameTime::GetGameTimeMS(), diff, GetActiveSessionCount()); + sWorldUpdateTime.RecordUpdateTime(GameTime::GetGameTimeMS(), diff, sWorldSessionMgr->GetActiveSessionCount()); - DynamicVisibilityMgr::Update(GetActiveSessionCount()); + DynamicVisibilityMgr::Update(sWorldSessionMgr->GetActiveSessionCount()); ///- Update the different timers for (int i = 0; i < WUPDATE_COUNT; ++i) @@ -2376,8 +2129,10 @@ void World::Update(uint32 diff) _mail_expire_check_timer = currentGameTime + 6h; } - METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions")); - UpdateSessions(diff); + { + METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions")); + sWorldSessionMgr->UpdateSessions(diff); + } ///
  • Handle weather updates when the timer has passed if (_timers[WUPDATE_WEATHERS].Passed()) @@ -2463,7 +2218,7 @@ void World::Update(uint32 diff) LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_UPTIME_PLAYERS); stmt->SetData(0, uint32(GameTime::GetUptime().count())); - stmt->SetData(1, uint16(GetMaxPlayerCount())); + stmt->SetData(1, uint16(sWorldSessionMgr->GetMaxPlayerCount())); stmt->SetData(2, realm.Id.Realm); stmt->SetData(3, uint32(GameTime::GetStartTime().count())); LoginDatabase.Execute(stmt); @@ -2535,41 +2290,6 @@ void World::ForceGameEventUpdate() _timers[WUPDATE_EVENTS].Reset(); } -/// Send a packet to all players (except self if mentioned) -void World::SendGlobalMessage(WorldPacket const* packet, WorldSession* self, TeamId teamId) -{ - SessionMap::const_iterator itr; - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) - { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - itr->second != self && - (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) - { - itr->second->SendPacket(packet); - } - } -} - -/// Send a packet to all GMs (except self if mentioned) -void World::SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self, TeamId teamId) -{ - SessionMap::iterator itr; - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) - { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - itr->second != self && - !AccountMgr::IsPlayerAccount(itr->second->GetSecurity()) && - (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) - { - itr->second->SendPacket(packet); - } - } -} - namespace Acore { class WorldWorldTextBuilder @@ -2615,60 +2335,6 @@ namespace Acore }; } // namespace Acore -/// Send a packet to all players (or players selected team) in the zone (except self if mentioned) -bool World::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self, TeamId teamId) -{ - bool foundPlayerToSend = false; - SessionMap::const_iterator itr; - - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) - { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - itr->second->GetPlayer()->GetZoneId() == zone && - itr->second != self && - (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) - { - itr->second->SendPacket(packet); - foundPlayerToSend = true; - } - } - - return foundPlayerToSend; -} - -/// Send a System Message to all players in the zone (except self if mentioned) -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.c_str()); - SendZoneMessage(zone, &data, self, teamId); -} - -/// Kick (and save) all players -void World::KickAll() -{ - _queuedPlayer.clear(); // prevent send queue update packet and login queued sessions - - // session not removed at kick and will removed in next update tick - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) - itr->second->KickPlayer("KickAll sessions"); - - // pussywizard: kick offline sessions - for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _offlineSessions.end(); ++itr) - itr->second->KickPlayer("KickAll offline sessions"); -} - -/// Kick (and save) all players with security level less `sec` -void World::KickAllLess(AccountTypes sec) -{ - // session not removed at kick and will removed in next update tick - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) - if (itr->second->GetSecurity() < sec) - itr->second->KickPlayer("KickAllLess"); -} - /// Update the game time void World::_UpdateGameTime() { @@ -2684,7 +2350,7 @@ void World::_UpdateGameTime() ///- ... and it is overdue, stop the world (set m_stopEvent) if (_shutdownTimer <= elapsed.count()) { - if (!(_shutdownMask & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount() == 0) + if (!(_shutdownMask & SHUTDOWN_MASK_IDLE) || sWorldSessionMgr->GetActiveAndQueuedSessionCount() == 0) _stopEvent = true; // exist code already set else _shutdownTimer = 1; // minimum timer value to wait idle state @@ -2715,7 +2381,7 @@ void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode, std::strin ///- If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions) if (time == 0) { - if (!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount() == 0) + if (!(options & SHUTDOWN_MASK_IDLE) || sWorldSessionMgr->GetActiveAndQueuedSessionCount() == 0) _stopEvent = true; // exist code already set else _shutdownTimer = 1; //So that the session count is re-evaluated at next world tick @@ -2767,7 +2433,7 @@ void World::ShutdownMsg(bool show, Player* player, std::string const& reason) str += " - " + _shutdownReason; ServerMessageType msgid = (_shutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_TIME : SERVER_MSG_SHUTDOWN_TIME; - SendServerMessage(msgid, str, player); + sWorldSessionMgr->SendServerMessage(msgid, str, player); LOG_WARN("server.worldserver", "Server {} in {}", (_shutdownMask & SHUTDOWN_MASK_RESTART ? "restarting" : "shutdown"), str); } } @@ -2784,100 +2450,13 @@ void World::ShutdownCancel() _shutdownMask = 0; _shutdownTimer = 0; _exitCode = SHUTDOWN_EXIT_CODE; // to default value - SendServerMessage(msgid); + sWorldSessionMgr->SendServerMessage(msgid); LOG_DEBUG("server.worldserver", "Server {} cancelled.", (_shutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown")); sScriptMgr->OnShutdownCancel(); } -/// Send a server message to the user(s) -void World::SendServerMessage(ServerMessageType messageID, std::string stringParam /*= ""*/, Player* player /*= nullptr*/) -{ - WorldPackets::Chat::ChatServerMessage chatServerMessage; - chatServerMessage.MessageID = int32(messageID); - if (messageID <= SERVER_MSG_STRING) - chatServerMessage.StringParam = stringParam; - - if (player) - player->SendDirectMessage(chatServerMessage.Write()); - else - SendGlobalMessage(chatServerMessage.Write()); -} - -void World::UpdateSessions(uint32 diff) -{ - { - METRIC_DETAILED_NO_THRESHOLD_TIMER("world_update_time", - METRIC_TAG("type", "Add sessions"), - METRIC_TAG("parent_type", "Update sessions")); - - ///- Add new sessions - WorldSession* sess = nullptr; - while (_addSessQueue.next(sess)) - { - AddSession_(sess); - } - } - - ///- Then send an update signal to remaining ones - for (SessionMap::iterator itr = _sessions.begin(), next; itr != _sessions.end(); itr = next) - { - next = itr; - ++next; - - ///- and remove not active sessions from the list - WorldSession* pSession = itr->second; - WorldSessionFilter updater(pSession); - - // pussywizard: - if (pSession->HandleSocketClosed()) - { - if (!RemoveQueuedPlayer(pSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) - _disconnects[pSession->GetAccountId()] = GameTime::GetGameTime().count(); - _sessions.erase(itr); - // there should be no offline session if current one is logged onto a character - SessionMap::iterator iter; - if ((iter = _offlineSessions.find(pSession->GetAccountId())) != _offlineSessions.end()) - { - WorldSession* tmp = iter->second; - _offlineSessions.erase(iter); - delete tmp; - } - pSession->SetOfflineTime(GameTime::GetGameTime().count()); - _offlineSessions[pSession->GetAccountId()] = pSession; - continue; - } - - [[maybe_unused]] uint32 currentSessionId = itr->first; - METRIC_DETAILED_TIMER("world_update_sessions_time", METRIC_TAG("account_id", std::to_string(currentSessionId))); - - if (!pSession->Update(diff, updater)) - { - if (!RemoveQueuedPlayer(pSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) - _disconnects[pSession->GetAccountId()] = GameTime::GetGameTime().count(); - _sessions.erase(itr); - delete pSession; - } - } - - // pussywizard: - if (_offlineSessions.empty()) - return; - uint32 currTime = GameTime::GetGameTime().count(); - for (SessionMap::iterator itr = _offlineSessions.begin(), next; itr != _offlineSessions.end(); itr = next) - { - next = itr; - ++next; - WorldSession* pSession = itr->second; - if (!pSession->GetPlayer() || pSession->GetOfflineTime() + 60 < currTime || pSession->IsKicked()) - { - _offlineSessions.erase(itr); - delete pSession; - } - } -} - // This handles the issued and queued CLI commands void World::ProcessCliCommands() { @@ -2995,7 +2574,8 @@ void World::ResetDailyQuests() CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_DAILY); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->ResetDailyQuestStatus(); @@ -3022,7 +2602,7 @@ void World::SetPlayerSecurityLimit(AccountTypes _sec) bool update = sec > _allowedSecurityLevel; _allowedSecurityLevel = sec; if (update) - KickAllLess(_allowedSecurityLevel); + sWorldSessionMgr->KickAllLess(_allowedSecurityLevel); } void World::ResetWeeklyQuests() @@ -3030,7 +2610,8 @@ void World::ResetWeeklyQuests() CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_WEEKLY); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->ResetWeeklyQuestStatus(); @@ -3048,7 +2629,8 @@ void World::ResetMonthlyQuests() CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_MONTHLY); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->ResetMonthlyQuestStatus(); @@ -3062,7 +2644,8 @@ void World::ResetEventSeasonalQuests(uint16 event_id) stmt->SetData(0, event_id); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->ResetSeasonalQuestStatus(event_id); } @@ -3074,7 +2657,8 @@ void World::ResetRandomBG() CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->SetRandomWinner(false); @@ -3101,12 +2685,6 @@ void World::ResetGuildCap() sGuildMgr->ResetTimes(); } -void World::UpdateMaxSessionCounters() -{ - _maxActiveSessionCount = std::max(_maxActiveSessionCount, uint32(_sessions.size() - _queuedPlayer.size())); - _maxQueuedSessionCount = std::max(_maxQueuedSessionCount, uint32(_queuedPlayer.size())); -} - void World::LoadDBVersion() { QueryResult result = WorldDatabase.Query("SELECT db_version, cache_id FROM version LIMIT 1"); @@ -3126,8 +2704,8 @@ void World::LoadDBVersion() void World::UpdateAreaDependentAuras() { - SessionMap::const_iterator itr; - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second && itr->second->GetPlayer() && itr->second->GetPlayer()->IsInWorld()) { itr->second->GetPlayer()->UpdateAreaDependentAuras(itr->second->GetPlayer()->GetAreaId()); @@ -3196,23 +2774,6 @@ void World::RemoveOldCorpses() _timers[WUPDATE_CORPSES].SetCurrent(_timers[WUPDATE_CORPSES].GetInterval()); } -void World::DoForAllOnlinePlayers(std::function exec) -{ - std::shared_lock lock(*HashMapHolder::GetLock()); - for (auto const& it : ObjectAccessor::GetPlayers()) - { - if (Player* player = it.second) - { - if (!player->IsInWorld()) - { - continue; - } - - exec(player); - } - } -} - bool World::IsPvPRealm() const { return getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP; diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 75f3bbdac..73ee81c4d 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -155,34 +155,6 @@ public: static uint32 m_worldLoopCounter; - [[nodiscard]] WorldSession* FindSession(uint32 id) const override; - [[nodiscard]] WorldSession* FindOfflineSession(uint32 id) const override; - [[nodiscard]] WorldSession* FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const override; - void AddSession(WorldSession* s) override; - bool KickSession(uint32 id) override; - /// Get the number of current active sessions - void UpdateMaxSessionCounters() override; - [[nodiscard]] const SessionMap& GetAllSessions() const override { return _sessions; } - [[nodiscard]] uint32 GetActiveAndQueuedSessionCount() const override { return _sessions.size(); } - [[nodiscard]] uint32 GetActiveSessionCount() const override { return _sessions.size() - _queuedPlayer.size(); } - [[nodiscard]] uint32 GetQueuedSessionCount() const override { return _queuedPlayer.size(); } - /// Get the maximum number of parallel sessions on the server since last reboot - [[nodiscard]] uint32 GetMaxQueuedSessionCount() const override { return _maxQueuedSessionCount; } - [[nodiscard]] uint32 GetMaxActiveSessionCount() const override { return _maxActiveSessionCount; } - /// Get number of players - [[nodiscard]] inline uint32 GetPlayerCount() const override { return _playerCount; } - [[nodiscard]] inline uint32 GetMaxPlayerCount() const override { return _maxPlayerCount; } - - /// Increase/Decrease number of players - inline void IncreasePlayerCount() override - { - _playerCount++; - _maxPlayerCount = std::max(_maxPlayerCount, _playerCount); - } - inline void DecreasePlayerCount() override { _playerCount--; } - - Player* FindPlayerInZone(uint32 zone) override; - /// Deny clients? [[nodiscard]] bool IsClosed() const override; @@ -194,17 +166,6 @@ public: void SetPlayerSecurityLimit(AccountTypes sec) override; void LoadDBAllowedSecurityLevel() override; - /// Active session server limit - void SetPlayerAmountLimit(uint32 limit) override { _playerLimit = limit; } - [[nodiscard]] uint32 GetPlayerAmountLimit() const override { return _playerLimit; } - - //player Queue - typedef std::list Queue; - void AddQueuedPlayer(WorldSession*) override; - bool RemoveQueuedPlayer(WorldSession* session) override; - int32 GetQueuePos(WorldSession*) override; - bool HasRecentlyDisconnected(WorldSession*) override; - /// \todo Actions on m_allowMovement still to be implemented /// Is movement allowed? [[nodiscard]] bool getAllowMovement() const override { return _allowMovement; } @@ -236,12 +197,6 @@ public: void SetInitialWorldSettings() override; void LoadConfigSettings(bool reload = false) override; - 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, 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? [[nodiscard]] bool IsShuttingDown() const override { return _shutdownTimer > 0; } [[nodiscard]] uint32 GetShutDownTimeLeft() const override { return _shutdownTimer; } @@ -254,7 +209,6 @@ public: void Update(uint32 diff) override; - void UpdateSessions(uint32 diff) override; /// Set a server rate (see #Rates) void setRate(Rates rate, float value) override { _rate_values[rate] = value; } /// Get a server rate (see #Rates) @@ -307,9 +261,6 @@ public: [[nodiscard]] bool IsPvPRealm() const override; [[nodiscard]] bool IsFFAPvPRealm() const override; - void KickAll() override; - void KickAllLess(AccountTypes sec) override; - // for max speed access static float GetMaxVisibleDistanceOnContinents() { return _maxVisibleDistanceOnContinents; } static float GetMaxVisibleDistanceInInstances() { return _maxVisibleDistanceInInstances; } @@ -342,8 +293,6 @@ public: void RemoveOldCorpses() override; - void DoForAllOnlinePlayers(std::function exec) override; - protected: void _UpdateGameTime(); // callback for UpdateRealmCharacters @@ -375,15 +324,6 @@ private: IntervalTimer _timers[WUPDATE_COUNT]; Seconds _mail_expire_check_timer; - SessionMap _sessions; - SessionMap _offlineSessions; - typedef std::unordered_map DisconnectMap; - DisconnectMap _disconnects; - uint32 _maxActiveSessionCount; - uint32 _maxQueuedSessionCount; - uint32 _playerCount; - uint32 _maxPlayerCount; - std::string _newCharString; float _rate_values[MAX_RATES]; @@ -392,7 +332,6 @@ private: float _float_configs[FLOAT_CONFIG_VALUE_COUNT]; typedef std::map WorldStatesMap; WorldStatesMap _worldstates; - uint32 _playerLimit; AccountTypes _allowedSecurityLevel; LocaleConstant _defaultDbcLocale; // from config for one from loaded DBC locales uint32 _availableDbcLocaleMask; // by loaded DBC @@ -418,13 +357,6 @@ private: Seconds _nextCalendarOldEventsDeletionTime; Seconds _nextGuildReset; - //Player Queue - Queue _queuedPlayer; - - // sessions that are added async - void AddSession_(WorldSession* s); - LockedQueue _addSessQueue; - // used versions std::string _dbVersion; diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index 717e94ef7..1667034ec 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -32,6 +32,7 @@ EndScriptData */ #include "Player.h" #include "World.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" using namespace Acore::ChatCommands; @@ -87,7 +88,7 @@ public: if (message.empty()) return false; - sWorld->SendServerMessage(SERVER_MSG_STRING, Acore::StringFormat(handler->GetAcoreString(LANG_SYSTEMMESSAGE), message.data())); + sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, Acore::StringFormat(handler->GetAcoreString(LANG_SYSTEMMESSAGE), message.data())); return true; } @@ -112,7 +113,7 @@ public: WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1)); data << str; - sWorld->SendGlobalMessage(&data); + sWorldSessionMgr->SendGlobalMessage(&data); return true; } @@ -128,7 +129,7 @@ public: WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1)); data << str; - sWorld->SendGlobalGMMessage(&data); + sWorldSessionMgr->SendGlobalGMMessage(&data); return true; } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index ce10a094b..cbfc4517c 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -45,6 +45,7 @@ #include "TargetedMovementGenerator.h" #include "Tokenize.h" #include "WeatherMgr.h" +#include "WorldSessionMgr.h" /// @todo: this import is not necessary for compilation and marked as unused by the IDE // however, for some reasons removing it would cause a damn linking issue @@ -2451,7 +2452,7 @@ public: // find only player from same account if any if (!target) - if (WorldSession* session = sWorld->FindSession(accountId)) + if (WorldSession* session = sWorldSessionMgr->FindSession(accountId)) { target = session->GetPlayer(); } @@ -2557,7 +2558,7 @@ public: // find only player from same account if any if (!playerTarget) { - if (WorldSession* session = sWorld->FindSession(accountId)) + if (WorldSession* session = sWorldSessionMgr->FindSession(accountId)) { playerTarget = session->GetPlayer(); } @@ -2946,7 +2947,7 @@ public: return false; } - sWorld->SendGlobalMessage(WorldPackets::Misc::Playsound(soundId).Write()); + sWorldSessionMgr->SendGlobalMessage(WorldPackets::Misc::Playsound(soundId).Write()); handler->PSendSysMessage(LANG_COMMAND_PLAYED_TO_ALL, soundId); return true; diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index e90da5af4..4b6328cb3 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -29,6 +29,7 @@ EndScriptData */ #include "Pet.h" #include "Player.h" #include "ScriptMgr.h" +#include "WorldSessionMgr.h" using namespace Acore::ChatCommands; @@ -302,7 +303,7 @@ public: stmt->SetData(0, uint16(atLogin)); CharacterDatabase.Execute(stmt); - sWorld->DoForAllOnlinePlayers([&] (Player* player){ + sWorldSessionMgr->DoForAllOnlinePlayers([&] (Player* player){ player->SetAtLoginFlag(atLogin); }); diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index a789420a4..088993244 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -36,6 +36,7 @@ #include "UpdateTime.h" #include "VMapFactory.h" #include "VMapMgr2.h" +#include "WorldSessionMgr.h" #include #include #include @@ -259,10 +260,10 @@ public: static bool HandleServerInfoCommand(ChatHandler* handler) { std::string realmName = sWorld->GetRealmName(); - uint32 playerCount = sWorld->GetPlayerCount(); - uint32 activeSessionCount = sWorld->GetActiveSessionCount(); - uint32 queuedSessionCount = sWorld->GetQueuedSessionCount(); - uint32 connPeak = sWorld->GetMaxActiveSessionCount(); + uint32 playerCount = sWorldSessionMgr->GetPlayerCount(); + uint32 activeSessionCount = sWorldSessionMgr->GetActiveSessionCount(); + uint32 queuedSessionCount = sWorldSessionMgr->GetQueuedSessionCount(); + uint32 connPeak = sWorldSessionMgr->GetMaxActiveSessionCount(); handler->PSendSysMessage("{}", GitRevision::GetFullVersion()); if (!queuedSessionCount) diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp index 474f7306a..33a1e63ee 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp @@ -27,6 +27,7 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OPvPCapturePointEP_EWT::OPvPCapturePointEP_EWT(OutdoorPvP* pvp) : OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_UnitsSummonedSideId(TEAM_NEUTRAL) @@ -40,12 +41,12 @@ void OPvPCapturePointEP_EWT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_NEUTRAL); } @@ -58,14 +59,14 @@ void OPvPCapturePointEP_EWT::ChangeState() artkit = 2; SummonSupportUnitAtNorthpassTower(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_ALLIANCE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; SummonSupportUnitAtNorthpassTower(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_HORDE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -172,12 +173,12 @@ void OPvPCapturePointEP_NPT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_NEUTRAL); } @@ -190,14 +191,14 @@ void OPvPCapturePointEP_NPT::ChangeState() artkit = 2; SummonGO(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_ALLIANCE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; SummonGO(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_HORDE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -314,12 +315,12 @@ void OPvPCapturePointEP_CGT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_NEUTRAL); } @@ -332,14 +333,14 @@ void OPvPCapturePointEP_CGT::ChangeState() artkit = 2; LinkGraveyard(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_ALLIANCE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; LinkGraveyard(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_HORDE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -441,12 +442,12 @@ void OPvPCapturePointEP_PWT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_NEUTRAL); } @@ -459,14 +460,14 @@ void OPvPCapturePointEP_PWT::ChangeState() SummonFlightMaster(TEAM_ALLIANCE); artkit = 2; ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_ALLIANCE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; SummonFlightMaster(TEAM_HORDE); artkit = 1; ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_HORDE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp index efb85af37..b26af4d6f 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp @@ -25,6 +25,7 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" const uint32 HP_LANG_LOSE_A[HP_TOWER_NUM] = {LANG_OPVP_HP_LOSE_BROKENHILL_A, LANG_OPVP_HP_LOSE_OVERLOOK_A, LANG_OPVP_HP_LOSE_STADIUM_A}; @@ -180,13 +181,13 @@ void OPvPCapturePointHP::ChangeState() field = HP_MAP_A[m_TowerType]; if (uint32 alliance_towers = ((OutdoorPvPHP*)_pvp)->GetAllianceTowersControlled()) ((OutdoorPvPHP*)_pvp)->SetAllianceTowersControlled(--alliance_towers); - sWorld->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_LOSE_A[m_TowerType])); + sWorldSessionMgr->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_LOSE_A[m_TowerType])); break; case OBJECTIVESTATE_HORDE: field = HP_MAP_H[m_TowerType]; if (uint32 horde_towers = ((OutdoorPvPHP*)_pvp)->GetHordeTowersControlled()) ((OutdoorPvPHP*)_pvp)->SetHordeTowersControlled(--horde_towers); - sWorld->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_LOSE_H[m_TowerType])); + sWorldSessionMgr->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_LOSE_H[m_TowerType])); break; case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: field = HP_MAP_N[m_TowerType]; @@ -223,7 +224,7 @@ void OPvPCapturePointHP::ChangeState() uint32 alliance_towers = ((OutdoorPvPHP*)_pvp)->GetAllianceTowersControlled(); if (alliance_towers < 3) ((OutdoorPvPHP*)_pvp)->SetAllianceTowersControlled(++alliance_towers); - sWorld->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_CAPTURE_A[m_TowerType])); + sWorldSessionMgr->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_CAPTURE_A[m_TowerType])); break; } case OBJECTIVESTATE_HORDE: @@ -234,7 +235,7 @@ void OPvPCapturePointHP::ChangeState() uint32 horde_towers = ((OutdoorPvPHP*)_pvp)->GetHordeTowersControlled(); if (horde_towers < 3) ((OutdoorPvPHP*)_pvp)->SetHordeTowersControlled(++horde_towers); - sWorld->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_CAPTURE_H[m_TowerType])); + sWorldSessionMgr->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_CAPTURE_H[m_TowerType])); break; } case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp index 23036977c..d59e2fb17 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp @@ -28,6 +28,7 @@ #include "ScriptedCreature.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OutdoorPvPNA::OutdoorPvPNA() { @@ -193,9 +194,9 @@ void OPvPCapturePointNA::FactionTakeOver(TeamId teamId) if (m_ControllingFaction != TEAM_NEUTRAL) sGraveyard->RemoveGraveyardLink(NA_HALAA_GRAVEYARD, NA_HALAA_GRAVEYARD_ZONE, m_ControllingFaction, false); if (m_ControllingFaction == TEAM_ALLIANCE) - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_LOSE_A)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_LOSE_A)); else if (m_ControllingFaction == TEAM_HORDE) - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_LOSE_H)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_LOSE_H)); DespawnCreatures(GetControllingFaction() == TEAM_HORDE ? halaaNPCHorde : halaaNPCAlly); m_ControllingFaction = teamId; if (m_ControllingFaction != TEAM_NEUTRAL) @@ -217,7 +218,7 @@ void OPvPCapturePointNA::FactionTakeOver(TeamId teamId) _pvp->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW, 0); _pvp->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW, 1); _pvp->SendUpdateWorldState(NA_UI_GUARDS_LEFT, m_GuardsAlive); - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_CAPTURE_A)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_CAPTURE_A)); } else { @@ -229,7 +230,7 @@ void OPvPCapturePointNA::FactionTakeOver(TeamId teamId) _pvp->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW, 1); _pvp->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW, 0); _pvp->SendUpdateWorldState(NA_UI_GUARDS_LEFT, m_GuardsAlive); - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_CAPTURE_H)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_CAPTURE_H)); } UpdateWyvernRoostWorldState(NA_ROOST_S); UpdateWyvernRoostWorldState(NA_ROOST_N); @@ -641,7 +642,7 @@ bool OPvPCapturePointNA::Update(uint32 diff) { m_capturable = true; m_RespawnTimer = NA_RESPAWN_TIME; - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_DEFENSELESS)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_DEFENSELESS)); } else m_capturable = false; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp index 357f810ea..bde78c3aa 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp @@ -28,6 +28,7 @@ #include "Transport.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OutdoorPvPSI::OutdoorPvPSI() { @@ -102,7 +103,7 @@ bool OutdoorPvPSI::HandleAreaTrigger(Player* player, uint32 trigger) if (m_Gathered_A >= SI_MAX_RESOURCES) { TeamApplyBuff(TEAM_ALLIANCE, SI_CENARION_FAVOR, 0, player); - sWorld->SendZoneText(OutdoorPvPSIBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_SI_CAPTURE_A)); + sWorldSessionMgr->SendZoneText(OutdoorPvPSIBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_SI_CAPTURE_A)); m_LastController = TEAM_ALLIANCE; m_Gathered_A = 0; m_Gathered_H = 0; @@ -128,7 +129,7 @@ bool OutdoorPvPSI::HandleAreaTrigger(Player* player, uint32 trigger) if (m_Gathered_H >= SI_MAX_RESOURCES) { TeamApplyBuff(TEAM_HORDE, SI_CENARION_FAVOR, 0, player); - sWorld->SendZoneText(OutdoorPvPSIBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_SI_CAPTURE_H)); + sWorldSessionMgr->SendZoneText(OutdoorPvPSIBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_SI_CAPTURE_H)); m_LastController = TEAM_HORDE; m_Gathered_A = 0; m_Gathered_H = 0; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp index 075ef17d8..d312b6abc 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp @@ -26,6 +26,7 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OutdoorPvPTF::OutdoorPvPTF() { @@ -397,14 +398,14 @@ void OPvPCapturePointTF::ChangeState() { if (uint32 alliance_towers = ((OutdoorPvPTF*)_pvp)->GetAllianceTowersControlled()) ((OutdoorPvPTF*)_pvp)->SetAllianceTowersControlled(--alliance_towers); - sWorld->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_LOSE_A)); + sWorldSessionMgr->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_LOSE_A)); } // if changing from controlling horde to alliance else if (_oldState == OBJECTIVESTATE_HORDE) { if (uint32 horde_towers = ((OutdoorPvPTF*)_pvp)->GetHordeTowersControlled()) ((OutdoorPvPTF*)_pvp)->SetHordeTowersControlled(--horde_towers); - sWorld->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_LOSE_H)); + sWorldSessionMgr->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_LOSE_H)); } uint32 artkit = 21; @@ -419,7 +420,7 @@ void OPvPCapturePointTF::ChangeState() if (alliance_towers < TF_TOWER_NUM) ((OutdoorPvPTF*)_pvp)->SetAllianceTowersControlled(++alliance_towers); - sWorld->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_CAPTURE_A)); + sWorldSessionMgr->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_CAPTURE_A)); for (PlayerSet::iterator itr = _activePlayers[0].begin(); itr != _activePlayers[0].end(); ++itr) if (Player* player = ObjectAccessor::FindPlayer(*itr)) @@ -434,7 +435,7 @@ void OPvPCapturePointTF::ChangeState() if (horde_towers < TF_TOWER_NUM) ((OutdoorPvPTF*)_pvp)->SetHordeTowersControlled(++horde_towers); - sWorld->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_CAPTURE_H)); + sWorldSessionMgr->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_CAPTURE_H)); for (PlayerSet::iterator itr = _activePlayers[1].begin(); itr != _activePlayers[1].end(); ++itr) if (Player* player = ObjectAccessor::FindPlayer(*itr)) diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp index 3ecf6d9e7..b681c1604 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp @@ -25,6 +25,7 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OPvPCapturePointZM_Beacon::OPvPCapturePointZM_Beacon(OutdoorPvP* pvp, ZM_BeaconType type) : OPvPCapturePoint(pvp), m_TowerType(type), m_TowerState(ZM_TOWERSTATE_N) @@ -78,14 +79,14 @@ void OPvPCapturePointZM_Beacon::ChangeState() { if (uint32 alliance_towers = ((OutdoorPvPZM*)_pvp)->GetAllianceTowersControlled()) ((OutdoorPvPZM*)_pvp)->SetAllianceTowersControlled(--alliance_towers); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconLoseA[m_TowerType])); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconLoseA[m_TowerType])); } // if changing from controlling horde to alliance else if (_oldState == OBJECTIVESTATE_HORDE) { if (uint32 horde_towers = ((OutdoorPvPZM*)_pvp)->GetHordeTowersControlled()) ((OutdoorPvPZM*)_pvp)->SetHordeTowersControlled(--horde_towers); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconLoseH[m_TowerType])); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconLoseH[m_TowerType])); } switch (_state) @@ -96,7 +97,7 @@ void OPvPCapturePointZM_Beacon::ChangeState() uint32 alliance_towers = ((OutdoorPvPZM*)_pvp)->GetAllianceTowersControlled(); if (alliance_towers < ZM_NUM_BEACONS) ((OutdoorPvPZM*)_pvp)->SetAllianceTowersControlled(++alliance_towers); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconCaptureA[m_TowerType])); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconCaptureA[m_TowerType])); break; } case OBJECTIVESTATE_HORDE: @@ -105,7 +106,7 @@ void OPvPCapturePointZM_Beacon::ChangeState() uint32 horde_towers = ((OutdoorPvPZM*)_pvp)->GetHordeTowersControlled(); if (horde_towers < ZM_NUM_BEACONS) ((OutdoorPvPZM*)_pvp)->SetHordeTowersControlled(++horde_towers); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconCaptureH[m_TowerType])); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconCaptureH[m_TowerType])); break; } case OBJECTIVESTATE_NEUTRAL: @@ -223,7 +224,7 @@ int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) if (player->HasAura(ZM_BATTLE_STANDARD_A) && m_GraveYardState != ZM_GRAVEYARD_A) { if (m_GraveYardState == ZM_GRAVEYARD_H) - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_H)); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_H)); m_GraveYardState = ZM_GRAVEYARD_A; DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant AddObject(0, ZM_Banner_A.entry, ZM_Banner_A.map, ZM_Banner_A.x, ZM_Banner_A.y, ZM_Banner_A.z, ZM_Banner_A.o, ZM_Banner_A.rot0, ZM_Banner_A.rot1, ZM_Banner_A.rot2, ZM_Banner_A.rot3); @@ -231,12 +232,12 @@ int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) sGraveyard->AddGraveyardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, TEAM_ALLIANCE, false); // add gy _pvp->TeamApplyBuff(TEAM_ALLIANCE, ZM_CAPTURE_BUFF, 0, player); player->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_A)); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_A)); } else if (player->HasAura(ZM_BATTLE_STANDARD_H) && m_GraveYardState != ZM_GRAVEYARD_H) { if (m_GraveYardState == ZM_GRAVEYARD_A) - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_A)); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_A)); m_GraveYardState = ZM_GRAVEYARD_H; DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant AddObject(0, ZM_Banner_H.entry, ZM_Banner_H.map, ZM_Banner_H.x, ZM_Banner_H.y, ZM_Banner_H.z, ZM_Banner_H.o, ZM_Banner_H.rot0, ZM_Banner_H.rot1, ZM_Banner_H.rot2, ZM_Banner_H.rot3); @@ -244,7 +245,7 @@ int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) sGraveyard->AddGraveyardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, TEAM_HORDE, false); // add gy _pvp->TeamApplyBuff(TEAM_HORDE, ZM_CAPTURE_BUFF, 0, player); player->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_H); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_H)); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_H)); } UpdateTowerState(); } diff --git a/src/test/mocks/WorldMock.h b/src/test/mocks/WorldMock.h index 11823fcf3..fc095b4a6 100644 --- a/src/test/mocks/WorldMock.h +++ b/src/test/mocks/WorldMock.h @@ -32,34 +32,11 @@ class WorldMock: public IWorld { public: ~WorldMock() override { } - MOCK_METHOD(WorldSession*, FindSession, (uint32 id), (const)); - MOCK_METHOD(WorldSession*, FindOfflineSession, (uint32 id), (const)); - MOCK_METHOD(WorldSession*, FindOfflineSessionForCharacterGUID, (ObjectGuid::LowType guidLow),(const)); - MOCK_METHOD(void, AddSession, (WorldSession* s), ()); - MOCK_METHOD(bool, KickSession, (uint32 id), ()); - MOCK_METHOD(void, UpdateMaxSessionCounters, ()); - MOCK_METHOD(const SessionMap&, GetAllSessions, (), (const)); - MOCK_METHOD(uint32, GetActiveAndQueuedSessionCount, (), (const)); - MOCK_METHOD(uint32, GetActiveSessionCount, (), (const)); - MOCK_METHOD(uint32, GetQueuedSessionCount, (), (const)); - MOCK_METHOD(uint32, GetMaxQueuedSessionCount, (), (const)); - MOCK_METHOD(uint32, GetMaxActiveSessionCount, (), (const)); - MOCK_METHOD(uint32, GetPlayerCount, (), (const)); - MOCK_METHOD(uint32, GetMaxPlayerCount, (), (const)); - MOCK_METHOD(void, IncreasePlayerCount, ()); - MOCK_METHOD(void, DecreasePlayerCount, ()); - MOCK_METHOD(Player*, FindPlayerInZone, (uint32 zone), ()); MOCK_METHOD(bool, IsClosed, (), (const)); MOCK_METHOD(void, SetClosed, (bool val), ()); MOCK_METHOD(AccountTypes, GetPlayerSecurityLimit, (), (const)); MOCK_METHOD(void, SetPlayerSecurityLimit, (AccountTypes sec), ()); MOCK_METHOD(void, LoadDBAllowedSecurityLevel, ()); - MOCK_METHOD(void, SetPlayerAmountLimit, (uint32 limit), ()); - MOCK_METHOD(uint32, GetPlayerAmountLimit, (), (const)); - MOCK_METHOD(void, AddQueuedPlayer, (WorldSession*), ()); - MOCK_METHOD(bool, RemoveQueuedPlayer, (WorldSession* session), ()); - MOCK_METHOD(int32, GetQueuePos, (WorldSession*), ()); - MOCK_METHOD(bool, HasRecentlyDisconnected, (WorldSession*), ()); MOCK_METHOD(bool, getAllowMovement, (), (const)); MOCK_METHOD(void, SetAllowMovement, (bool allow), ()); MOCK_METHOD(void, SetNewCharString, (std::string const& str), ()); @@ -72,18 +49,12 @@ public: MOCK_METHOD(uint16, GetConfigMaxSkillValue, (), (const)); MOCK_METHOD(void, SetInitialWorldSettings, ()); MOCK_METHOD(void, LoadConfigSettings, (bool reload), ()); - 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, 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)); MOCK_METHOD(void, ShutdownServ, (uint32 time, uint32 options, uint8 exitcode, const std::string& reason), ()); MOCK_METHOD(void, ShutdownCancel, ()); MOCK_METHOD(void, ShutdownMsg, (bool show, Player* player, const std::string& reason), ()); MOCK_METHOD(void, Update, (uint32 diff), ()); - MOCK_METHOD(void, UpdateSessions, (uint32 diff), ()); MOCK_METHOD(void, setRate, (Rates rate, float value), ()); MOCK_METHOD(float, getRate, (Rates rate), (const)); MOCK_METHOD(void, setBoolConfig, (WorldBoolConfigs index, bool value), ()); @@ -97,8 +68,6 @@ public: MOCK_METHOD(void, LoadWorldStates, ()); MOCK_METHOD(bool, IsPvPRealm, (), (const)); MOCK_METHOD(bool, IsFFAPvPRealm, (), (const)); - MOCK_METHOD(void, KickAll, ()); - MOCK_METHOD(void, KickAllLess, (AccountTypes sec), ()); MOCK_METHOD(uint32, GetNextWhoListUpdateDelaySecs, ()); MOCK_METHOD(void, ProcessCliCommands, ()); MOCK_METHOD(void, QueueCliCommand, (CliCommandHolder* commandHolder), ()); @@ -116,7 +85,6 @@ public: MOCK_METHOD(std::string const&, GetRealmName, (), (const)); MOCK_METHOD(void, SetRealmName, (std::string name), ()); MOCK_METHOD(void, RemoveOldCorpses, ()); - MOCK_METHOD(void, DoForAllOnlinePlayers, (std::function exec)); }; #pragma GCC diagnostic pop From f9415f38cbd54a7820f43e6b327447ba55bcca5e Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Thu, 13 Feb 2025 05:04:36 -0300 Subject: [PATCH 17/97] fix(Scripts/Naxxramas): Update Faerlina script (#21375) --- .../rev_1739149791709679700.sql | 6 + .../Northrend/Naxxramas/boss_faerlina.cpp | 166 +++++------------- 2 files changed, 49 insertions(+), 123 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1739149791709679700.sql diff --git a/data/sql/updates/pending_db_world/rev_1739149791709679700.sql b/data/sql/updates/pending_db_world/rev_1739149791709679700.sql new file mode 100644 index 000000000..986d91122 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1739149791709679700.sql @@ -0,0 +1,6 @@ +-- +DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (28796, 28794, 28798); +INSERT INTO `spelldifficulty_dbc` (`ID`, `DifficultySpellID_1`, `DifficultySpellID_2`, `DifficultySpellID_3`, `DifficultySpellID_4`) VALUES +(28796, 28796, 54098, 0, 0), +(28794, 28794, 54099, 0, 0), +(28798, 28798, 54100, 0, 0); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index ad9c534a6..1be14803f 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -33,21 +33,16 @@ enum Yells enum Spells { - SPELL_POISON_BOLT_VOLLEY_10 = 28796, - SPELL_POISON_BOLT_VOLLEY_25 = 54098, - SPELL_RAIN_OF_FIRE_10 = 28794, - SPELL_RAIN_OF_FIRE_25 = 54099, - SPELL_FRENZY_10 = 28798, - SPELL_FRENZY_25 = 54100, + SPELL_POISON_BOLT_VOLLEY = 28796, + SPELL_RAIN_OF_FIRE = 28794, + SPELL_FRENZY = 28798, SPELL_WIDOWS_EMBRACE = 28732, SPELL_MINION_WIDOWS_EMBRACE = 54097 }; -enum Events +enum Groups { - EVENT_POISON_BOLT = 1, - EVENT_RAIN_OF_FIRE = 2, - EVENT_FRENZY = 3 + GROUP_FRENZY = 1 }; enum Misc @@ -68,16 +63,7 @@ public: struct boss_faerlinaAI : public BossAI { - boss_faerlinaAI(Creature* c) : BossAI(c, BOSS_FAERLINA), summons(me) - { - pInstance = me->GetInstanceScript(); - sayGreet = false; - } - - InstanceScript* pInstance; - EventMap events; - SummonList summons; - bool sayGreet; + boss_faerlinaAI(Creature* c) : BossAI(c, BOSS_FAERLINA), _introDone(false) { } void SummonHelpers() { @@ -92,24 +78,13 @@ public: } } - void JustSummoned(Creature* cr) override - { - summons.Summon(cr); - } - void Reset() override { BossAI::Reset(); - events.Reset(); summons.DespawnAll(); SummonHelpers(); - if (pInstance) - { - if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_FAERLINA_WEB))) - { - go->SetGoState(GO_STATE_ACTIVE); - } - } + if (GameObject* go = me->GetMap()->GetGameObject(instance->GetGuidData(DATA_FAERLINA_WEB))) + go->SetGoState(GO_STATE_ACTIVE); } void JustEngagedWith(Unit* who) override @@ -118,25 +93,38 @@ public: me->CallForHelp(VISIBLE_RANGE); summons.DoZoneInCombat(); Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_POISON_BOLT, 7s, 15s); - events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 8s, 18s); - events.ScheduleEvent(EVENT_FRENZY, 60s, 80s, 1); - events.SetPhase(1); - if (pInstance) - { - if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_FAERLINA_WEB))) + + ScheduleTimedEvent(7s, 15s, [&]{ + if (!me->HasAura(SPELL_WIDOWS_EMBRACE)) + DoCastVictim(SPELL_POISON_BOLT_VOLLEY); + }, 7s, 15s); + + ScheduleTimedEvent(8s, 18s, [&] { + DoCastRandomTarget(SPELL_RAIN_OF_FIRE); + }, 8s, 18s); + + scheduler.Schedule(60s, 80s, GROUP_FRENZY, [this](TaskContext context) { + if (!me->HasAura(SPELL_WIDOWS_EMBRACE)) { - go->SetGoState(GO_STATE_READY); + Talk(SAY_FRENZY); + Talk(EMOTE_FRENZY); + DoCastSelf(SPELL_FRENZY, true); + context.Repeat(1min); } - } + else + context.Repeat(30s); + }); + + if (GameObject* go = me->GetMap()->GetGameObject(instance->GetGuidData(DATA_FAERLINA_WEB))) + go->SetGoState(GO_STATE_READY); } void MoveInLineOfSight(Unit* who) override { - if (!sayGreet && who->IsPlayer()) + if (!_introDone && who->IsPlayer()) { Talk(SAY_GREET); - sayGreet = true; + _introDone = true; } ScriptedAI::MoveInLineOfSight(who); } @@ -147,83 +135,17 @@ public: return; if (!urand(0, 3)) - { Talk(SAY_SLAY); - } - if (pInstance) - { - pInstance->SetData(DATA_IMMORTAL_FAIL, 0); - } + + instance->SetData(DATA_IMMORTAL_FAIL, 0); } void JustDied(Unit* killer) override { BossAI::JustDied(killer); Talk(SAY_DEATH); - if (pInstance) - { - if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_FAERLINA_WEB))) - { - go->SetGoState(GO_STATE_ACTIVE); - } - } - } - - void UpdateAI(uint32 diff) override - { - if (!me->IsInCombat() && sayGreet) - { - for (SummonList::iterator itr = summons.begin(); itr != summons.end(); ++itr) - { - if (pInstance) - { - if (Creature* cr = pInstance->instance->GetCreature(*itr)) - { - if (cr->IsInCombat()) - DoZoneInCombat(); - } - } - } - } - - if (!UpdateVictim()) - return; - - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_POISON_BOLT: - if (!me->HasAura(RAID_MODE(SPELL_WIDOWS_EMBRACE, SPELL_MINION_WIDOWS_EMBRACE))) - { - me->CastCustomSpell(RAID_MODE(SPELL_POISON_BOLT_VOLLEY_10, SPELL_POISON_BOLT_VOLLEY_25), SPELLVALUE_MAX_TARGETS, RAID_MODE(3, 10), me, false); - } - events.Repeat(7s, 15s); - break; - case EVENT_RAIN_OF_FIRE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) - { - me->CastSpell(target, RAID_MODE(SPELL_RAIN_OF_FIRE_10, SPELL_RAIN_OF_FIRE_25), false); - } - events.Repeat(8s, 18s); - break; - case EVENT_FRENZY: - if (!me->HasAura(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25))) - { - Talk(SAY_FRENZY); - Talk(EMOTE_FRENZY); - me->CastSpell(me, RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25), true); - events.Repeat(1min); - } - else - { - events.Repeat(30s); - } - break; - } - DoMeleeAttackIfReady(); + if (GameObject* go = me->GetMap()->GetGameObject(instance->GetGuidData(DATA_FAERLINA_WEB))) + go->SetGoState(GO_STATE_ACTIVE); } void SpellHit(Unit* caster, SpellInfo const* spell) override @@ -231,18 +153,16 @@ public: if (spell->Id == RAID_MODE(SPELL_WIDOWS_EMBRACE, SPELL_MINION_WIDOWS_EMBRACE)) { Talk(EMOTE_WIDOWS_EMBRACE); - if (me->HasAura(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25))) - { - me->RemoveAurasDueToSpell(RAID_MODE(SPELL_FRENZY_10, SPELL_FRENZY_25)); - events.RescheduleEvent(EVENT_FRENZY, 1min); - } - pInstance->SetData(DATA_FRENZY_REMOVED, 0); + scheduler.RescheduleGroup(GROUP_FRENZY, 1min); + me->RemoveAurasDueToSpell(SPELL_FRENZY); + instance->SetData(DATA_FRENZY_REMOVED, 0); if (Is25ManRaid()) - { - Unit::Kill(caster, caster); - } + caster->KillSelf(); } } + + private: + bool _introDone; }; }; From 75388c75380a28502392f338a5da31ea135c698e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 13 Feb 2025 08:05:42 +0000 Subject: [PATCH 18/97] chore(DB): import pending files Referenced commit(s): f9415f38cbd54a7820f43e6b327447ba55bcca5e --- .../rev_1739149791709679700.sql => db_world/2025_02_13_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1739149791709679700.sql => db_world/2025_02_13_00.sql} (87%) diff --git a/data/sql/updates/pending_db_world/rev_1739149791709679700.sql b/data/sql/updates/db_world/2025_02_13_00.sql similarity index 87% rename from data/sql/updates/pending_db_world/rev_1739149791709679700.sql rename to data/sql/updates/db_world/2025_02_13_00.sql index 986d91122..93c8c0dd8 100644 --- a/data/sql/updates/pending_db_world/rev_1739149791709679700.sql +++ b/data/sql/updates/db_world/2025_02_13_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_12_01 -> 2025_02_13_00 -- DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (28796, 28794, 28798); INSERT INTO `spelldifficulty_dbc` (`ID`, `DifficultySpellID_1`, `DifficultySpellID_2`, `DifficultySpellID_3`, `DifficultySpellID_4`) VALUES From 98a8a1306a09aba9930d6da41d25729314cb9abd Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Thu, 13 Feb 2025 07:38:47 -0300 Subject: [PATCH 19/97] fix(Scripts/SunwellPlateau): Fix Felmyst death event (#21425) --- .../rev_1739410685005818200.sql | 24 +++++++++++ .../instance_magisters_terrace.cpp | 3 ++ .../MagistersTerrace/magisters_terrace.h | 5 +++ .../SunwellPlateau/boss_felmyst.cpp | 20 ++++++++- .../SunwellPlateau/boss_kalecgos.cpp | 43 ++----------------- 5 files changed, 53 insertions(+), 42 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1739410685005818200.sql diff --git a/data/sql/updates/pending_db_world/rev_1739410685005818200.sql b/data/sql/updates/pending_db_world/rev_1739410685005818200.sql new file mode 100644 index 000000000..d6bd5a16e --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1739410685005818200.sql @@ -0,0 +1,24 @@ +-- +DELETE FROM `creature_text` WHERE `CreatureID` = 24844 AND `GroupID` = 1; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(24844, 1, 0, 'Madrigosa deserved a far better fate. You did what had to be done, but this battle is far from over!', 14, 0, 100, 25261, 3, 'Kalecgos (SWP) - SAY_KALECGOS_MADRIGOSA'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24844); +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 +(24844, 0, 0, 1, 34, 0, 100, 0, 0, 6, 0, 0, 0, 0, 5, 293, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Reached Point 6 - Play Emote 293'), +(24844, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 207, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Reached Point 6 - Set hover 0'), +(24844, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 67, 0, 2000, 2000, 0, 0, 100, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Reached Point 6 - Create Timed Event'), +(24844, 0, 3, 4, 59, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44762, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Timed Event 0 Triggered - Cast \'Camera Shake - Med\''), +(24844, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 227, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Timed Event 0 Triggered - Set Scale to 1%'), +(24844, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 67, 1, 1000, 1000, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Timed Event 0 Triggered - Create Timed Event'), +(24844, 0, 6, 7, 59, 0, 100, 0, 1, 0, 0, 0, 0, 0, 11, 46307, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Timed Event 1 Triggered - Cast \'Scrying Orb Kill Credit\''), +(24844, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 24085, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Timed Event 1 Triggered - Cast \'Transform Visual\''), +(24844, 0, 8, 9, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 44670, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Timed Event 1 Triggered - Cast \'KalecgosTransform into Kalec\''), +(24844, 0, 9, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 36, 24848, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Timed Event 1 Triggered - Update Template To \'Kalecgos\''), +(24844, 0, 10, 11, 34, 0, 100, 0, 8, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Reached Point 1 - Say Line 1'), +(24844, 0, 11, 0, 61, 0, 100, 1, 0, 0, 0, 0, 0, 0, 67, 2, 4000, 4000, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Reached Point 1 - Create Timed Event'), +(24844, 0, 12, 0, 59, 0, 100, 0, 2, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1511.65, 550.702, 25.5101, 0, 'Kalecgos - On Timed Event 2 Triggered - Move To Self'), +(24844, 0, 13, 14, 34, 0, 100, 0, 8, 2, 0, 0, 0, 0, 11, 46650, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Reached Point 2 - Cast \'Open Brutallus Back Door\''), +(24844, 0, 14, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 67, 3, 4000, 4000, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Reached Point 2 - Create Timed Event'), +(24844, 0, 15, 0, 59, 0, 100, 0, 3, 0, 0, 0, 0, 0, 69, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1648.26, 519.377, 165.848, 0, 'Kalecgos - On Timed Event 3 Triggered - Move To Self'), +(24844, 0, 16, 0, 34, 0, 100, 0, 8, 3, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Kalecgos - On Reached Point 3 - Despawn Instant'); diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp index 74308a0bb..3311f3965 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -79,7 +79,10 @@ public: scheduler.Schedule(1min, 1min, DATA_KALECGOS,[this](TaskContext) { if (Creature* kalecgos = instance->SummonCreature(NPC_KALECGOS, KalecgosSpawnPos)) + { kalecgos->GetMotionMaster()->MovePath(PATH_KALECGOS_FLIGHT, false); + kalecgos->AI()->Talk(SAY_KALECGOS_SPAWN); + } }); } } diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h index 35b04fc67..49de3e72d 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h @@ -69,6 +69,11 @@ enum MovementData PATH_KALECGOS_FLIGHT = 248440 }; +enum CreatureTexts +{ + SAY_KALECGOS_SPAWN = 0 +}; + template inline AI* GetMagistersTerraceAI(T* obj) { diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp index f8ead6557..615fd8ee8 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp @@ -73,10 +73,13 @@ enum Misc POINT_AIR_BREATH_END2 = 6, POINT_MISC = 7, + POINT_KALECGOS = 1, + GROUP_START_INTRO = 0, GROUP_BREATH = 1, - NPC_FOG_TRIGGER = 23472 + NPC_FOG_TRIGGER = 23472, + NPC_KALECGOS_FELMYST = 24844 // Same as Magister's Terrace }; class CorruptTriggers : public BasicEvent @@ -159,7 +162,8 @@ struct boss_felmyst : public BossAI instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FOG_OF_CORRUPTION_CHARM); // Summon Kalecgos (human form of kalecgos fight) - me->SummonCreature(NPC_KALEC, 1526.28f, 700.10f, 60.0f, 4.33f); + if (Creature* kalec = me->SummonCreature(NPC_KALECGOS_FELMYST, 1573.1461f, 755.20245f, 99.524956f, 3.595378f)) + kalec->GetMotionMaster()->MovePoint(POINT_KALECGOS, 1474.2347f, 624.0703f, 29.32589f, false, true); } void MovementInform(uint32 type, uint32 point) override @@ -472,14 +476,26 @@ class spell_felmyst_open_brutallus_back_doors : public SpellScript { PrepareSpellScript(spell_felmyst_open_brutallus_back_doors); + bool Load() override + { + return GetCaster()->GetInstanceScript(); + } + void FilterTargets(std::list& unitList) { unitList.remove_if(DoorsGuidCheck()); } + void HandleAfterCast() + { + GetCaster()->GetInstanceScript()->SetBossState(DATA_FELMYST_DOORS, NOT_STARTED); + GetCaster()->GetInstanceScript()->SetBossState(DATA_FELMYST_DOORS, DONE); + } + void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_felmyst_open_brutallus_back_doors::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + AfterCast += SpellCastFn(spell_felmyst_open_brutallus_back_doors::HandleAfterCast); } }; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index 35c71b297..b775edb8c 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -246,7 +246,9 @@ struct boss_kalecgos : public BossAI scheduler.Schedule(16s, [this](TaskContext) { - me->SummonCreature(NPC_KALEC, 1702.21f, 931.7f, -74.56f, 5.07f, TEMPSUMMON_MANUAL_DESPAWN); + if (Creature* kalec = me->SummonCreature(NPC_KALEC, 1702.21f, 931.7f, -74.56f, 5.07f, TEMPSUMMON_MANUAL_DESPAWN)) + kalec->CastSpell(kalec, SPELL_SPECTRAL_INVISIBILITY, true); + me->SummonCreature(NPC_SATHROVARR, 1704.62f, 927.78f, -73.9f, 2.0f, TEMPSUMMON_MANUAL_DESPAWN); }); @@ -264,49 +266,10 @@ struct boss_kalecgos : public BossAI bool _sathBanished; }; -enum Kalec -{ - SPELL_OPEN_BRUTALLUS_BACK_DOOR = 46650, - MODEL_KALECGOS_DRAGON = 23487, - - EVENT_KALEC_SCENE_1 = 101, - EVENT_KALEC_SCENE_2 = 102, - EVENT_KALEC_SCENE_3 = 103 -}; - struct boss_kalec : public ScriptedAI { boss_kalec(Creature* creature) : ScriptedAI(creature) { } - void Reset() override - { - if (me->GetPositionY() < 750.0f) - { - me->SetSpeed(MOVE_RUN, 2.4f); - me->SetDisplayId(MODEL_KALECGOS_DRAGON); - me->SetDisableGravity(true); - me->GetMotionMaster()->MovePoint(0, 1483.30f, 657.99f, 28.0f, false, true); - - me->m_Events.AddEventAtOffset([&] { - Talk(SAY_GOOD_MADRIGOSA); - me->GetMotionMaster()->MovePoint(0, 1509.0f, 560.0f, 30.0f, false, true); - }, 9s); - - me->m_Events.AddEventAtOffset([&] { - DoCastAOE(SPELL_OPEN_BRUTALLUS_BACK_DOOR, true); - me->GetInstanceScript()->SetBossState(DATA_FELMYST_DOORS, NOT_STARTED); - me->GetInstanceScript()->SetBossState(DATA_FELMYST_DOORS, DONE); - }, 16s); - - me->m_Events.AddEventAtOffset([&] { - me->GetMotionMaster()->MovePoint(0, 1400.0f, 630.0f, 90.0f, false, true); - me->DespawnOrUnsummon(6000); - }, 22s); - } - else - DoCastSelf(SPELL_SPECTRAL_INVISIBILITY, true); - } - void JustEngagedWith(Unit*) override { ScheduleTimedEvent(5s, [&] { From c5d83d31c757600988793566e88f3b30438b2995 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 13 Feb 2025 10:39:46 +0000 Subject: [PATCH 20/97] chore(DB): import pending files Referenced commit(s): 98a8a1306a09aba9930d6da41d25729314cb9abd --- .../rev_1739410685005818200.sql => db_world/2025_02_13_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1739410685005818200.sql => db_world/2025_02_13_01.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1739410685005818200.sql b/data/sql/updates/db_world/2025_02_13_01.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1739410685005818200.sql rename to data/sql/updates/db_world/2025_02_13_01.sql index d6bd5a16e..fd4398508 100644 --- a/data/sql/updates/pending_db_world/rev_1739410685005818200.sql +++ b/data/sql/updates/db_world/2025_02_13_01.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_13_00 -> 2025_02_13_01 -- DELETE FROM `creature_text` WHERE `CreatureID` = 24844 AND `GroupID` = 1; INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `BroadcastTextId`, `TextRange`, `comment`) VALUES From 9e720b91f0347b4e4efe6dd4b8017d340f086ced Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Thu, 13 Feb 2025 13:13:40 +0100 Subject: [PATCH 21/97] fix(Core/Worldstate): fix Sanctums Wards triggering phase transition too early (#21430) --- src/server/game/World/WorldState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/World/WorldState.cpp b/src/server/game/World/WorldState.cpp index 2d7d56b55..d2fe8f64f 100644 --- a/src/server/game/World/WorldState.cpp +++ b/src/server/game/World/WorldState.cpp @@ -431,7 +431,7 @@ void WorldState::AddSunsReachProgress(uint32 questId) break; case QUEST_SANCTUM_WARDS: counter = COUNTER_SANCTUM_WARDS; - otherCounter = COUNTER_SANCTUM_WARDS; + otherCounter = COUNTER_ERRATIC_BEHAVIOR; worldState = WORLD_STATE_QUEL_DANAS_SANCTUM; break; case QUEST_BATTLE_FOR_THE_SUNS_REACH_ARMORY: From 6c2d9aff49dbbd3f5e463cb8b7f26fd3352aff18 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:05:14 -0300 Subject: [PATCH 22/97] chore(Config): Improve DynamicRates description (#21431) --- .../apps/worldserver/worldserver.conf.dist | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index e0698fa55..4e32c5807 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -4473,10 +4473,13 @@ Debug.Arena = 0 # # # Respawn.DynamicRateCreature -# Description: The rate at which the respawn time is adjusted for high player counts in a zone (for creatures). -# Up to this number of players, the respawn rate is unchanged. -# Does not affect instanced creatures, bosses or quest givers. -# At double this number in players, you get twice as many respawns, at three times this number, three times the respawns, and so forth. +# Description: Controls how creature respawn times adjust based on player count in a zone. +# The respawn time is unchanged up to the configured number of players. +# As player count exceeds this value, respawn times decrease proportionally +# (e.g., at double the player count, respawn times are halved; at triple the player count, respawns happen three times as fast). +# Does not affect instanced creatures, bosses, or quest givers. +# Formula: adjustFactor = rate / playerCount +# RespawnTime = RespawnTime * adjustFactor # Default: 1 (Disabled) Respawn.DynamicRateCreature = 1 @@ -4490,10 +4493,13 @@ Respawn.DynamicMinimumCreature = 10 # # Respawn.DynamicRateGameObject -# Description: The rate at which the respawn time is adjusted for high player counts in a zone (for gameobjects). -# Up to this number of players, the respawn rate is unchanged. +# Description: Controls how gameobject respawn times adjust based on player count in a zone. +# The respawn time is unchanged up to the configured number of players. +# As player count exceeds this value, respawn times decrease proportionally +# (e.g., at double the player count, respawn times are halved; at triple the player count, respawns happen three times as fast). # Does not affect instanced objects or quest givers. -# At double this number in players, you get twice as many respawns, at three times this number, three times the respawns, and so forth. +# Formula: adjustFactor = rate / playerCount +# RespawnTime = RespawnTime * adjustFactor # Default: 1 (Disabled) Respawn.DynamicRateGameObject = 1 From 0db39f76de2667fcb495deaef257d8a9e38f4bf2 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:22:02 -0300 Subject: [PATCH 23/97] fix(Core/Creature): Creatures should skip confused targets (#21410) --- src/server/game/Combat/ThreatMgr.cpp | 4 ++-- .../BlackwingLair/boss_razorgore.cpp | 20 +------------------ .../EasternKingdoms/ZulGurub/boss_jindo.cpp | 18 ----------------- .../Mechanar/boss_nethermancer_sepethrea.cpp | 18 ----------------- 4 files changed, 3 insertions(+), 57 deletions(-) diff --git a/src/server/game/Combat/ThreatMgr.cpp b/src/server/game/Combat/ThreatMgr.cpp index 30fb7a146..899eee48e 100644 --- a/src/server/game/Combat/ThreatMgr.cpp +++ b/src/server/game/Combat/ThreatMgr.cpp @@ -328,7 +328,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR Unit* cvUnit = currentVictim->getTarget(); if (!attacker->CanCreatureAttack(cvUnit)) // pussywizard: if currentVictim is not valid => don't compare the threat with it, just take the highest threat valid target currentVictim = nullptr; - else if (cvUnit->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || cvUnit->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage + else if (cvUnit->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || cvUnit->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || cvUnit->HasUnitState(UNIT_STATE_CONFUSED)) // pussywizard: no 10%/30% if currentVictim is immune to damage or has auras breakable by damage currentVictim = nullptr; } @@ -345,7 +345,7 @@ HostileReference* ThreatContainer::SelectNextVictim(Creature* attacker, HostileR // pussywizard: don't go to threat comparison if this ref is immune to damage or has aura breakable on damage (second choice target) // pussywizard: if this is the last entry on the threat list, then all targets are second choice, set bool to true and loop threat list again, ignoring this section - if (!noPriorityTargetFound && (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID()))) + if (!noPriorityTargetFound && (target->IsImmunedToDamageOrSchool(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE) || target->HasUnitState(UNIT_STATE_CONFUSED) || target->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, attacker->GetGUID()))) { if (iter != lastRef) { diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp index c837cfc81..4b82654fb 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp @@ -110,25 +110,7 @@ public: bool CanAIAttack(Unit const* target) const override { - if (target->IsCreature() && !secondPhase) - { - return false; - } - - if (me->GetThreatMgr().GetThreatListSize() > 1) - { - ThreatContainer::StorageType::const_iterator lastRef = me->GetThreatMgr().GetOnlineContainer().GetThreatList().end(); - --lastRef; - if (Unit* lastTarget = (*lastRef)->getTarget()) - { - if (lastTarget != target) - { - return !target->HasAura(SPELL_CONFLAGRATION); - } - } - } - - return true; + return !(target->IsCreature() && !secondPhase); } void JustEngagedWith(Unit* /*who*/) override diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp index 57b2321d6..27d302260 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp @@ -153,24 +153,6 @@ struct boss_jindo : public BossAI DoMeleeAttackIfReady(); } - bool CanAIAttack(Unit const* target) const override - { - if (me->GetThreatMgr().GetThreatListSize() > 1) - { - ThreatContainer::StorageType::const_iterator lastRef = me->GetThreatMgr().GetOnlineContainer().GetThreatList().end(); - --lastRef; - if (Unit* lastTarget = (*lastRef)->getTarget()) - { - if (lastTarget != target) - { - return !target->HasAura(SPELL_HEX); - } - } - } - - return true; - } - private: TaskScheduler _scheduler; }; diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp index c45fe391f..5999aaa8a 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp @@ -51,24 +51,6 @@ struct boss_nethermancer_sepethrea : public BossAI { boss_nethermancer_sepethrea(Creature* creature) : BossAI(creature, DATA_NETHERMANCER_SEPRETHREA) { } - bool CanAIAttack(Unit const* target) const override - { - if (me->GetThreatMgr().GetThreatListSize() > 1) - { - ThreatContainer::StorageType::const_iterator lastRef = me->GetThreatMgr().GetOnlineContainer().GetThreatList().end(); - --lastRef; - if (Unit* lastTarget = (*lastRef)->getTarget()) - { - if (lastTarget != target) - { - return !target->HasAura(SPELL_DRAGONS_BREATH); - } - } - } - - return true; - } - void JustEngagedWith(Unit* /*who*/) override { _JustEngagedWith(); From db49562a6aaad5336f1287dc5f30ac32e3ebcbfa Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Thu, 13 Feb 2025 21:39:29 +0100 Subject: [PATCH 24/97] fix(Core/Channels): Don't use deleted pointer in channel name creation. (#21435) --- src/server/game/Entities/Player/PlayerUpdates.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index 4ffd9efcf..7dccbf189 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -550,17 +550,16 @@ void Player::UpdateLocalChannels(uint32 newZone) // names are not changing char new_channel_name_buf[100]; - char const* currentNameExt; + std::string currentNameExt; if (channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY) - currentNameExt = sObjectMgr->GetAcoreStringForDBCLocale( - LANG_CHANNEL_CITY).c_str(); + currentNameExt = sObjectMgr->GetAcoreStringForDBCLocale(LANG_CHANNEL_CITY); else - currentNameExt = current_zone_name.c_str(); + currentNameExt = current_zone_name; snprintf(new_channel_name_buf, 100, channel->pattern[m_session->GetSessionDbcLocale()], - currentNameExt); + currentNameExt.c_str()); joinChannel = cMgr->GetJoinChannel(new_channel_name_buf, channel->ChannelID); From db9b4cf0c61ed6b738df5090bd6144e24415436f Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Fri, 14 Feb 2025 05:54:45 +0100 Subject: [PATCH 25/97] fix(Scripts/ICC): Fix crash in npc_darnavan when killer is nil. (#21438) --- .../boss_lady_deathwhisper.cpp | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index dcc37e3ca..ef04e7e5b 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -1021,18 +1021,25 @@ public: void JustDied(Unit* killer) override { events.Reset(); - if (Player* owner = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) + + if (!killer) + return; + + Player* owner = killer->GetCharmerOrOwnerPlayerOrPlayerItself(); + if (!owner) + return; + + Group* group = owner->GetGroup(); + if (!group) { - if (Group* group = owner->GetGroup()) - { - for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) - if (Player* member = itr->GetSource()) - if (member->IsInMap(owner)) - member->FailQuest(QUEST_DEPROGRAMMING); - } - else - owner->FailQuest(QUEST_DEPROGRAMMING); + owner->FailQuest(QUEST_DEPROGRAMMING); + return; } + + for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) + if (Player* member = itr->GetSource()) + if (member->IsInMap(owner)) + member->FailQuest(QUEST_DEPROGRAMMING); } void MovementInform(uint32 type, uint32 id) override From 062f9c4341aafe2e128668dc847f9821d5ecba7e Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Fri, 14 Feb 2025 07:30:59 -0300 Subject: [PATCH 26/97] fix(Core/Map): Dynamic respawns: preserve original respawn timer and skip rares (#21440) --- .../game/Entities/Creature/Creature.cpp | 4 ++-- .../game/Entities/GameObject/GameObject.cpp | 4 ++-- src/server/game/Maps/Map.cpp | 22 ++++++++++--------- src/server/game/Maps/Map.h | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 6b60457a9..c26c50589 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1975,8 +1975,8 @@ void Creature::setDeathState(DeathState state, bool despawn) if (state == DeathState::JustDied) { m_corpseRemoveTime = GameTime::GetGameTime().count() + m_corpseDelay; - GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelay); - m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay + m_corpseDelay; + uint32 dynamicRespawnDelay = GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelay); + m_respawnTime = GameTime::GetGameTime().count() + dynamicRespawnDelay + m_corpseDelay; // always save boss respawn time at death to prevent crash cheating if (GetMap()->IsDungeon() || isWorldBoss() || GetCreatureTemplate()->rank >= CREATURE_ELITE_ELITE) diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 9ed685f9e..6c942d576 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -897,8 +897,8 @@ void GameObject::Update(uint32 diff) return; } - GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelayTime); - m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelayTime; + uint32 dynamicRespawnDelay = GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelayTime); + m_respawnTime = GameTime::GetGameTime().count() + dynamicRespawnDelay; // if option not set then object will be saved at grid unload if (GetMap()->IsDungeon()) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 33e4a8a2c..5d9579c4a 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2658,38 +2658,40 @@ void Map::SendObjectUpdates() } } -void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32& respawnDelay) const +uint32 Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32 respawnDelay) const { ASSERT(obj->GetMap() == this); float rate = sWorld->getFloatConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICRATE_CREATURE); if (rate == 1.0f) - return; + return respawnDelay; // No instanced maps (dungeons, battlegrounds, arenas etc.) if (obj->GetMap()->Instanceable()) - return; + return respawnDelay; // No quest givers or world bosses if (Creature const* creature = obj->ToCreature()) - if (creature->IsQuestGiver() || creature->isWorldBoss()) - return; + if (creature->IsQuestGiver() || creature->isWorldBoss() + || (creature->GetCreatureTemplate()->rank == CREATURE_ELITE_RARE) + || (creature->GetCreatureTemplate()->rank == CREATURE_ELITE_RAREELITE)) + return respawnDelay; auto it = _zonePlayerCountMap.find(obj->GetZoneId()); if (it == _zonePlayerCountMap.end()) - return; + return respawnDelay; uint32 const playerCount = it->second; if (!playerCount) - return; + return respawnDelay; double const adjustFactor = rate / playerCount; if (adjustFactor >= 1.0) // nothing to do here - return; + return respawnDelay; uint32 const timeMinimum = sWorld->getIntConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE); if (respawnDelay <= timeMinimum) - return; + return respawnDelay; - respawnDelay = std::max(std::ceil(respawnDelay * adjustFactor), timeMinimum); + return std::max(std::ceil(respawnDelay * adjustFactor), timeMinimum); } void Map::DelayedUpdate(const uint32 t_diff) diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 8763590e5..54f8d7c2c 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -595,7 +595,7 @@ public: [[nodiscard]] time_t GetInstanceResetPeriod() const { return _instanceResetPeriod; } void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone); - void ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32& respawnDelay) const; + [[nodiscard]] uint32 ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32 respawnDelay) const; TaskScheduler _creatureRespawnScheduler; From 9412c1eb3ae7c9b0b39a81351f3575f79c1b714d Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Fri, 14 Feb 2025 11:31:14 +0100 Subject: [PATCH 27/97] fix(Scripts/BlackTemple): Illidan buffer overflow (#21441) --- .../scripts/Outland/BlackTemple/boss_illidan.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 4ab5aaae9..da92628e0 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -207,7 +207,7 @@ struct boss_illidan_stormrage : public BossAI _canTalk = true; _dying = false; _inCutscene = false; - beamPosId = urand(0, MAX_EYE_BEAM_POS); + beamPosId = urand(0, MAX_EYE_BEAM_POS - 1); me->ReplaceAllUnitFlags(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); me->SetDisableGravity(false); me->SetHover(false); @@ -696,11 +696,11 @@ private: void CycleBeamPos(uint8 &beamPosId) { - uint8 _incumbentBeamPos = urand(0, MAX_EYE_BEAM_POS); - if (_incumbentBeamPos == beamPosId) - CycleBeamPos(beamPosId); - else - beamPosId = _incumbentBeamPos; + uint8 newPos; + do { + newPos = urand(0, MAX_EYE_BEAM_POS - 1); + } while (newPos == beamPosId); + beamPosId = newPos; } }; From 3854d00dee336ea9331b1f6a627fd117b017c16b Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Fri, 14 Feb 2025 11:31:21 +0100 Subject: [PATCH 28/97] fix(Scripts/ShadowmoonValley): Illidan buffer overflow (#21442) --- src/server/scripts/Outland/zone_shadowmoon_valley.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index a93ff83bf..06e0b287c 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -1385,9 +1385,12 @@ void npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI::SummonNextWave() } } } - ++WaveCount; - WaveTimer = WavesInfo[WaveCount].SpawnTimer; - AnnounceTimer = WavesInfo[WaveCount].YellTimer; + if (WaveCount < 3) + { + ++WaveCount; + WaveTimer = WavesInfo[WaveCount].SpawnTimer; + AnnounceTimer = WavesInfo[WaveCount].YellTimer; + } } /*##### From 75441ddb3b94f207345d1646a991a57cb00698dd Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Fri, 14 Feb 2025 15:45:36 +0100 Subject: [PATCH 29/97] fix(Core/Player): SpellQueue avoid possible undefined behavior by copying instead of move (#21444) --- src/server/game/Handlers/SpellHandler.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 7f11d413f..e200aaf3d 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -110,11 +110,12 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) if (!_player->CanExecutePendingSpellCastRequest(spellInfo)) if (_player->CanRequestSpellCast(spellInfo)) { - recvPacket.rpos(0); // Reset read position to the start of the buffer. + WorldPacket packetCopy(recvPacket); // Copy the packet + packetCopy.rpos(0); // Reset read position to the start of the buffer. _player->SpellQueue.emplace_back( spellId, spellInfo->GetCategory(), - std::move(recvPacket), // Move ownership of recvPacket + std::move(packetCopy), // Move ownership of copied packet true // itemCast ); return; @@ -424,11 +425,12 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { if (_player->CanRequestSpellCast(spellInfo)) { - recvPacket.rpos(0); // Reset read position to the start of the buffer. + WorldPacket packetCopy(recvPacket); // Copy the packet + packetCopy.rpos(0); // Reset read position to the start of the buffer. _player->SpellQueue.emplace_back( spellId, spellInfo->GetCategory(), - std::move(recvPacket) // Move ownership of recvPacket + std::move(packetCopy) // Move ownership of copied packet ); return; } From cdcdf4564bebf7a2b1c390a137bb6622f23f01da Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Fri, 14 Feb 2025 20:02:02 +0100 Subject: [PATCH 30/97] fix(Core/Pet): Fix possible heap-use-after-free of charmInfo when handling pet action. (#21439) --- src/server/game/Handlers/PetHandler.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index e7c42cb57..56702d125 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -432,8 +432,14 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe spell->prepare(&(spell->m_targets)); - charmInfo->SetForcedSpell(0); - charmInfo->SetForcedTargetGUID(); + // spell->prepare() can delete charm info. + // Let's refresh the pointer. + charmInfo = pet->GetCharmInfo(); + if (charmInfo) + { + charmInfo->SetForcedSpell(0); + charmInfo->SetForcedTargetGUID(); + } } else if (pet->ToPet() && (result == SPELL_FAILED_LINE_OF_SIGHT || result == SPELL_FAILED_OUT_OF_RANGE)) { From 0bbcddcf70f80fe267532382144a10c17acd7125 Mon Sep 17 00:00:00 2001 From: sudlud Date: Fri, 14 Feb 2025 21:49:28 +0100 Subject: [PATCH 31/97] fix(DB/Creature): Sniffed Values for 'Chemical Wagon' spawns (#21446) --- .../rev_1739562014383775800.sql | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1739562014383775800.sql diff --git a/data/sql/updates/pending_db_world/rev_1739562014383775800.sql b/data/sql/updates/pending_db_world/rev_1739562014383775800.sql new file mode 100644 index 000000000..390563dfa --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1739562014383775800.sql @@ -0,0 +1,22 @@ +-- Update creature 'Chemical Wagon' with sniffed values +-- updated spawns +DELETE FROM `creature` WHERE (`id1` IN (38035)) +AND (`guid` IN (244545, 244546, 244547, 244563, 244606, 244607, 244608, 244609, 244610, 244626, 244627, 244628)); +INSERT INTO `creature` (`guid`, `id1`, `map`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES +(244545, 38035, 571, 1, 1, 0, 5576.52001953125, 124.3194427490234375, 150.7883148193359375, 0, 60, 0, 0, 0, 0, 0, "", 47966, 1, NULL), +(244546, 38035, 571, 1, 1, 0, 5579.13623046875, 179.282989501953125, 149.988311767578125, 0, 60, 0, 0, 0, 0, 0, "", 47966, 1, NULL), +(244547, 38035, 571, 1, 1, 0, 5592.712890625, 68.626739501953125, 148.6106414794921875, 0, 60, 0, 0, 0, 0, 0, "", 47966, 1, NULL), +(244563, 38035, 0, 1, 1, 0, -50.1857643127441406, 1150.40283203125, 66.0908966064453125, 0, 60, 0, 0, 0, 0, 0, "", 48120, 1, NULL), +(244606, 38035, 0, 1, 1, 0, -9454.0869140625, 522.810791015625, 55.90142440795898437, 0, 60, 0, 0, 0, 0, 0, "", 47966, 1, NULL), +(244607, 38035, 1, 1, 1, 0, 1264.05908203125, -4084.616455078125, 25.5284423828125, 6.091198921203613281, 60, 0, 0, 0, 0, 0, "", 52237, 1, NULL), +(244608, 38035, 530, 1, 1, 0, -1808.5399169921875, 4844.61279296875, 1.952302336692810058, 0, 60, 0, 0, 0, 0, 0, "", 52237, 1, NULL), +(244609, 38035, 1, 1, 1, 0, 6764.822265625, -4905.1337890625, 774.3394775390625, 0, 60, 0, 0, 0, 0, 0, "", 52237, 1, NULL), +(244610, 38035, 571, 1, 1, 0, 5638.01904296875, 107.0156326293945312, 154.995635986328125, 1.099557399749755859, 60, 0, 0, 0, 0, 0, "", 47966, 1, NULL), +(244626, 38035, 0, 1, 1, 0, 88.58333587646484375, -2477.989501953125, 124.8402938842773437, 0, 60, 0, 0, 0, 0, 0, "", 52237, 1, NULL), +(244627, 38035, 1, 1, 1, 0, -3370.935791015625, -4168.5537109375, 17.8669586181640625, 0, 60, 0, 0, 0, 0, 0, "", 52237, 1, NULL), +(244628, 38035, 0, 1, 1, 0, -406.282989501953125, 163.5868072509765625, 75.5319976806640625, 0, 60, 0, 0, 0, 0, 0, "", 52237, 1, NULL); + +-- enable all spawns for eventEntry 8 +DELETE FROM `game_event_creature` WHERE (`eventEntry` = 8) +AND (`guid` IN (SELECT `guid` FROM `creature` WHERE `id1` IN (38035))); +INSERT INTO `game_event_creature` (SELECT 8, `guid` FROM `creature` WHERE `id1` IN (38035)); From 0273a9f08dba7fe5993e86a60a60da6a68bfc657 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 14 Feb 2025 20:50:33 +0000 Subject: [PATCH 32/97] chore(DB): import pending files Referenced commit(s): 0bbcddcf70f80fe267532382144a10c17acd7125 --- .../rev_1739562014383775800.sql => db_world/2025_02_14_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1739562014383775800.sql => db_world/2025_02_14_00.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1739562014383775800.sql b/data/sql/updates/db_world/2025_02_14_00.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1739562014383775800.sql rename to data/sql/updates/db_world/2025_02_14_00.sql index 390563dfa..ce6e14524 100644 --- a/data/sql/updates/pending_db_world/rev_1739562014383775800.sql +++ b/data/sql/updates/db_world/2025_02_14_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_13_01 -> 2025_02_14_00 -- Update creature 'Chemical Wagon' with sniffed values -- updated spawns DELETE FROM `creature` WHERE (`id1` IN (38035)) From 2982b64430bfd87df9b92ba901c9ea7de7517c49 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Fri, 14 Feb 2025 21:58:30 +0100 Subject: [PATCH 33/97] fix(Core/Spell): Reset insignia spell target when it is deleted. (#21437) --- src/server/game/Spells/SpellEffects.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index e34918ac1..c10a2cb2c 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -5586,6 +5586,10 @@ void Spell::EffectSkinPlayerCorpse(SpellEffIndex /*effIndex*/) return; unitTarget->ToPlayer()->RemovedInsignia(m_caster->ToPlayer()); + + // We have a corpse object as the target. + // This target was deleted in RemovedInsignia() -> ConvertCorpseToBones(). + m_targets.RemoveObjectTarget(); } void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex) From 10183efd5135d2f51bf1117c93921239401b7c3d Mon Sep 17 00:00:00 2001 From: Mykhailo Redko Date: Fri, 14 Feb 2025 23:11:01 +0200 Subject: [PATCH 34/97] fix(Core/Chat): Fix lower security check for GM commands. (#21382) --- src/server/game/Chat/Chat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 26bfaf34c..d446b0eaa 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -82,7 +82,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac return false; // ignore only for non-players for non strong checks (when allow apply command at least to same sec level) - if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity()) && !strong && !sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY)) + if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity()) && !strong && sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY)) return false; if (target) From ee69a569c404594ab52304e78a13682662538470 Mon Sep 17 00:00:00 2001 From: Takenbacon Date: Fri, 14 Feb 2025 13:11:27 -0800 Subject: [PATCH 35/97] fix(Core/Grids): Grid improvements (#20955) --- src/common/Collision/Maps/MapDefines.h | 1 + .../game/Achievements/AchievementMgr.cpp | 5 - .../game/Entities/Creature/CreatureGroups.cpp | 1 + .../game/Entities/Item/ItemEnchantmentMgr.cpp | 1 + src/server/game/Entities/Object/Object.cpp | 11 +- .../game/Entities/Transport/Transport.h | 1 + src/server/game/Entities/Unit/Unit.cpp | 2 + src/server/game/Globals/ObjectMgr.cpp | 18 +- src/server/game/Globals/ObjectMgr.h | 4 +- src/server/game/Grids/Cells/Cell.h | 24 +- src/server/game/Grids/Cells/CellImpl.h | 59 +- src/server/game/Grids/Grid.h | 131 -- src/server/game/Grids/GridCell.h | 75 ++ src/server/game/Grids/GridDefines.h | 16 +- src/server/game/Grids/GridLoader.h | 76 -- src/server/game/Grids/GridObjectLoader.cpp | 138 ++ ...{ObjectGridLoader.h => GridObjectLoader.h} | 47 +- src/server/game/Grids/GridTerrainData.cpp | 617 +++++++++ src/server/game/Grids/GridTerrainData.h | 255 ++++ src/server/game/Grids/GridTerrainLoader.cpp | 160 +++ src/server/game/Grids/GridTerrainLoader.h | 59 + src/server/game/Grids/MapGrid.h | 154 +++ src/server/game/Grids/MapGridManager.cpp | 129 ++ src/server/game/Grids/MapGridManager.h | 62 + src/server/game/Grids/NGrid.h | 113 -- .../game/Grids/Notifiers/GridNotifiers.h | 2 +- src/server/game/Grids/ObjectGridLoader.cpp | 245 ---- src/server/game/Handlers/ChatHandler.cpp | 8 +- src/server/game/Loot/LootItemStorage.cpp | 1 + src/server/game/Maps/Map.cpp | 1149 +++-------------- src/server/game/Maps/Map.h | 254 +--- src/server/game/Maps/MapInstanced.cpp | 9 +- src/server/game/Maps/MapMgr.cpp | 11 +- src/server/game/Maps/MapMgr.h | 1 + .../game/Movement/Waypoints/WaypointMgr.cpp | 1 + .../Scripting/ScriptDefines/AllMapScript.cpp | 5 +- src/server/game/Scripting/ScriptMgr.h | 4 +- src/server/game/Scripting/ScriptObject.h | 4 +- src/server/game/Scripting/ScriptObjectFwd.h | 2 +- src/server/game/Spells/Spell.cpp | 4 - src/server/game/World/World.cpp | 2 +- src/server/scripts/Commands/cs_debug.cpp | 17 +- src/server/scripts/Commands/cs_misc.cpp | 9 +- .../Karazhan/boss_nightbane.cpp | 1 - .../Stratholme/instance_stratholme.cpp | 6 - .../SunkenTemple/instance_sunken_temple.cpp | 1 - .../instance_sunwell_plateau.cpp | 2 - .../EasternKingdoms/ZulGurub/boss_hakkar.cpp | 20 - .../Events/firework_show/firework_show.cpp | 1 + .../instance_culling_of_stratholme.cpp | 13 - .../instance_old_hillsbrad.cpp | 16 - .../instance_the_black_morass.cpp | 1 - .../Kalimdor/DireMaul/instance_dire_maul.cpp | 3 - .../RuinsOfAhnQiraj/boss_kurinnaxx.cpp | 3 - .../instance_ruins_of_ahnqiraj.cpp | 1 - .../instance_wailing_caverns.cpp | 2 - .../RubySanctum/instance_ruby_sanctum.cpp | 1 - .../instance_halls_of_reflection.cpp | 3 - .../PitOfSaron/instance_pit_of_saron.cpp | 1 - .../IcecrownCitadel/boss_sindragosa.cpp | 1 - .../IcecrownCitadel/icecrown_citadel.cpp | 2 - .../instance_icecrown_citadel.cpp | 2 - .../Naxxramas/instance_naxxramas.cpp | 4 - .../Ulduar/Ulduar/instance_ulduar.cpp | 6 - .../scripts/OutdoorPvP/OutdoorPvPNA.cpp | 2 +- .../BloodFurnace/boss_kelidan_the_breaker.cpp | 1 - .../instance_shattered_halls.cpp | 1 - 67 files changed, 1955 insertions(+), 2026 deletions(-) delete mode 100644 src/server/game/Grids/Grid.h create mode 100644 src/server/game/Grids/GridCell.h delete mode 100644 src/server/game/Grids/GridLoader.h create mode 100644 src/server/game/Grids/GridObjectLoader.cpp rename src/server/game/Grids/{ObjectGridLoader.h => GridObjectLoader.h} (55%) create mode 100644 src/server/game/Grids/GridTerrainData.cpp create mode 100644 src/server/game/Grids/GridTerrainData.h create mode 100644 src/server/game/Grids/GridTerrainLoader.cpp create mode 100644 src/server/game/Grids/GridTerrainLoader.h create mode 100644 src/server/game/Grids/MapGrid.h create mode 100644 src/server/game/Grids/MapGridManager.cpp create mode 100644 src/server/game/Grids/MapGridManager.h delete mode 100644 src/server/game/Grids/NGrid.h delete mode 100644 src/server/game/Grids/ObjectGridLoader.cpp diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h index 6772a20c7..7f28fc8b2 100644 --- a/src/common/Collision/Maps/MapDefines.h +++ b/src/common/Collision/Maps/MapDefines.h @@ -22,6 +22,7 @@ #include "DetourNavMesh.h" #define MAX_NUMBER_OF_GRIDS 64 +#define MAX_NUMBER_OF_CELLS 8 #define SIZE_OF_GRIDS 533.3333f #define MMAP_MAGIC 0x4d4d4150 // 'MMAP' diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 036621656..404305b78 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -751,11 +751,6 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) // if player is in world he can tell his friends about new achievement else if (GetPlayer()->IsInWorld()) { - CellCoord p = Acore::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); - - Cell cell(p); - cell.SetNoCreate(); - Acore::BroadcastTextBuilder _builder(GetPlayer(), CHAT_MSG_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, GetPlayer()->getGender(), GetPlayer(), achievement->ID); Acore::LocalizedPacketDo _localizer(_builder); Acore::PlayerDistWorker> _worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _localizer); diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 759d38fa1..c4ef53ae6 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -22,6 +22,7 @@ #include "MoveSplineInit.h" #include "ObjectMgr.h" #include "QueryResult.h" +#include "Timer.h" #include "WaypointMgr.h" FormationMgr::~FormationMgr() diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp index f82d42f87..dd781062e 100644 --- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp +++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp @@ -21,6 +21,7 @@ #include "Log.h" #include "ObjectMgr.h" #include "QueryResult.h" +#include "Timer.h" #include "Util.h" #include #include diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index fe37ea46c..f790f4297 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -3098,18 +3098,9 @@ void WorldObject::BuildUpdate(UpdateDataMapType& data_map, UpdatePlayerSet& play void WorldObject::GetCreaturesWithEntryInRange(std::list& creatureList, float radius, uint32 entry) { - CellCoord pair(Acore::ComputeCellCoord(this->GetPositionX(), this->GetPositionY())); - Cell cell(pair); - cell.SetNoCreate(); - Acore::AllCreaturesOfEntryInRange check(this, entry, radius); Acore::CreatureListSearcher searcher(this, creatureList, check); - - TypeContainerVisitor, WorldTypeMapContainer> world_visitor(searcher); - cell.Visit(pair, world_visitor, *(this->GetMap()), *this, radius); - - TypeContainerVisitor, GridTypeMapContainer> grid_visitor(searcher); - cell.Visit(pair, grid_visitor, *(this->GetMap()), *this, radius); + Cell::VisitAllObjects(this, searcher, radius); } void WorldObject::AddToObjectUpdate() diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 75fc9f9ee..2387b3b98 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -19,6 +19,7 @@ #define TRANSPORTS_H #include "GameObject.h" +#include "Timer.h" #include "TransportMgr.h" #include "VehicleDefines.h" #include "ZoneScript.h" diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f1fd08412..43b2568dc 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -20535,6 +20535,8 @@ void Unit::ExecuteDelayedUnitRelocationEvent() } } + GetMap()->LoadGridsInRange(*player, MAX_VISIBILITY_DISTANCE); + Acore::PlayerRelocationNotifier relocateNoLarge(*player, false); // visit only objects which are not large; default distance Cell::VisitAllObjects(viewPoint, relocateNoLarge, player->GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS); relocateNoLarge.SendToSelf(); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index aa39808ce..9b04949b1 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2341,8 +2341,8 @@ void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* { if (mask & 1) { - CellCoord cellCoord = Acore::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; + GridCoord gridCoord = Acore::ComputeGridCoord(data->posX, data->posY); + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][gridCoord.GetId()]; cell_guids.creatures.insert(guid); } } @@ -2355,8 +2355,8 @@ void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData co { if (mask & 1) { - CellCoord cellCoord = Acore::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; + GridCoord gridCoord = Acore::ComputeGridCoord(data->posX, data->posY); + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][gridCoord.GetId()]; cell_guids.creatures.erase(guid); } } @@ -2454,7 +2454,7 @@ uint32 ObjectMgr::AddCreData(uint32 entry, uint32 mapId, float x, float y, float AddCreatureToGrid(spawnId, &data); // Spawn if necessary (loaded grids only) - if (!map->Instanceable() && !map->IsRemovalGrid(x, y)) + if (!map->Instanceable() && !map->IsGridCreated(x, y)) { Creature* creature = new Creature(); if (!creature->LoadCreatureFromDB(spawnId, map, true, true)) @@ -2644,8 +2644,8 @@ void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData con { if (mask & 1) { - CellCoord cellCoord = Acore::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; + GridCoord gridCoord = Acore::ComputeGridCoord(data->posX, data->posY); + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][gridCoord.GetId()]; cell_guids.gameobjects.insert(guid); } } @@ -2658,8 +2658,8 @@ void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectDat { if (mask & 1) { - CellCoord cellCoord = Acore::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; + GridCoord gridCoord = Acore::ComputeGridCoord(data->posX, data->posY); + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][gridCoord.GetId()]; cell_guids.gameobjects.erase(guid); } } diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 3541637b9..3e1a15f8b 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1150,12 +1150,12 @@ public: return nullptr; } - CellObjectGuids const& GetCellObjectGuids(uint16 mapid, uint8 spawnMode, uint32 cell_id) + CellObjectGuids const& GetGridObjectGuids(uint16 mapid, uint8 spawnMode, uint32 gridId) { MapObjectGuids::const_iterator itr1 = _mapObjectGuidsStore.find(MAKE_PAIR32(mapid, spawnMode)); if (itr1 != _mapObjectGuidsStore.end()) { - CellObjectGuidsMap::const_iterator itr2 = itr1->second.find(cell_id); + CellObjectGuidsMap::const_iterator itr2 = itr1->second.find(gridId); if (itr2 != itr1->second.end()) return itr2->second; } diff --git a/src/server/game/Grids/Cells/Cell.h b/src/server/game/Grids/Cells/Cell.h index 86ce107b1..b3c5747a7 100644 --- a/src/server/game/Grids/Cells/Cell.h +++ b/src/server/game/Grids/Cells/Cell.h @@ -70,8 +70,6 @@ struct Cell [[nodiscard]] uint32 CellY() const { return data.Part.cell_y; } [[nodiscard]] uint32 GridX() const { return data.Part.grid_x; } [[nodiscard]] uint32 GridY() const { return data.Part.grid_y; } - [[nodiscard]] bool NoCreate() const { return data.Part.nocreate; } - void SetNoCreate() { data.Part.nocreate = 1; } [[nodiscard]] CellCoord GetCellCoord() const { @@ -92,12 +90,10 @@ struct Cell { struct { - unsigned grid_x : 6; - unsigned grid_y : 6; - unsigned cell_x : 6; - unsigned cell_y : 6; - unsigned nocreate : 1; - unsigned reserved : 7; + unsigned grid_x : 8; + unsigned grid_y : 8; + unsigned cell_x : 8; + unsigned cell_y : 8; } Part; uint32 All; } data; @@ -107,13 +103,13 @@ struct Cell static CellArea CalculateCellArea(float x, float y, float radius); - template static void VisitGridObjects(WorldObject const* obj, T& visitor, float radius, bool dont_load = true); - template static void VisitWorldObjects(WorldObject const* obj, T& visitor, float radius, bool dont_load = true); - template static void VisitAllObjects(WorldObject const* obj, T& visitor, float radius, bool dont_load = true); + template static void VisitGridObjects(WorldObject const* obj, T& visitor, float radius); + template static void VisitWorldObjects(WorldObject const* obj, T& visitor, float radius); + template static void VisitAllObjects(WorldObject const* obj, T& visitor, float radius); - template static void VisitGridObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load = true); - template static void VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load = true); - template static void VisitAllObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load = true); + template static void VisitGridObjects(float x, float y, Map* map, T& visitor, float radius); + template static void VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius); + template static void VisitAllObjects(float x, float y, Map* map, T& visitor, float radius); private: template void VisitCircle(TypeContainerVisitor&, Map&, CellCoord const&, CellCoord const&) const; diff --git a/src/server/game/Grids/Cells/CellImpl.h b/src/server/game/Grids/Cells/CellImpl.h index f8cf0ed08..ec6e6e93a 100644 --- a/src/server/game/Grids/Cells/CellImpl.h +++ b/src/server/game/Grids/Cells/CellImpl.h @@ -28,8 +28,6 @@ inline Cell::Cell(CellCoord const& p) data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; - data.Part.nocreate = 0; - data.Part.reserved = 0; } inline Cell::Cell(float x, float y) @@ -39,8 +37,6 @@ inline Cell::Cell(float x, float y) data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS; data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS; data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS; - data.Part.nocreate = 0; - data.Part.reserved = 0; } inline CellArea Cell::CalculateCellArea(float x, float y, float radius) @@ -66,7 +62,8 @@ inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor -inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor& visitor, Map& map, float x_off, float y_off, float radius) const{ +inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor& visitor, Map& map, float x_off, float y_off, float radius) const +{ if (!standing_cell.IsCoordValid()) return; @@ -101,23 +98,14 @@ inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitordata.Part.nocreate; - map.Visit(r_zone, visitor); - } + Cell r_zone(cellCoord); + map.Visit(r_zone, visitor); } } } @@ -138,7 +126,6 @@ inline void Cell::VisitCircle(TypeContainerVisitor& visitor, Map& { CellCoord cellCoord(x, y); Cell r_zone(cellCoord); - r_zone.data.Part.nocreate = this->data.Part.nocreate; map.Visit(r_zone, visitor); } } @@ -162,55 +149,41 @@ inline void Cell::VisitCircle(TypeContainerVisitor& visitor, Map& //e.g. filling 2 trapezoids after filling central cell strip... CellCoord cellCoord_left(x_start - step, y); Cell r_zone_left(cellCoord_left); - r_zone_left.data.Part.nocreate = this->data.Part.nocreate; map.Visit(r_zone_left, visitor); //right trapezoid cell visit CellCoord cellCoord_right(x_end + step, y); Cell r_zone_right(cellCoord_right); - r_zone_right.data.Part.nocreate = this->data.Part.nocreate; map.Visit(r_zone_right, visitor); } } } template -inline void Cell::VisitGridObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load /*= true*/) +inline void Cell::VisitGridObjects(WorldObject const* center_obj, T& visitor, float radius) { CellCoord p(Acore::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY())); Cell cell(p); - if (dont_load) - { - cell.SetNoCreate(); - } TypeContainerVisitor gnotifier(visitor); cell.Visit(p, gnotifier, *center_obj->GetMap(), *center_obj, radius); } template -inline void Cell::VisitWorldObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load /*= true*/) +inline void Cell::VisitWorldObjects(WorldObject const* center_obj, T& visitor, float radius) { CellCoord p(Acore::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY())); Cell cell(p); - if (dont_load) - { - cell.SetNoCreate(); - } TypeContainerVisitor wnotifier(visitor); cell.Visit(p, wnotifier, *center_obj->GetMap(), *center_obj, radius); } template -inline void Cell::VisitAllObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load /*= true*/) +inline void Cell::VisitAllObjects(WorldObject const* center_obj, T& visitor, float radius) { CellCoord p(Acore::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY())); Cell cell(p); - if (dont_load) - { - cell.SetNoCreate(); - } TypeContainerVisitor wnotifier(visitor); cell.Visit(p, wnotifier, *center_obj->GetMap(), *center_obj, radius); @@ -219,42 +192,30 @@ inline void Cell::VisitAllObjects(WorldObject const* center_obj, T& visitor, flo } template -inline void Cell::VisitGridObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load /*= true*/) +inline void Cell::VisitGridObjects(float x, float y, Map* map, T& visitor, float radius) { CellCoord p(Acore::ComputeCellCoord(x, y)); Cell cell(p); - if (dont_load) - { - cell.SetNoCreate(); - } TypeContainerVisitor gnotifier(visitor); cell.Visit(p, gnotifier, *map, x, y, radius); } template -inline void Cell::VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load /*= true*/) +inline void Cell::VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius) { CellCoord p(Acore::ComputeCellCoord(x, y)); Cell cell(p); - if (dont_load) - { - cell.SetNoCreate(); - } TypeContainerVisitor wnotifier(visitor); cell.Visit(p, wnotifier, *map, x, y, radius); } template -inline void Cell::VisitAllObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load /*= true*/) +inline void Cell::VisitAllObjects(float x, float y, Map* map, T& visitor, float radius) { CellCoord p(Acore::ComputeCellCoord(x, y)); Cell cell(p); - if (dont_load) - { - cell.SetNoCreate(); - } TypeContainerVisitor wnotifier(visitor); cell.Visit(p, wnotifier, *map, x, y, radius); diff --git a/src/server/game/Grids/Grid.h b/src/server/game/Grids/Grid.h deleted file mode 100644 index b9cafdbe0..000000000 --- a/src/server/game/Grids/Grid.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 . - */ - -#ifndef ACORE_GRID_H -#define ACORE_GRID_H - -/* - @class Grid - Grid is a logical segment of the game world represented inside TrinIty. - Grid is bind at compile time to a particular type of object which - we call it the object of interested. There are many types of loader, - specially, dynamic loader, static loader, or on-demand loader. There's - a subtle difference between dynamic loader and on-demand loader but - this is implementation specific to the loader class. From the - Grid's perspective, the loader meets its API requirement is suffice. -*/ - -#include "Define.h" -#include "TypeContainer.h" -#include "TypeContainerVisitor.h" - -// forward declaration -template class GridLoader; - -template -< - class ACTIVE_OBJECT, - class WORLD_OBJECT_TYPES, - class GRID_OBJECT_TYPES - > -class Grid -{ - // allows the GridLoader to access its internals - template friend class GridLoader; -public: - /** destructor to clean up its resources. This includes unloading the - grid if it has not been unload. - */ - ~Grid() = default; - - /** an object of interested enters the grid - */ - template void AddWorldObject(SPECIFIC_OBJECT* obj) - { - i_objects.template insert(obj); - ASSERT(obj->IsInGrid()); - } - - /** an object of interested exits the grid - */ - //Actually an unlink is enough, no need to go through the container - //template void RemoveWorldObject(SPECIFIC_OBJECT *obj) - //{ - // ASSERT(obj->GetGridRef().isValid()); - // i_objects.template remove(obj); - // ASSERT(!obj->GetGridRef().isValid()); - //} - - /** Refreshes/update the grid. This required for remote grids. - */ - //void RefreshGrid(void) { /* TBI */} - - /** Locks a grid. Any object enters must wait until the grid is unlock. - */ - //void LockGrid(void) { /* TBI */ } - - /** Unlocks the grid. - */ - //void UnlockGrid(void) { /* TBI */ } - - // Visit grid objects - template - void Visit(TypeContainerVisitor >& visitor) - { - visitor.Visit(i_container); - } - - // Visit world objects - template - void Visit(TypeContainerVisitor >& visitor) - { - visitor.Visit(i_objects); - } - - /** Inserts a container type object into the grid. - */ - template void AddGridObject(SPECIFIC_OBJECT* obj) - { - i_container.template insert(obj); - ASSERT(obj->IsInGrid()); - } - - /** Removes a containter type object from the grid - */ - //template void RemoveGridObject(SPECIFIC_OBJECT *obj) - //{ - // ASSERT(obj->GetGridRef().isValid()); - // i_container.template remove(obj); - // ASSERT(!obj->GetGridRef().isValid()); - //} - - /*bool NoWorldObjectInGrid() const - { - return i_objects.GetElements().IsEmpty(); - } - - bool NoGridObjectInGrid() const - { - return i_container.GetElements().IsEmpty(); - }*/ -private: - TypeMapContainer i_container; - TypeMapContainer i_objects; - //typedef std::set ActiveGridObjects; - //ActiveGridObjects m_activeGridObjects; -}; -#endif diff --git a/src/server/game/Grids/GridCell.h b/src/server/game/Grids/GridCell.h new file mode 100644 index 000000000..c0ccfdbba --- /dev/null +++ b/src/server/game/Grids/GridCell.h @@ -0,0 +1,75 @@ +/* + * 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 . + */ + +#ifndef ACORE_GRID_CELL_H +#define ACORE_GRID_CELL_H + +/* + @class GridCell + Grid is a logical segment of the game world represented inside TrinIty. + Grid is bind at compile time to a particular type of object which + we call it the object of interested. There are many types of loader, + specially, dynamic loader, static loader, or on-demand loader. There's + a subtle difference between dynamic loader and on-demand loader but + this is implementation specific to the loader class. From the + Grid's perspective, the loader meets its API requirement is suffice. +*/ + +#include "Define.h" +#include "TypeContainer.h" +#include "TypeContainerVisitor.h" + +template +< + class WORLD_OBJECT_TYPES, + class GRID_OBJECT_TYPES +> +class GridCell +{ +public: + ~GridCell() = default; + + template void AddWorldObject(SPECIFIC_OBJECT* obj) + { + _worldObjects.template insert(obj); + ASSERT(obj->IsInGrid()); + } + + template void AddGridObject(SPECIFIC_OBJECT* obj) + { + _gridObjects.template insert(obj); + ASSERT(obj->IsInGrid()); + } + + // Visit grid objects + template + void Visit(TypeContainerVisitor >& visitor) + { + visitor.Visit(_gridObjects); + } + + // Visit world objects + template + void Visit(TypeContainerVisitor >& visitor) + { + visitor.Visit(_worldObjects); + } +private: + TypeMapContainer _gridObjects; + TypeMapContainer _worldObjects; +}; +#endif diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h index 0e72af22e..62d1a6f50 100644 --- a/src/server/game/Grids/GridDefines.h +++ b/src/server/game/Grids/GridDefines.h @@ -20,7 +20,8 @@ #include "Common.h" #include "MapDefines.h" -#include "NGrid.h" +#include "GridCell.h" +#include "MapGrid.h" // Forward class definitions class Corpse; @@ -31,8 +32,6 @@ class Pet; class Player; class ObjectGuid; -#define MAX_NUMBER_OF_CELLS 8 - #define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2) #define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) @@ -73,8 +72,8 @@ enum GridMapTypeMask GRID_MAP_TYPE_MASK_ALL = 0x1F }; -typedef Grid GridType; -typedef NGrid NGridType; +typedef GridCell GridCellType; +typedef MapGrid MapGridType; typedef TypeMapContainer GridTypeMapContainer; typedef TypeMapContainer WorldTypeMapContainer; @@ -187,6 +186,13 @@ namespace Acore return Compute(x, y, CENTER_GRID_OFFSET, SIZE_OF_GRIDS); } + inline GridCoord ComputeGridCoordSimple(float x, float y) + { + int gx = (int)(CENTER_GRID_ID - x / SIZE_OF_GRIDS); + int gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS); + return GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy); + } + inline CellCoord ComputeCellCoord(float x, float y) { return Compute(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL); diff --git a/src/server/game/Grids/GridLoader.h b/src/server/game/Grids/GridLoader.h deleted file mode 100644 index 00081281c..000000000 --- a/src/server/game/Grids/GridLoader.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 . - */ - -#ifndef ACORE_GRIDLOADER_H -#define ACORE_GRIDLOADER_H - -/** - @class GridLoader - The GridLoader is working in conjuction with the Grid and responsible - for loading and unloading object-types (one or more) when objects - enters a grid. Unloading is scheduled and might be canceled if - an interested object re-enters. GridLoader does not do the actuall - loading and unloading but implements as a template pattern that - delicate its loading and unloading for the actualy loader and unloader. - GridLoader manages the grid (both local and remote). - */ - -//I cannot see why this cannot be replaced by a Grid::Visit -/* -#include "Define.h" -#include "Grid.h" -#include "TypeContainerVisitor.h" - -template -< -class ACTIVE_OBJECT, -class WORLD_OBJECT_TYPES, -class GRID_OBJECT_TYPES -> -class GridLoader -{ - public: - - // Loads the grid - template - void Load(Grid &grid, LOADER &loader) - { - grid.LockGrid(); - loader.Load(grid); - grid.UnlockGrid(); - } - - // Stop the grid - template - void Stop(Grid &grid, STOPER &stoper) - { - grid.LockGrid(); - stoper.Stop(grid); - grid.UnlockGrid(); - } - - // Unloads the grid - template - void Unload(Grid &grid, UNLOADER &unloader) - { - grid.LockGrid(); - unloader.Unload(grid); - grid.UnlockGrid(); - } -}; -*/ -#endif diff --git a/src/server/game/Grids/GridObjectLoader.cpp b/src/server/game/Grids/GridObjectLoader.cpp new file mode 100644 index 000000000..09550ab90 --- /dev/null +++ b/src/server/game/Grids/GridObjectLoader.cpp @@ -0,0 +1,138 @@ +/* + * 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 "GridObjectLoader.h" +#include "CellImpl.h" +#include "Corpse.h" +#include "Creature.h" +#include "DynamicObject.h" +#include "GameObject.h" +#include "GridNotifiers.h" +#include "Transport.h" + +template +void GridObjectLoader::AddObjectHelper(Map* map, T* obj) +{ + CellCoord cellCoord = Acore::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY()); + Cell cell(cellCoord); + + map->AddToGrid(obj, cell); + obj->AddToWorld(); + if (obj->isActiveObject()) + map->AddToActive(obj); +} + +void GridObjectLoader::LoadCreatures(CellGuidSet const& guid_set, Map* map) +{ + for (ObjectGuid::LowType const& guid : guid_set) + { + Creature* obj = new Creature(); + if (!obj->LoadFromDB(guid, map)) + { + delete obj; + continue; + } + + AddObjectHelper(map, obj); + + if (!obj->IsMoveInLineOfSightDisabled() && obj->GetDefaultMovementType() == IDLE_MOTION_TYPE && !obj->isNeedNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION)) + { + if (obj->IsAlive() && !obj->HasUnitState(UNIT_STATE_SIGHTLESS) && obj->HasReactState(REACT_AGGRESSIVE) && !obj->IsImmuneToNPC()) + { + // call MoveInLineOfSight for nearby grid creatures + Acore::AIRelocationNotifier notifier(*obj); + Cell::VisitGridObjects(obj, notifier, 60.f); + } + } + } +} + +void GridObjectLoader::LoadGameObjects(CellGuidSet const& guid_set, Map* map) +{ + for (ObjectGuid::LowType const& guid : guid_set) + { + GameObjectData const* data = sObjectMgr->GetGameObjectData(guid); + GameObject* obj = data && sObjectMgr->IsGameObjectStaticTransport(data->id) ? new StaticTransport() : new GameObject(); + + if (!obj->LoadFromDB(guid, map)) + { + delete obj; + continue; + } + + AddObjectHelper(map, obj); + } +} + +void GridObjectLoader::LoadAllCellsInGrid() +{ + CellObjectGuids const& cell_guids = sObjectMgr->GetGridObjectGuids(_map->GetId(), _map->GetSpawnMode(), _grid.GetId()); + LoadGameObjects(cell_guids.gameobjects, _map); + LoadCreatures(cell_guids.creatures, _map); + + if (std::unordered_set const* corpses = _map->GetCorpsesInCell(_grid.GetId())) + { + for (Corpse* corpse : *corpses) + { + if (corpse->IsInGrid()) + continue; + + CellCoord cellCoord = Acore::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY()); + Cell cell(cellCoord); + + if (corpse->IsWorldObject()) + _grid.AddWorldObject(cell.CellX(), cell.CellY(), corpse); + else + _grid.AddGridObject(cell.CellX(), cell.CellY(), corpse); + } + } +} + +template +void GridObjectUnloader::Visit(GridRefMgr& m) +{ + while (!m.IsEmpty()) + { + T* obj = m.getFirst()->GetSource(); + // if option set then object already saved at this moment + //if (!sWorld->getBoolConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) + // obj->SaveRespawnTime(); + //Some creatures may summon other temp summons in CleanupsBeforeDelete() + //So we need this even after cleaner (maybe we can remove cleaner) + //Example: Flame Leviathan Turret 33139 is summoned when a creature is deleted + //TODO: Check if that script has the correct logic. Do we really need to summons something before deleting? + obj->CleanupsBeforeDelete(); + ///- object will get delinked from the manager when deleted + delete obj; + } +} + +template +void GridObjectCleaner::Visit(GridRefMgr& m) +{ + for (typename GridRefMgr::iterator iter = m.begin(); iter != m.end(); ++iter) + iter->GetSource()->CleanupsBeforeDelete(); +} + +template void GridObjectUnloader::Visit(CreatureMapType&); +template void GridObjectUnloader::Visit(GameObjectMapType&); +template void GridObjectUnloader::Visit(DynamicObjectMapType&); + +template void GridObjectCleaner::Visit(CreatureMapType&); +template void GridObjectCleaner::Visit(GameObjectMapType&); +template void GridObjectCleaner::Visit(DynamicObjectMapType&); +template void GridObjectCleaner::Visit(CorpseMapType&); diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/GridObjectLoader.h similarity index 55% rename from src/server/game/Grids/ObjectGridLoader.h rename to src/server/game/Grids/GridObjectLoader.h index d6029ac7b..101f489bf 100644 --- a/src/server/game/Grids/ObjectGridLoader.h +++ b/src/server/game/Grids/GridObjectLoader.h @@ -15,51 +15,42 @@ * with this program. If not, see . */ -#ifndef ACORE_OBJECTGRIDLOADER_H -#define ACORE_OBJECTGRIDLOADER_H +#ifndef ACORE_GRID_OBJECT_LOADER_H +#define ACORE_GRID_OBJECT_LOADER_H #include "Cell.h" #include "Define.h" #include "GridDefines.h" +#include "ObjectMgr.h" -class ObjectWorldLoader; - -class ObjectGridLoader +class GridObjectLoader { - friend class ObjectWorldLoader; - public: - ObjectGridLoader(NGridType& grid, Map* map, const Cell& cell) - : i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses (0) - {} + GridObjectLoader(MapGridType& grid, Map* map) + : _grid(grid), _map(map) { } - void Visit(GameObjectMapType& m); - void Visit(CreatureMapType& m); - void Visit(CorpseMapType&) const {} - void Visit(DynamicObjectMapType&) const {} - - void LoadN(void); - - template static void SetObjectCell(T* obj, CellCoord const& cellCoord); + void LoadAllCellsInGrid(); private: - Cell i_cell; - NGridType& i_grid; - Map* i_map; - uint32 i_gameObjects; - uint32 i_creatures; - uint32 i_corpses; + template + void AddObjectHelper(Map* map, T* obj); + + void LoadCreatures(CellGuidSet const& guid_set, Map* map); + void LoadGameObjects(CellGuidSet const& guid_set, Map* map); + + MapGridType& _grid; + Map* _map; }; -//Clean up and remove from world -class ObjectGridCleaner +// Clean up and remove from world +class GridObjectCleaner { public: template void Visit(GridRefMgr&); }; -//Delete objects before deleting NGrid -class ObjectGridUnloader +// Delete objects before deleting NGrid +class GridObjectUnloader { public: void Visit(CorpseMapType&) { } // corpses are deleted with Map diff --git a/src/server/game/Grids/GridTerrainData.cpp b/src/server/game/Grids/GridTerrainData.cpp new file mode 100644 index 000000000..e2439dc2e --- /dev/null +++ b/src/server/game/Grids/GridTerrainData.cpp @@ -0,0 +1,617 @@ +#include "DBCStores.h" +#include "GridDefines.h" +#include "GridTerrainData.h" +#include "Log.h" +#include "MapDefines.h" +#include +#include + +uint16 const holetab_h[4] = { 0x1111, 0x2222, 0x4444, 0x8888 }; +uint16 const holetab_v[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 }; + +GridTerrainData::GridTerrainData() +{ + _gridGetHeight = &GridTerrainData::getHeightFromFlat; +} + +TerrainMapDataReadResult GridTerrainData::Load(std::string const& mapFileName) +{ + // Check if file exists, we do this first as we need to + // differentiate between file existing and any other file errors + if (!std::filesystem::exists(mapFileName)) + return TerrainMapDataReadResult::NotFound; + + // Start the input stream and check for any errors + std::ifstream fileStream(mapFileName, std::ios::binary); + if (fileStream.fail()) + return TerrainMapDataReadResult::ReadError; + + // Read the map header + map_fileheader header; + if (!fileStream.read(reinterpret_cast(&header), sizeof(header))) + return TerrainMapDataReadResult::ReadError; + + // Check for valid map and version magics + if (header.mapMagic != MapMagic.asUInt || header.versionMagic != MapVersionMagic) + return TerrainMapDataReadResult::InvalidMagic; + + // Load area data + if (header.areaMapOffset && !LoadAreaData(fileStream, header.areaMapOffset)) + return TerrainMapDataReadResult::InvalidAreaData; + + // Load height data + if (header.heightMapOffset && !LoadHeightData(fileStream, header.heightMapOffset)) + return TerrainMapDataReadResult::InvalidHeightData; + + // Load liquid data + if (header.liquidMapOffset && !LoadLiquidData(fileStream, header.liquidMapOffset)) + return TerrainMapDataReadResult::InvalidLiquidData; + + // Load hole data + if (header.holesSize && !LoadHolesData(fileStream, header.holesOffset)) + return TerrainMapDataReadResult::InvalidHoleData; + + return TerrainMapDataReadResult::Success; +} + +bool GridTerrainData::LoadAreaData(std::ifstream& fileStream, uint32 const offset) +{ + fileStream.seekg(offset); + + map_areaHeader header; + if (!fileStream.read(reinterpret_cast(&header), sizeof(header)) || header.fourcc != MapAreaMagic.asUInt) + return false; + + _loadedAreaData = std::make_unique(); + _loadedAreaData->gridArea = header.gridArea; + if (!(header.flags & MAP_AREA_NO_AREA)) + { + _loadedAreaData->areaMap = std::make_unique(); + if (!fileStream.read(reinterpret_cast(_loadedAreaData->areaMap.get()), sizeof(LoadedAreaData::AreaMapType))) + return false; + } + return true; +} + +bool GridTerrainData::LoadHeightData(std::ifstream& fileStream, uint32 const offset) +{ + fileStream.seekg(offset); + + map_heightHeader header; + if (!fileStream.read(reinterpret_cast(&header), sizeof(header)) || header.fourcc != MapHeightMagic.asUInt) + return false; + + _loadedHeightData = std::make_unique(); + _loadedHeightData->gridHeight = header.gridHeight; + if (!(header.flags & MAP_HEIGHT_NO_HEIGHT)) + { + if ((header.flags & MAP_HEIGHT_AS_INT16)) + { + _loadedHeightData->uint16HeightData = std::make_unique(); + if (!fileStream.read(reinterpret_cast(&_loadedHeightData->uint16HeightData->v9), sizeof(_loadedHeightData->uint16HeightData->v9)) + || !fileStream.read(reinterpret_cast(&_loadedHeightData->uint16HeightData->v8), sizeof(_loadedHeightData->uint16HeightData->v8))) + return false; + + _loadedHeightData->uint16HeightData->gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; + _gridGetHeight = &GridTerrainData::getHeightFromUint16; + } + else if ((header.flags & MAP_HEIGHT_AS_INT8)) + { + _loadedHeightData->uint8HeightData = std::make_unique(); + if (!fileStream.read(reinterpret_cast(&_loadedHeightData->uint8HeightData->v9), sizeof(_loadedHeightData->uint8HeightData->v9)) + || !fileStream.read(reinterpret_cast(&_loadedHeightData->uint8HeightData->v8), sizeof(_loadedHeightData->uint8HeightData->v8))) + return false; + + _loadedHeightData->uint8HeightData->gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255; + _gridGetHeight = &GridTerrainData::getHeightFromUint8; + } + else + { + _loadedHeightData->floatHeightData = std::make_unique(); + if (!fileStream.read(reinterpret_cast(&_loadedHeightData->floatHeightData->v9), sizeof(_loadedHeightData->floatHeightData->v9)) + || !fileStream.read(reinterpret_cast(&_loadedHeightData->floatHeightData->v8), sizeof(_loadedHeightData->floatHeightData->v8))) + return false; + + _gridGetHeight = &GridTerrainData::getHeightFromFloat; + } + } + else + _gridGetHeight = &GridTerrainData::getHeightFromFlat; + + if (header.flags & MAP_HEIGHT_HAS_FLIGHT_BOUNDS) + { + std::array maxHeights; + std::array minHeights; + if (!fileStream.read(reinterpret_cast(maxHeights.data()), sizeof(maxHeights)) || + !fileStream.read(reinterpret_cast(minHeights.data()), sizeof(minHeights))) + return false; + + static uint32 constexpr indices[8][3] = + { + { 3, 0, 4 }, + { 0, 1, 4 }, + { 1, 2, 4 }, + { 2, 5, 4 }, + { 5, 8, 4 }, + { 8, 7, 4 }, + { 7, 6, 4 }, + { 6, 3, 4 } + }; + + static float constexpr boundGridCoords[9][2] = + { + { 0.0f, 0.0f }, + { 0.0f, -266.66666f }, + { 0.0f, -533.33331f }, + { -266.66666f, 0.0f }, + { -266.66666f, -266.66666f }, + { -266.66666f, -533.33331f }, + { -533.33331f, 0.0f }, + { -533.33331f, -266.66666f }, + { -533.33331f, -533.33331f } + }; + + _loadedHeightData->minHeightPlanes = std::make_unique(); + for (uint32 quarterIndex = 0; quarterIndex < _loadedHeightData->minHeightPlanes->size(); ++quarterIndex) + _loadedHeightData->minHeightPlanes->at(quarterIndex) = G3D::Plane( + G3D::Vector3(boundGridCoords[indices[quarterIndex][0]][0], boundGridCoords[indices[quarterIndex][0]][1], minHeights[indices[quarterIndex][0]]), + G3D::Vector3(boundGridCoords[indices[quarterIndex][1]][0], boundGridCoords[indices[quarterIndex][1]][1], minHeights[indices[quarterIndex][1]]), + G3D::Vector3(boundGridCoords[indices[quarterIndex][2]][0], boundGridCoords[indices[quarterIndex][2]][1], minHeights[indices[quarterIndex][2]]) + ); + } + + return true; +} + +bool GridTerrainData::LoadLiquidData(std::ifstream& fileStream, uint32 const offset) +{ + fileStream.seekg(offset); + + map_liquidHeader header; + if (!fileStream.read(reinterpret_cast(&header), sizeof(header)) || header.fourcc != MapLiquidMagic.asUInt) + return false; + + _loadedLiquidData = std::make_unique(); + _loadedLiquidData->liquidGlobalEntry = header.liquidType; + _loadedLiquidData->liquidGlobalFlags = header.liquidFlags; + _loadedLiquidData->liquidOffX = header.offsetX; + _loadedLiquidData->liquidOffY = header.offsetY; + _loadedLiquidData->liquidWidth = header.width; + _loadedLiquidData->liquidHeight = header.height; + _loadedLiquidData->liquidLevel = header.liquidLevel; + + if (!(header.flags & MAP_LIQUID_NO_TYPE)) + { + _loadedLiquidData->liquidEntry = std::make_unique(); + if (!fileStream.read(reinterpret_cast(_loadedLiquidData->liquidEntry.get()), sizeof(LoadedLiquidData::LiquidEntryType))) + return false; + + _loadedLiquidData->liquidFlags = std::make_unique(); + if (!fileStream.read(reinterpret_cast(_loadedLiquidData->liquidFlags.get()), sizeof(LoadedLiquidData::LiquidFlagsType))) + return false; + } + if (!(header.flags & MAP_LIQUID_NO_HEIGHT)) + { + _loadedLiquidData->liquidMap = std::make_unique(); + _loadedLiquidData->liquidMap->resize(_loadedLiquidData->liquidWidth * _loadedLiquidData->liquidHeight); + if (!fileStream.read(reinterpret_cast(_loadedLiquidData->liquidMap->data()), _loadedLiquidData->liquidMap->size() * sizeof(float))) + return false; + } + return true; +} + +bool GridTerrainData::LoadHolesData(std::ifstream& fileStream, uint32 const offset) +{ + fileStream.seekg(offset); + + _loadedHoleData = std::make_unique(); + if (!fileStream.read(reinterpret_cast(&_loadedHoleData->holes), sizeof(_loadedHoleData->holes))) + return false; + + return true; +} + +uint16 GridTerrainData::getArea(float x, float y) const +{ + if (!_loadedAreaData) + return 0; + + if (!_loadedAreaData->areaMap) + return _loadedAreaData->gridArea; + + x = 16 * (32 - x / SIZE_OF_GRIDS); + y = 16 * (32 - y / SIZE_OF_GRIDS); + int lx = (int)x & 15; + int ly = (int)y & 15; + return _loadedAreaData->areaMap->at(lx * 16 + ly); +} + +float GridTerrainData::getHeightFromFlat(float /*x*/, float /*y*/) const +{ + if (!_loadedHeightData) + return INVALID_HEIGHT; + + return _loadedHeightData->gridHeight; +} + +float GridTerrainData::getHeightFromFloat(float x, float y) const +{ + if (!_loadedHeightData || !_loadedHeightData->floatHeightData) + return INVALID_HEIGHT; + + x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int &= (MAP_RESOLUTION - 1); + y_int &= (MAP_RESOLUTION - 1); + + if (isHole(x_int, y_int)) + return INVALID_HEIGHT; + + // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid + // +--------------> X + // | h1-------h2 Coordinates is: + // | | \ 1 / | h1 0, 0 + // | | \ / | h2 0, 1 + // | | 2 h5 3 | h3 1, 0 + // | | / \ | h4 1, 1 + // | | / 4 \ | h5 1/2, 1/2 + // | h3-------h4 + // V Y + // For find height need + // 1 - detect triangle + // 2 - solve linear equation from triangle points + // Calculate coefficients for solve h = a*x + b*y + c + + float a, b, c; + // Select triangle: + if (x + y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + float h1 = _loadedHeightData->floatHeightData->v9[(x_int) * 129 + y_int]; + float h2 = _loadedHeightData->floatHeightData->v9[(x_int + 1) * 129 + y_int]; + float h5 = 2 * _loadedHeightData->floatHeightData->v8[x_int * 128 + y_int]; + a = h2 - h1; + b = h5 - h1 - h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + float h1 = _loadedHeightData->floatHeightData->v9[x_int * 129 + y_int]; + float h3 = _loadedHeightData->floatHeightData->v9[x_int * 129 + y_int + 1]; + float h5 = 2 * _loadedHeightData->floatHeightData->v8[x_int * 128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + float h2 = _loadedHeightData->floatHeightData->v9[(x_int + 1) * 129 + y_int]; + float h4 = _loadedHeightData->floatHeightData->v9[(x_int + 1) * 129 + y_int + 1]; + float h5 = 2 * _loadedHeightData->floatHeightData->v8[x_int * 128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + float h3 = _loadedHeightData->floatHeightData->v9[(x_int) * 129 + y_int + 1]; + float h4 = _loadedHeightData->floatHeightData->v9[(x_int + 1) * 129 + y_int + 1]; + float h5 = 2 * _loadedHeightData->floatHeightData->v8[x_int * 128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return a * x + b * y + c; +} + +float GridTerrainData::getHeightFromUint8(float x, float y) const +{ + if (!_loadedHeightData || !_loadedHeightData->uint8HeightData) + return INVALID_HEIGHT; + + x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int &= (MAP_RESOLUTION - 1); + y_int &= (MAP_RESOLUTION - 1); + + if (isHole(x_int, y_int)) + return INVALID_HEIGHT; + + int32 a, b, c; + uint8* V9_h1_ptr = &_loadedHeightData->uint8HeightData->v9[x_int * 128 + x_int + y_int]; + if (x + y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h2 = V9_h1_ptr[129]; + int32 h5 = 2 * _loadedHeightData->uint8HeightData->v8[x_int * 128 + y_int]; + a = h2 - h1; + b = h5 - h1 - h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h3 = V9_h1_ptr[1]; + int32 h5 = 2 * _loadedHeightData->uint8HeightData->v8[x_int * 128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + int32 h2 = V9_h1_ptr[129]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * _loadedHeightData->uint8HeightData->v8[x_int * 128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + int32 h3 = V9_h1_ptr[1]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * _loadedHeightData->uint8HeightData->v8[x_int * 128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return (float)((a * x) + (b * y) + c) * _loadedHeightData->uint8HeightData->gridIntHeightMultiplier + _loadedHeightData->gridHeight; +} + +float GridTerrainData::getHeightFromUint16(float x, float y) const +{ + if (!_loadedHeightData || !_loadedHeightData->uint16HeightData) + return INVALID_HEIGHT; + + x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); + + int x_int = (int)x; + int y_int = (int)y; + x -= x_int; + y -= y_int; + x_int &= (MAP_RESOLUTION - 1); + y_int &= (MAP_RESOLUTION - 1); + + if (isHole(x_int, y_int)) + return INVALID_HEIGHT; + + int32 a, b, c; + uint16* V9_h1_ptr = &_loadedHeightData->uint16HeightData->v9[x_int * 128 + x_int + y_int]; + if (x + y < 1) + { + if (x > y) + { + // 1 triangle (h1, h2, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h2 = V9_h1_ptr[129]; + int32 h5 = 2 * _loadedHeightData->uint16HeightData->v8[x_int * 128 + y_int]; + a = h2 - h1; + b = h5 - h1 - h2; + c = h1; + } + else + { + // 2 triangle (h1, h3, h5 points) + int32 h1 = V9_h1_ptr[0]; + int32 h3 = V9_h1_ptr[1]; + int32 h5 = 2 * _loadedHeightData->uint16HeightData->v8[x_int * 128 + y_int]; + a = h5 - h1 - h3; + b = h3 - h1; + c = h1; + } + } + else + { + if (x > y) + { + // 3 triangle (h2, h4, h5 points) + int32 h2 = V9_h1_ptr[129]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * _loadedHeightData->uint16HeightData->v8[x_int * 128 + y_int]; + a = h2 + h4 - h5; + b = h4 - h2; + c = h5 - h4; + } + else + { + // 4 triangle (h3, h4, h5 points) + int32 h3 = V9_h1_ptr[1]; + int32 h4 = V9_h1_ptr[130]; + int32 h5 = 2 * _loadedHeightData->uint16HeightData->v8[x_int * 128 + y_int]; + a = h4 - h3; + b = h3 + h4 - h5; + c = h5 - h4; + } + } + // Calculate height + return (float)((a * x) + (b * y) + c) * _loadedHeightData->uint16HeightData->gridIntHeightMultiplier + _loadedHeightData->gridHeight; +} + +bool GridTerrainData::isHole(int row, int col) const +{ + if (!_loadedHoleData) + return false; + + int cellRow = row / 8; // 8 squares per cell + int cellCol = col / 8; + int holeRow = row % 8 / 2; + int holeCol = (col - (cellCol * 8)) / 2; + + uint16 hole = _loadedHoleData->holes[cellRow * 16 + cellCol]; + + return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0; +} + +float GridTerrainData::getMinHeight(float x, float y) const +{ + if (!_loadedHeightData || !_loadedHeightData->minHeightPlanes) + return MIN_HEIGHT; + + GridCoord gridCoord = Acore::ComputeGridCoordSimple(x, y); + + int32 doubleGridX = int32(std::floor(-(x - MAP_HALFSIZE) / CENTER_GRID_OFFSET)); + int32 doubleGridY = int32(std::floor(-(y - MAP_HALFSIZE) / CENTER_GRID_OFFSET)); + + float gx = x - (int32(gridCoord.x_coord) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS; + float gy = y - (int32(gridCoord.y_coord) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS; + + uint32 quarterIndex = 0; + if (doubleGridY & 1) + { + if (doubleGridX & 1) + quarterIndex = 4 + (gx <= gy); + else + quarterIndex = 2 + ((-SIZE_OF_GRIDS - gx) > gy); + } + else if (doubleGridX & 1) + quarterIndex = 6 + ((-SIZE_OF_GRIDS - gx) <= gy); + else + quarterIndex = gx > gy; + + G3D::Ray ray = G3D::Ray::fromOriginAndDirection(G3D::Vector3(gx, gy, 0.0f), G3D::Vector3::unitZ()); + return ray.intersection(_loadedHeightData->minHeightPlanes->at(quarterIndex)).z; +} + +float GridTerrainData::getLiquidLevel(float x, float y) const +{ + if (!_loadedLiquidData) + return INVALID_HEIGHT; + + if (!_loadedLiquidData->liquidMap) + return _loadedLiquidData->liquidLevel; + + x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); + y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); + + int cx_int = ((int)x & (MAP_RESOLUTION - 1)) - _loadedLiquidData->liquidOffY; + int cy_int = ((int)y & (MAP_RESOLUTION - 1)) - _loadedLiquidData->liquidOffX; + + if (cx_int < 0 || cx_int >= _loadedLiquidData->liquidHeight) + return INVALID_HEIGHT; + if (cy_int < 0 || cy_int >= _loadedLiquidData->liquidWidth) + return INVALID_HEIGHT; + + return _loadedLiquidData->liquidMap->at(cx_int * _loadedLiquidData->liquidWidth + cy_int); +} + +// Get water state on map +LiquidData const GridTerrainData::GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const +{ + LiquidData liquidData; + if (!_loadedLiquidData) + return liquidData; + + // Check water type (if no water return) + if (_loadedLiquidData->liquidGlobalFlags || _loadedLiquidData->liquidFlags) + { + // Get cell + float cx = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); + float cy = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); + + int x_int = (int)cx & (MAP_RESOLUTION - 1); + int y_int = (int)cy & (MAP_RESOLUTION - 1); + + // Check water type in cell + int idx = (x_int >> 3) * 16 + (y_int >> 3); + uint8 type = _loadedLiquidData->liquidFlags ? _loadedLiquidData->liquidFlags->at(idx) : _loadedLiquidData->liquidGlobalFlags; + uint32 entry = _loadedLiquidData->liquidEntry ? _loadedLiquidData->liquidEntry->at(idx) : _loadedLiquidData->liquidGlobalEntry; + if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(entry)) + { + type &= MAP_LIQUID_TYPE_DARK_WATER; + uint32 liqTypeIdx = liquidEntry->Type; + if (entry < 21) + { + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y))) + { + uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; + if (!overrideLiquid && area->zone) + { + area = sAreaTableStore.LookupEntry(area->zone); + if (area) + overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; + } + + if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid)) + { + entry = overrideLiquid; + liqTypeIdx = liq->Type; + } + } + } + + type |= 1 << liqTypeIdx; + } + + // Check req liquid type mask + if (type != 0 && (!ReqLiquidType || (ReqLiquidType & type) != 0)) + { + // Check water level: + // Check water height map + int lx_int = x_int - _loadedLiquidData->liquidOffY; + int ly_int = y_int - _loadedLiquidData->liquidOffX; + if (lx_int >= 0 && lx_int < _loadedLiquidData->liquidHeight && ly_int >= 0 && ly_int < _loadedLiquidData->liquidWidth) + { + // Get water level + float liquid_level = _loadedLiquidData->liquidMap ? _loadedLiquidData->liquidMap->at(lx_int * _loadedLiquidData->liquidWidth + ly_int) : _loadedLiquidData->liquidLevel; + // Get ground level + float ground_level = getHeight(x, y); + + // Check water level and ground level (sub 0.2 for fix some errors) + if (liquid_level >= ground_level && z >= ground_level - 0.2f) + { + // All ok in water -> store data + liquidData.Entry = entry; + liquidData.Flags = type; + liquidData.Level = liquid_level; + liquidData.DepthLevel = ground_level; + + // For speed check as int values + float delta = liquid_level - z; + + if (delta > collisionHeight) + liquidData.Status = LIQUID_MAP_UNDER_WATER; + else if (delta > 0.0f) + liquidData.Status = LIQUID_MAP_IN_WATER; + else if (delta > -0.1f) + liquidData.Status = LIQUID_MAP_WATER_WALK; + else + liquidData.Status = LIQUID_MAP_ABOVE_WATER; + } + } + } + } + + return liquidData; +} diff --git a/src/server/game/Grids/GridTerrainData.h b/src/server/game/Grids/GridTerrainData.h new file mode 100644 index 000000000..6d6b89825 --- /dev/null +++ b/src/server/game/Grids/GridTerrainData.h @@ -0,0 +1,255 @@ +/* + * 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 . + */ + +#ifndef GRID_TERRAIN_DATA_H +#define GRID_TERRAIN_DATA_H + +#include "Common.h" +#include +#include +#include + +#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface +#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE +#define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT +#define MIN_HEIGHT -500.0f + +#define MAP_LIQUID_STATUS_SWIMMING (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER) +#define MAP_LIQUID_STATUS_IN_CONTACT (MAP_LIQUID_STATUS_SWIMMING | LIQUID_MAP_WATER_WALK) + +#define MAP_LIQUID_TYPE_NO_WATER 0x00 +#define MAP_LIQUID_TYPE_WATER 0x01 +#define MAP_LIQUID_TYPE_OCEAN 0x02 +#define MAP_LIQUID_TYPE_MAGMA 0x04 +#define MAP_LIQUID_TYPE_SLIME 0x08 + +#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME) + +#define MAP_LIQUID_TYPE_DARK_WATER 0x10 + +// ****************************************** +// Map file format defines +// ****************************************** +union u_map_magic +{ + char asChar[4]; + uint32 asUInt; +}; + +const u_map_magic MapMagic = { {'M', 'A', 'P', 'S'} }; +const uint32 MapVersionMagic = 9; +const u_map_magic MapAreaMagic = { {'A', 'R', 'E', 'A'} }; +const u_map_magic MapHeightMagic = { {'M', 'H', 'G', 'T'} }; +const u_map_magic MapLiquidMagic = { {'M', 'L', 'I', 'Q'} }; + +struct map_fileheader +{ + uint32 mapMagic; + uint32 versionMagic; + uint32 buildMagic; + uint32 areaMapOffset; + uint32 areaMapSize; + uint32 heightMapOffset; + uint32 heightMapSize; + uint32 liquidMapOffset; + uint32 liquidMapSize; + uint32 holesOffset; + uint32 holesSize; +}; + +#define MAP_AREA_NO_AREA 0x0001 + +struct map_areaHeader +{ + uint32 fourcc; + uint16 flags; + uint16 gridArea; +}; + +#define MAP_HEIGHT_NO_HEIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 +#define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008 + +struct map_heightHeader +{ + uint32 fourcc; + uint32 flags; + float gridHeight; + float gridMaxHeight; +}; + +#define MAP_LIQUID_NO_TYPE 0x0001 +#define MAP_LIQUID_NO_HEIGHT 0x0002 + +struct map_liquidHeader +{ + uint32 fourcc; + uint8 flags; + uint8 liquidFlags; + uint16 liquidType; + uint8 offsetX; + uint8 offsetY; + uint8 width; + uint8 height; + float liquidLevel; +}; + +// ****************************************** +// Loaded map data structures +// ****************************************** + +struct LoadedAreaData +{ + typedef std::array AreaMapType; + + uint16 gridArea; + std::unique_ptr areaMap; +}; + +struct LoadedHeightData +{ + typedef std::array HeightPlanesType; + + struct Uint16HeightData + { + typedef std::array V9Type; + typedef std::array V8Type; + + V9Type v9; + V8Type v8; + float gridIntHeightMultiplier; + }; + + struct Uint8HeightData + { + typedef std::array V9Type; + typedef std::array V8Type; + + V9Type v9; + V8Type v8; + float gridIntHeightMultiplier; + }; + + struct FloatHeightData + { + typedef std::array V9Type; + typedef std::array V8Type; + + V9Type v9; + V8Type v8; + }; + + float gridHeight; + std::unique_ptr uint16HeightData; + std::unique_ptr uint8HeightData; + std::unique_ptr floatHeightData; + std::unique_ptr minHeightPlanes; +}; + +struct LoadedLiquidData +{ + typedef std::array LiquidEntryType; + typedef std::array LiquidFlagsType; + typedef std::vector LiquidMapType; + + uint16 liquidGlobalEntry; + uint8 liquidGlobalFlags; + uint8 liquidOffX; + uint8 liquidOffY; + uint8 liquidWidth; + uint8 liquidHeight; + float liquidLevel; + std::unique_ptr liquidEntry; + std::unique_ptr liquidFlags; + std::unique_ptr liquidMap; +}; + +struct LoadedHoleData +{ + typedef std::array HolesType; + + HolesType holes; +}; + +enum LiquidStatus +{ + LIQUID_MAP_NO_WATER = 0x00000000, + LIQUID_MAP_ABOVE_WATER = 0x00000001, + LIQUID_MAP_WATER_WALK = 0x00000002, + LIQUID_MAP_IN_WATER = 0x00000004, + LIQUID_MAP_UNDER_WATER = 0x00000008 +}; + +struct LiquidData +{ + LiquidData() = default; + + uint32 Entry{ 0 }; + uint32 Flags{ 0 }; + float Level{ INVALID_HEIGHT }; + float DepthLevel{ INVALID_HEIGHT }; + LiquidStatus Status{ LIQUID_MAP_NO_WATER }; +}; + +enum class TerrainMapDataReadResult +{ + Success, + NotFound, + ReadError, + InvalidMagic, + InvalidAreaData, + InvalidHeightData, + InvalidLiquidData, + InvalidHoleData +}; + +class GridTerrainData +{ + bool LoadAreaData(std::ifstream& fileStream, uint32 const offset); + bool LoadHeightData(std::ifstream& fileStream, uint32 const offset); + bool LoadLiquidData(std::ifstream& fileStream, uint32 const offset); + bool LoadHolesData(std::ifstream& fileStream, uint32 const offset); + + std::unique_ptr _loadedAreaData; + std::unique_ptr _loadedHeightData; + std::unique_ptr _loadedLiquidData; + std::unique_ptr _loadedHoleData; + + bool isHole(int row, int col) const; + + // Get height functions and pointers + typedef float (GridTerrainData::* GetHeightPtr) (float x, float y) const; + GetHeightPtr _gridGetHeight; + float getHeightFromFloat(float x, float y) const; + float getHeightFromUint16(float x, float y) const; + float getHeightFromUint8(float x, float y) const; + float getHeightFromFlat(float x, float y) const; + +public: + GridTerrainData(); + ~GridTerrainData() { }; + TerrainMapDataReadResult Load(std::string const& mapFileName); + + uint16 getArea(float x, float y) const; + inline float getHeight(float x, float y) const { return (this->*_gridGetHeight)(x, y); } + float getMinHeight(float x, float y) const; + float getLiquidLevel(float x, float y) const; + LiquidData const GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const; +}; + +#endif diff --git a/src/server/game/Grids/GridTerrainLoader.cpp b/src/server/game/Grids/GridTerrainLoader.cpp new file mode 100644 index 000000000..b82c3b544 --- /dev/null +++ b/src/server/game/Grids/GridTerrainLoader.cpp @@ -0,0 +1,160 @@ +#include "DisableMgr.h" +#include "GridTerrainLoader.h" +#include "MMapFactory.h" +#include "MMapMgr.h" +#include "ScriptMgr.h" +#include "VMapFactory.h" +#include "VMapMgr2.h" + +void GridTerrainLoader::LoadTerrain() +{ + LoadMap(); + if (_map->GetInstanceId() == 0) + { + LoadVMap(); + LoadMMap(); + } +} + +void GridTerrainLoader::LoadMap() +{ + // Instances will point to the parent maps terrain data + if (_map->GetInstanceId() != 0) + { + // load grid map for base map + Map* parentMap = const_cast(_map->GetParent()); + + // GetGridTerrainData will create the parent map grid + _grid.SetTerrainData(parentMap->GetGridTerrainDataSharedPtr(GridCoord(_grid.GetX(), _grid.GetY()))); + return; + } + + // map file name + std::string const mapFileName = Acore::StringFormat("{}maps/{:03}{:02}{:02}.map", sWorld->GetDataPath(), _map->GetId(), GetX(), GetY()); + + // loading data + LOG_DEBUG("maps", "Loading map {}", mapFileName); + std::unique_ptr terrainData = std::make_unique(); + TerrainMapDataReadResult loadResult = terrainData->Load(mapFileName); + if (loadResult == TerrainMapDataReadResult::Success) + _grid.SetTerrainData(std::move(terrainData)); + else + { + if (loadResult == TerrainMapDataReadResult::InvalidMagic) + LOG_ERROR("maps", "Map file '{}' is from an incompatible clientversion. Please recreate using the mapextractor.", mapFileName); + else + LOG_DEBUG("maps", "Error (result: {}) loading map file: {}", uint32(loadResult), mapFileName); + } + + sScriptMgr->OnLoadGridMap(_map, _grid.GetTerrainData(), GetX(), GetY()); +} + +void GridTerrainLoader::LoadVMap() +{ + int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapMgr()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), _map->GetId(), GetX(), GetY()); + switch (vmapLoadResult) + { + case VMAP::VMAP_LOAD_RESULT_OK: + LOG_DEBUG("maps", "VMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", + _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + break; + case VMAP::VMAP_LOAD_RESULT_ERROR: + LOG_DEBUG("maps", "Could not load VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", + _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + break; + case VMAP::VMAP_LOAD_RESULT_IGNORED: + LOG_DEBUG("maps", "Ignored VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", + _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + break; + } +} + +void GridTerrainLoader::LoadMMap() +{ + if (!DisableMgr::IsPathfindingEnabled(_map)) + return; + + int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(_map->GetId(), GetX(), GetY()); + switch (mmapLoadResult) + { + case MMAP::MMAP_LOAD_RESULT_OK: + LOG_DEBUG("maps", "MMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", + _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + break; + case MMAP::MMAP_LOAD_RESULT_ERROR: + LOG_DEBUG("maps", "Could not load MMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", + _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + break; + case MMAP::MMAP_LOAD_RESULT_IGNORED: + LOG_DEBUG("maps", "Ignored MMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", + _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + break; + } +} + +bool GridTerrainLoader::ExistMap(uint32 mapid, int gx, int gy) +{ + std::string const mapFileName = Acore::StringFormat("{}maps/{:03}{:02}{:02}.map", sWorld->GetDataPath(), mapid, gx, gy); + std::ifstream fileStream(mapFileName, std::ios::binary); + if (fileStream.fail()) + { + LOG_DEBUG("maps", "Map file '{}': error opening file", mapFileName); + return false; + } + + map_fileheader header; + if (!fileStream.read(reinterpret_cast(&header), sizeof(header))) + { + LOG_DEBUG("maps", "Map file '{}': unable to read header", mapFileName); + return false; + } + + if (header.mapMagic != MapMagic.asUInt || header.versionMagic != MapVersionMagic) + { + LOG_ERROR("maps", "Map file '{}' is from an incompatible map version ({:.4u} v{}), {:.4s} v{} is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files.", + mapFileName, 4, header.mapMagic, header.versionMagic, 4, MapMagic.asChar, MapVersionMagic); + return false; + } + + return true; +} + +bool GridTerrainLoader::ExistVMap(uint32 mapid, int gx, int gy) +{ + if (VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr()) + { + if (vmgr->isMapLoadingEnabled()) + { + VMAP::LoadResult result = vmgr->existsMap((sWorld->GetDataPath() + "vmaps").c_str(), mapid, gx, gy); + std::string name = vmgr->getDirFileName(mapid, gx, gy); + switch (result) + { + case VMAP::LoadResult::Success: + break; + case VMAP::LoadResult::FileNotFound: + LOG_DEBUG("maps", "VMap file '{}' does not exist", (sWorld->GetDataPath() + "vmaps/" + name)); + LOG_DEBUG("maps", "Please place VMAP files (*.vmtree and *.vmtile) in the vmap directory ({}), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath() + "vmaps/")); + return false; + case VMAP::LoadResult::VersionMismatch: + LOG_ERROR("maps", "VMap file '{}' couldn't be loaded", (sWorld->GetDataPath() + "vmaps/" + name)); + LOG_ERROR("maps", "This is because the version of the VMap file and the version of this module are different, please re-extract the maps with the tools compiled with this module."); + return false; + } + } + } + + return true; +} + +void GridTerrainUnloader::UnloadTerrain() +{ + // Only parent maps manage terrain data + if (_map->GetInstanceId() != 0) + return; + + int gx = (MAX_NUMBER_OF_GRIDS - 1) - _grid.GetX(); + int gy = (MAX_NUMBER_OF_GRIDS - 1) - _grid.GetY(); + + VMAP::VMapFactory::createOrGetVMapMgr()->unloadMap(_map->GetId(), gx, gy); + MMAP::MMapFactory::createOrGetMMapMgr()->unloadMap(_map->GetId(), gx, gy); +} diff --git a/src/server/game/Grids/GridTerrainLoader.h b/src/server/game/Grids/GridTerrainLoader.h new file mode 100644 index 000000000..03db11f7f --- /dev/null +++ b/src/server/game/Grids/GridTerrainLoader.h @@ -0,0 +1,59 @@ +/* + * 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 . + */ + +#ifndef ACORE_GRID_TERRAIN_LOADER_H +#define ACORE_GRID_TERRAIN_LOADER_H + +#include "GridDefines.h" + +class GridTerrainLoader +{ +public: + GridTerrainLoader(MapGridType& grid, Map* map) + : _grid(grid), _map(map) { } + + void LoadTerrain(); + + static bool ExistMap(uint32 mapid, int gx, int gy); + static bool ExistVMap(uint32 mapid, int gx, int gy); + +private: + void LoadMap(); + void LoadVMap(); + void LoadMMap(); + + uint16 GetX() { return (MAX_NUMBER_OF_GRIDS - 1) - _grid.GetX(); } + uint16 GetY() { return (MAX_NUMBER_OF_GRIDS - 1) - _grid.GetY(); } + + MapGridType& _grid; + Map* _map; +}; + +class GridTerrainUnloader +{ +public: + GridTerrainUnloader(MapGridType& grid, Map* map) + : _grid(grid), _map(map) { } + + void UnloadTerrain(); + +private: + MapGridType& _grid; + Map* _map; +}; + +#endif diff --git a/src/server/game/Grids/MapGrid.h b/src/server/game/Grids/MapGrid.h new file mode 100644 index 000000000..9c6b33c91 --- /dev/null +++ b/src/server/game/Grids/MapGrid.h @@ -0,0 +1,154 @@ +/* + * 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 . + */ + +#ifndef MAP_GRID_H +#define MAP_GRID_H + +#include "GridCell.h" +#include "GridReference.h" + +class GridTerrainData; + +template +< + class WORLD_OBJECT_TYPES, + class GRID_OBJECT_TYPES +> +class MapGrid +{ +public: + typedef GridCell GridCellType; + + MapGrid(uint16 const x, uint16 const y) + : _x(x), _y(y), _objectDataLoaded(false), _terrainData(nullptr) { } + + // Unique identifier for grid + uint32 GetId() const { return _y * MAX_NUMBER_OF_GRIDS + _x; } + + uint16 GetX() const { return _x; } + uint16 GetY() const { return _y; } + + bool IsObjectDataLoaded() const { return _objectDataLoaded; } + void SetObjectDataLoaded() { _objectDataLoaded = true; } + + template void AddWorldObject(uint16 const x, uint16 const y, SPECIFIC_OBJECT* obj) + { + GetOrCreateCell(x, y).AddWorldObject(obj); + } + + template void RemoveWorldObject(uint16 const x, uint16 const y, SPECIFIC_OBJECT* obj) + { + GetOrCreateCell(x, y).RemoveWorldObject(obj); + } + + template void AddGridObject(uint16 const x, uint16 const y, SPECIFIC_OBJECT* obj) + { + GetOrCreateCell(x, y).AddGridObject(obj); + } + + template void RemoveGridObject(uint16 const x, uint16 const y, SPECIFIC_OBJECT* obj) + { + GetOrCreateCell(x, y).RemoveGridObject(obj); + } + + // Visit all cells + template + void VisitAllCells(TypeContainerVisitor >& visitor) + { + for (auto& cellX : _cells) + { + for (auto& cellY : cellX) + { + if (!cellY) + continue; + + cellY->Visit(visitor); + } + } + } + + // Visit single cell + template + void VisitCell(uint16 const x, uint16 const y, TypeContainerVisitor >& visitor) + { + GridCellType* gridCell = GetCell(x, y); + if (!gridCell) + return; + + gridCell->Visit(visitor); + } + + void link(GridRefMgr>* pTo) + { + _gridReference.link(pTo, this); + } + + GridTerrainData* GetTerrainData() const { return _terrainData.get(); } + std::shared_ptr GetTerrainDataSharedPtr() { return _terrainData; } + void SetTerrainData(std::shared_ptr terrainData) { _terrainData = terrainData; } + + uint32 GetCreatedCellsCount() + { + uint32 count = 0; + for (auto& cellX : _cells) + { + for (auto& cellY : cellX) + { + if (!cellY) + continue; + + ++count; + } + } + return count; + } + +private: + // Creates and returns the cell if not already created + GridCellType& GetOrCreateCell(uint16 const x, uint16 const y) + { + GridCellType* cell = GetCell(x, y); + if (!cell) + _cells[x][y] = std::make_unique(); + + return *_cells[x][y]; + } + + GridCellType* GetCell(uint16 const x, uint16 const y) + { + ASSERT(x < MAX_NUMBER_OF_CELLS && y < MAX_NUMBER_OF_CELLS); + return _cells[x][y].get(); + } + + GridCellType const* GetCell(uint16 const x, uint16 const y) const + { + ASSERT(x < MAX_NUMBER_OF_CELLS && y < MAX_NUMBER_OF_CELLS); + return _cells[x][y].get(); + } + + uint16 _x; + uint16 _y; + + bool _objectDataLoaded; + std::array, MAX_NUMBER_OF_CELLS>, MAX_NUMBER_OF_CELLS> _cells; // N * N array + GridReference> _gridReference; + + // Instances will share a copy of the parent maps terrainData + std::shared_ptr _terrainData; +}; + +#endif diff --git a/src/server/game/Grids/MapGridManager.cpp b/src/server/game/Grids/MapGridManager.cpp new file mode 100644 index 000000000..21ca5bfed --- /dev/null +++ b/src/server/game/Grids/MapGridManager.cpp @@ -0,0 +1,129 @@ +#include "MapGridManager.h" +#include "GridObjectLoader.h" +#include "GridTerrainLoader.h" + +void MapGridManager::CreateGrid(uint16 const x, uint16 const y) +{ + std::lock_guard guard(_gridLock); + if (IsGridCreated(x, y)) + return; + + std::unique_ptr grid = std::make_unique(x, y); + grid->link(_map); + + GridTerrainLoader loader(*grid, _map); + loader.LoadTerrain(); + + _mapGrid[x][y] = std::move(grid); + + ++_createdGridsCount; +} + +bool MapGridManager::LoadGrid(uint16 const x, uint16 const y) +{ + MapGridType* grid = GetGrid(x, y); + if (!grid || grid->IsObjectDataLoaded()) + return false; + + // Must mark as loaded first, as GridObjectLoader spawning objects can attempt to recursively load the grid + grid->SetObjectDataLoaded(); + + GridObjectLoader loader(*grid, _map); + loader.LoadAllCellsInGrid(); + + ++_loadedGridsCount; + return true; +} + +void MapGridManager::UnloadGrid(uint16 const x, uint16 const y) +{ + MapGridType* grid = GetGrid(x, y); + if (!grid) + return; + + { + GridObjectCleaner worker; + TypeContainerVisitor visitor(worker); + grid->VisitAllCells(visitor); + } + + _map->RemoveAllObjectsInRemoveList(); + + { + GridObjectUnloader worker; + TypeContainerVisitor visitor(worker); + grid->VisitAllCells(visitor); + } + + GridTerrainUnloader terrainUnloader(*grid, _map); + terrainUnloader.UnloadTerrain(); + + _mapGrid[x][y] = nullptr; +} + +bool MapGridManager::IsGridCreated(uint16 const x, uint16 const y) const +{ + if (!MapGridManager::IsValidGridCoordinates(x, y)) + return false; + + return _mapGrid[x][y].get(); +} + +bool MapGridManager::IsGridLoaded(uint16 const x, uint16 const y) const +{ + if (!MapGridManager::IsValidGridCoordinates(x, y)) + return false; + + return _mapGrid[x][y].get() && _mapGrid[x][y]->IsObjectDataLoaded(); +} + +MapGridType* MapGridManager::GetGrid(uint16 const x, uint16 const y) +{ + if (!MapGridManager::IsValidGridCoordinates(x, y)) + return nullptr; + + return _mapGrid[x][y].get(); +} + +uint32 MapGridManager::GetCreatedGridsCount() +{ + return _createdGridsCount; +} + +uint32 MapGridManager::GetLoadedGridsCount() +{ + return _loadedGridsCount; +} + +uint32 MapGridManager::GetCreatedCellsInGridCount(uint16 const x, uint16 const y) +{ + MapGridType* grid = GetGrid(x, y); + if (grid) + return grid->GetCreatedCellsCount(); + + return 0; +} + +uint32 MapGridManager::GetCreatedCellsInMapCount() +{ + uint32 count = 0; + for (uint32 gridX = 0; gridX < MAX_NUMBER_OF_GRIDS; ++gridX) + { + for (uint32 gridY = 0; gridY < MAX_NUMBER_OF_GRIDS; ++gridY) + { + if (MapGridType* grid = GetGrid(gridX, gridY)) + count += grid->GetCreatedCellsCount(); + } + } + return count; +} + +bool MapGridManager::IsGridsFullyCreated() const +{ + return _createdGridsCount == (MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS); +} + +bool MapGridManager::IsGridsFullyLoaded() const +{ + return _loadedGridsCount == (MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS); +} diff --git a/src/server/game/Grids/MapGridManager.h b/src/server/game/Grids/MapGridManager.h new file mode 100644 index 000000000..3eb7c629d --- /dev/null +++ b/src/server/game/Grids/MapGridManager.h @@ -0,0 +1,62 @@ +/* + * 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 . + */ + +#ifndef MAP_GRID_MANAGER_H +#define MAP_GRID_MANAGER_H + +#include "Common.h" +#include "GridDefines.h" +#include "MapDefines.h" +#include "MapGrid.h" + +#include + +class Map; + +class MapGridManager +{ +public: + MapGridManager(Map* map) : _map(map), _createdGridsCount(0), _loadedGridsCount(0) { } + + void CreateGrid(uint16 const x, uint16 const y); + bool LoadGrid(uint16 const x, uint16 const y); + void UnloadGrid(uint16 const x, uint16 const y); + bool IsGridCreated(uint16 const x, uint16 const y) const; + bool IsGridLoaded(uint16 const x, uint16 const y) const; + MapGridType* GetGrid(uint16 const x, uint16 const y); + + static bool IsValidGridCoordinates(uint16 const x, uint16 const y) { return (x < MAX_NUMBER_OF_GRIDS && y < MAX_NUMBER_OF_GRIDS); } + + uint32 GetCreatedGridsCount(); + uint32 GetLoadedGridsCount(); + uint32 GetCreatedCellsInGridCount(uint16 const x, uint16 const y); + uint32 GetCreatedCellsInMapCount(); + + bool IsGridsFullyCreated() const; + bool IsGridsFullyLoaded() const; + +private: + Map* _map; + + uint32 _createdGridsCount; + uint32 _loadedGridsCount; + + std::mutex _gridLock; + std::unique_ptr _mapGrid[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; +}; + +#endif diff --git a/src/server/game/Grids/NGrid.h b/src/server/game/Grids/NGrid.h deleted file mode 100644 index 6ac60aeb7..000000000 --- a/src/server/game/Grids/NGrid.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 . - */ - -#ifndef ACORE_NGRID_H -#define ACORE_NGRID_H - -/** NGrid is nothing more than a wrapper of the Grid with an NxN cells - */ - -#include "Grid.h" -#include "GridReference.h" -#include "Timer.h" - -template -< - uint32 N, - class ACTIVE_OBJECT, - class WORLD_OBJECT_TYPES, - class GRID_OBJECT_TYPES - > -class NGrid -{ -public: - typedef Grid GridType; - NGrid(uint32 id, int32 x, int32 y) - : i_gridId(id), i_x(x), i_y(y), i_GridObjectDataLoaded(false) - { - } - - GridType& GetGridType(const uint32 x, const uint32 y) - { - ASSERT(x < N && y < N); - return i_cells[x][y]; - } - - [[nodiscard]] GridType const& GetGridType(const uint32 x, const uint32 y) const - { - ASSERT(x < N && y < N); - return i_cells[x][y]; - } - - [[nodiscard]] uint32 GetGridId() const { return i_gridId; } - [[nodiscard]] int32 getX() const { return i_x; } - [[nodiscard]] int32 getY() const { return i_y; } - - void link(GridRefMgr >* pTo) - { - i_Reference.link(pTo, this); - } - [[nodiscard]] bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; } - void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; } - - /* - template void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - GetGridType(x, y).AddWorldObject(obj); - } - - template void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - GetGridType(x, y).RemoveWorldObject(obj); - } - - template void AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - GetGridType(x, y).AddGridObject(obj); - } - - template void RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - GetGridType(x, y).RemoveGridObject(obj); - } - */ - - // Visit all Grids (cells) in NGrid (grid) - template - void VisitAllGrids(TypeContainerVisitor >& visitor) - { - for (uint32 x = 0; x < N; ++x) - for (uint32 y = 0; y < N; ++y) - GetGridType(x, y).Visit(visitor); - } - - // Visit a single Grid (cell) in NGrid (grid) - template - void VisitGrid(const uint32 x, const uint32 y, TypeContainerVisitor >& visitor) - { - GetGridType(x, y).Visit(visitor); - } - -private: - uint32 i_gridId; - GridReference > i_Reference; - int32 i_x; - int32 i_y; - GridType i_cells[N][N]; - bool i_GridObjectDataLoaded; -}; -#endif diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 42f657f9b..6e084b733 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -24,7 +24,7 @@ #include "GameObject.h" #include "Group.h" #include "Object.h" -#include "ObjectGridLoader.h" +#include "GridObjectLoader.h" #include "Optional.h" #include "Player.h" #include "Spell.h" diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp deleted file mode 100644 index 2b7d6f8ef..000000000 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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 "ObjectGridLoader.h" -#include "CellImpl.h" -#include "Corpse.h" -#include "Creature.h" -#include "DynamicObject.h" -#include "GameObject.h" -#include "GridNotifiers.h" -#include "ObjectMgr.h" -#include "Transport.h" - -// for loading world object at grid loading (Corpses) -//TODO: to implement npc on transport, also need to load npcs at grid loading -class ObjectWorldLoader -{ -public: - explicit ObjectWorldLoader(ObjectGridLoader& gloader) - : i_cell(gloader.i_cell), i_map(gloader.i_map), i_grid(gloader.i_grid), i_corpses(gloader.i_corpses) - {} - - void Visit(CorpseMapType& m); - - template void Visit(GridRefMgr&) { } - -private: - Cell i_cell; - Map* i_map; - NGridType& i_grid; -public: - uint32& i_corpses; -}; - -template void ObjectGridLoader::SetObjectCell(T* /*obj*/, CellCoord const& /*cellCoord*/) -{ -} - -template<> void ObjectGridLoader::SetObjectCell(Creature* obj, CellCoord const& cellCoord) -{ - Cell cell(cellCoord); - obj->SetCurrentCell(cell); -} - -template<> void ObjectGridLoader::SetObjectCell(GameObject* obj, CellCoord const& cellCoord) -{ - Cell cell(cellCoord); - obj->SetCurrentCell(cell); -} - -template -void AddObjectHelper(CellCoord& cell, GridRefMgr& m, uint32& count, Map* /*map*/, T* obj) -{ - obj->AddToGrid(m); - ObjectGridLoader::SetObjectCell(obj, cell); - obj->AddToWorld(); - ++count; -} - -template <> -void AddObjectHelper(CellCoord& cell, CreatureMapType& m, uint32& count, Map* map, Creature* obj) -{ - obj->AddToGrid(m); - ObjectGridLoader::SetObjectCell(obj, cell); - obj->AddToWorld(); - if (obj->isActiveObject()) - map->AddToActive(obj); - - ++count; -} - -template <> -void AddObjectHelper(CellCoord& cell, GameObjectMapType& m, uint32& count, Map* map, GameObject* obj) -{ - obj->AddToGrid(m); - ObjectGridLoader::SetObjectCell(obj, cell); - obj->AddToWorld(); - if (obj->isActiveObject()) - map->AddToActive(obj); - - ++count; -} - -template -void LoadHelper(CellGuidSet const& /*guid_set*/, CellCoord& /*cell*/, GridRefMgr& /*m*/, uint32& /*count*/, Map* /*map*/) -{ -} - -template <> -void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr& m, uint32& count, Map* map) -{ - for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) - { - Creature* obj = new Creature(); - ObjectGuid::LowType guid = *i_guid; - if (!obj->LoadFromDB(guid, map)) - { - delete obj; - continue; - } - - AddObjectHelper(cell, m, count, map, obj); - - if (!obj->IsMoveInLineOfSightDisabled() && obj->GetDefaultMovementType() == IDLE_MOTION_TYPE && !obj->isNeedNotify(NOTIFY_VISIBILITY_CHANGED | NOTIFY_AI_RELOCATION)) - { - if (obj->IsAlive() && !obj->HasUnitState(UNIT_STATE_SIGHTLESS) && obj->HasReactState(REACT_AGGRESSIVE) && !obj->IsImmuneToNPC()) - { - // call MoveInLineOfSight for nearby grid creatures - Acore::AIRelocationNotifier notifier(*obj); - Cell::VisitGridObjects(obj, notifier, 60.f); - } - } - } -} - -template <> -void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr& m, uint32& count, Map* map) -{ - for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) - { - ObjectGuid::LowType guid = *i_guid; - GameObjectData const* data = sObjectMgr->GetGameObjectData(guid); - GameObject* obj = data && sObjectMgr->IsGameObjectStaticTransport(data->id) ? new StaticTransport() : new GameObject(); - - if (!obj->LoadFromDB(guid, map)) - { - delete obj; - continue; - } - - AddObjectHelper(cell, m, count, map, obj); - } -} - -void ObjectGridLoader::Visit(GameObjectMapType& m) -{ - CellCoord cellCoord = i_cell.GetCellCoord(); - CellObjectGuids const& cell_guids = sObjectMgr->GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cellCoord.GetId()); - LoadHelper(cell_guids.gameobjects, cellCoord, m, i_gameObjects, i_map); -} - -void ObjectGridLoader::Visit(CreatureMapType& m) -{ - CellCoord cellCoord = i_cell.GetCellCoord(); - CellObjectGuids const& cell_guids = sObjectMgr->GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cellCoord.GetId()); - LoadHelper(cell_guids.creatures, cellCoord, m, i_creatures, i_map); -} - -void ObjectWorldLoader::Visit(CorpseMapType& /*m*/) -{ - CellCoord cellCoord = i_cell.GetCellCoord(); - if (std::unordered_set const* corpses = i_map->GetCorpsesInCell(cellCoord.GetId())) - { - for (Corpse* corpse : *corpses) - { - corpse->AddToWorld(); - GridType& cell = i_grid.GetGridType(i_cell.CellX(), i_cell.CellY()); - if (corpse->IsWorldObject()) - cell.AddWorldObject(corpse); - else - cell.AddGridObject(corpse); - - ++i_corpses; - } - } -} - -void ObjectGridLoader::LoadN(void) -{ - i_gameObjects = 0; - i_creatures = 0; - i_corpses = 0; - i_cell.data.Part.cell_y = 0; - for (uint32 x = 0; x < MAX_NUMBER_OF_CELLS; ++x) - { - i_cell.data.Part.cell_x = x; - for (uint32 y = 0; y < MAX_NUMBER_OF_CELLS; ++y) - { - i_cell.data.Part.cell_y = y; - - //Load creatures and game objects - { - TypeContainerVisitor visitor(*this); - i_grid.VisitGrid(x, y, visitor); - } - - //Load corpses (not bones) - { - ObjectWorldLoader worker(*this); - TypeContainerVisitor visitor(worker); - i_grid.VisitGrid(x, y, visitor); - } - } - } - LOG_DEBUG("maps", "{} GameObjects, {} Creatures, and {} Corpses/Bones loaded for grid {} on map {}", i_gameObjects, i_creatures, i_corpses, i_grid.GetGridId(), i_map->GetId()); -} - -template -void ObjectGridUnloader::Visit(GridRefMgr& m) -{ - while (!m.IsEmpty()) - { - T* obj = m.getFirst()->GetSource(); - // if option set then object already saved at this moment - //if (!sWorld->getBoolConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY)) - // obj->SaveRespawnTime(); - //Some creatures may summon other temp summons in CleanupsBeforeDelete() - //So we need this even after cleaner (maybe we can remove cleaner) - //Example: Flame Leviathan Turret 33139 is summoned when a creature is deleted - //TODO: Check if that script has the correct logic. Do we really need to summons something before deleting? - obj->CleanupsBeforeDelete(); - ///- object will get delinked from the manager when deleted - delete obj; - } -} - -template -void ObjectGridCleaner::Visit(GridRefMgr& m) -{ - for (typename GridRefMgr::iterator iter = m.begin(); iter != m.end(); ++iter) - iter->GetSource()->CleanupsBeforeDelete(); -} - -template void ObjectGridUnloader::Visit(CreatureMapType&); -template void ObjectGridUnloader::Visit(GameObjectMapType&); -template void ObjectGridUnloader::Visit(DynamicObjectMapType&); - -template void ObjectGridCleaner::Visit(CreatureMapType&); -template void ObjectGridCleaner::Visit(GameObjectMapType&); -template void ObjectGridCleaner::Visit(DynamicObjectMapType&); -template void ObjectGridCleaner::Visit(CorpseMapType&); diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index f5c3df9b8..963fdcb29 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -777,16 +777,10 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData) Unit* unit = ObjectAccessor::GetUnit(*_player, guid); - CellCoord p = Acore::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()); - - Cell cell(p); - cell.SetNoCreate(); - Acore::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit); Acore::LocalizedPacketDo emote_do(emote_builder); Acore::PlayerDistWorker > emote_worker(GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), emote_do); - TypeContainerVisitor >, WorldTypeMapContainer> message(emote_worker); - cell.Visit(p, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + Cell::VisitWorldObjects(GetPlayer(), emote_worker, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); diff --git a/src/server/game/Loot/LootItemStorage.cpp b/src/server/game/Loot/LootItemStorage.cpp index e5b6de588..434ad4325 100644 --- a/src/server/game/Loot/LootItemStorage.cpp +++ b/src/server/game/Loot/LootItemStorage.cpp @@ -20,6 +20,7 @@ #include "ObjectMgr.h" #include "PreparedStatement.h" #include "QueryResult.h" +#include "Timer.h" LootItemStorage::LootItemStorage() { diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 5d9579c4a..38f501bb3 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -28,13 +28,13 @@ #include "InstanceScript.h" #include "IVMapMgr.h" #include "LFGMgr.h" +#include "MapGrid.h" #include "MapInstanced.h" #include "Metric.h" #include "MiscPackets.h" #include "MMapFactory.h" #include "Object.h" #include "ObjectAccessor.h" -#include "ObjectGridLoader.h" #include "ObjectMgr.h" #include "Pet.h" #include "ScriptMgr.h" @@ -44,21 +44,6 @@ #include "VMapMgr2.h" #include "Weather.h" -union u_map_magic -{ - char asChar[4]; - uint32 asUInt; -}; - -u_map_magic MapMagic = { {'M', 'A', 'P', 'S'} }; -uint32 MapVersionMagic = 9; -u_map_magic MapAreaMagic = { {'A', 'R', 'E', 'A'} }; -u_map_magic MapHeightMagic = { {'M', 'H', 'G', 'T'} }; -u_map_magic MapLiquidMagic = { {'M', 'L', 'I', 'Q'} }; - -static uint16 const holetab_h[4] = { 0x1111, 0x2222, 0x4444, 0x8888 }; -static uint16 const holetab_v[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 }; - #define MAP_INVALID_ZONE 0xFFFFFFFF ZoneDynamicInfo::ZoneDynamicInfo() : MusicId(0), WeatherId(WEATHER_STATE_FINE), @@ -83,181 +68,29 @@ Map::~Map() if (!m_scriptSchedule.empty()) sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); - //MMAP::MMapFactory::createOrGetMMapMgr()->unloadMap(GetId()); MMAP::MMapFactory::createOrGetMMapMgr()->unloadMapInstance(GetId(), i_InstanceId); } -bool Map::ExistMap(uint32 mapid, int gx, int gy) -{ - int len = sWorld->GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1; - char* tmp = new char[len]; - snprintf(tmp, len, (char*)(sWorld->GetDataPath() + "maps/%03u%02u%02u.map").c_str(), mapid, gx, gy); - - bool ret = false; - FILE* pf = fopen(tmp, "rb"); - - if (!pf) - LOG_ERROR("maps", "Map file '{}': does not exist!", tmp); - else - { - map_fileheader header; - if (fread(&header, sizeof(header), 1, pf) == 1) - { - if (header.mapMagic != MapMagic.asUInt || header.versionMagic != MapVersionMagic) - { - LOG_ERROR("maps", "Map file '{}' is from an incompatible map version ({:.4u} v{}), {:.4s} v{} is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files.", - tmp, 4, header.mapMagic, header.versionMagic, 4, MapMagic.asChar, MapVersionMagic); - } - - else - ret = true; - } - fclose(pf); - } - delete [] tmp; - return ret; -} - -bool Map::ExistVMap(uint32 mapid, int gx, int gy) -{ - if (VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr()) - { - if (vmgr->isMapLoadingEnabled()) - { - VMAP::LoadResult result = vmgr->existsMap((sWorld->GetDataPath() + "vmaps").c_str(), mapid, gx, gy); - std::string name = vmgr->getDirFileName(mapid, gx, gy); - switch (result) - { - case VMAP::LoadResult::Success: - break; - case VMAP::LoadResult::FileNotFound: - LOG_ERROR("maps", "VMap file '{}' does not exist", (sWorld->GetDataPath() + "vmaps/" + name)); - LOG_ERROR("maps", "Please place VMAP files (*.vmtree and *.vmtile) in the vmap directory ({}), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath() + "vmaps/")); - return false; - case VMAP::LoadResult::VersionMismatch: - LOG_ERROR("maps", "VMap file '{}' couldn't be loaded", (sWorld->GetDataPath() + "vmaps/" + name)); - LOG_ERROR("maps", "This is because the version of the VMap file and the version of this module are different, please re-extract the maps with the tools compiled with this module."); - return false; - } - } - } - - return true; -} - -void Map::LoadMMap(int gx, int gy) -{ - if (!sDisableMgr->IsPathfindingEnabled(this)) // pussywizard - return; - - int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(GetId(), gx, gy); - switch (mmapLoadResult) - { - case MMAP::MMAP_LOAD_RESULT_OK: - LOG_DEBUG("maps", "MMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy); - break; - case MMAP::MMAP_LOAD_RESULT_ERROR: - LOG_DEBUG("maps", "Could not load MMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy); - break; - case MMAP::MMAP_LOAD_RESULT_IGNORED: - LOG_DEBUG("maps", "Ignored MMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy); - break; - } -} - -void Map::LoadVMap(int gx, int gy) -{ - // x and y are swapped !! - int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapMgr()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), GetId(), gx, gy); - switch (vmapLoadResult) - { - case VMAP::VMAP_LOAD_RESULT_OK: - LOG_DEBUG("maps", "VMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy); - break; - case VMAP::VMAP_LOAD_RESULT_ERROR: - LOG_DEBUG("maps", "Could not load VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy); - break; - case VMAP::VMAP_LOAD_RESULT_IGNORED: - LOG_DEBUG("maps", "Ignored VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy); - break; - } -} - -void Map::LoadMap(int gx, int gy, bool reload) -{ - if (i_InstanceId != 0) - { - if (GridMaps[gx][gy]) - return; - - // load grid map for base map - m_parentMap->EnsureGridCreated(GridCoord(63 - gx, 63 - gy)); - - GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy]; - return; - } - - if (GridMaps[gx][gy] && !reload) - return; - - //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?) - if (GridMaps[gx][gy]) - { - LOG_DEBUG("maps", "Unloading previously loaded map {} before reloading.", GetId()); - sScriptMgr->OnUnloadGridMap(this, GridMaps[gx][gy], gx, gy); - - delete (GridMaps[gx][gy]); - GridMaps[gx][gy] = nullptr; - } - - // map file name - char* tmp = nullptr; - int len = sWorld->GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1; - tmp = new char[len]; - snprintf(tmp, len, (char*)(sWorld->GetDataPath() + "maps/%03u%02u%02u.map").c_str(), GetId(), gx, gy); - LOG_DEBUG("maps", "Loading map {}", tmp); - // loading data - GridMaps[gx][gy] = new GridMap(); - if (!GridMaps[gx][gy]->loadData(tmp)) - { - LOG_ERROR("maps", "Error loading map file: \n {}\n", tmp); - } - delete [] tmp; - - sScriptMgr->OnLoadGridMap(this, GridMaps[gx][gy], gx, gy); -} - -void Map::LoadMapAndVMap(int gx, int gy) -{ - LoadMap(gx, gy); - if (i_InstanceId == 0) - { - LoadVMap(gx, gy); // Only load the data for the base map - LoadMMap(gx, gy); - } -} - Map::Map(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent) : - i_mapEntry(sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId), + _mapGridManager(this), i_mapEntry(sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId), m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE), _instanceResetPeriod(0), m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transports.end()), i_scriptLock(false), _defaultLight(GetDefaultMapLight(id)) { m_parentMap = (_parent ? _parent : this); - for (unsigned int idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx) - { - for (unsigned int j = 0; j < MAX_NUMBER_OF_GRIDS; ++j) - { - //z code - GridMaps[idx][j] = nullptr; - setNGrid(nullptr, idx, j); - } - } _zonePlayerCountMap.clear(); //lets initialize visibility distance for map Map::InitVisibilityDistance(); +} + +// Hook called after map is created AND after added to map list +void Map::OnCreateMap() +{ + // Instances load all grids by default (both base map and child maps) + if (GetInstanceId()) + LoadAllGrids(); sScriptMgr->OnCreateMap(this); } @@ -282,21 +115,21 @@ void Map::InitVisibilityDistance() template void Map::AddToGrid(T* obj, Cell const& cell) { - NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); + MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY()); if (obj->IsWorldObject()) - grid->GetGridType(cell.CellX(), cell.CellY()).template AddWorldObject(obj); + grid->AddWorldObject(cell.CellX(), cell.CellY(), obj); else - grid->GetGridType(cell.CellX(), cell.CellY()).template AddGridObject(obj); + grid->AddGridObject(cell.CellX(), cell.CellY(), obj); } template<> void Map::AddToGrid(Creature* obj, Cell const& cell) { - NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); + MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY()); if (obj->IsWorldObject()) - grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj); + grid->AddWorldObject(cell.CellX(), cell.CellY(), obj); else - grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj); + grid->AddGridObject(cell.CellX(), cell.CellY(), obj); obj->SetCurrentCell(cell); } @@ -304,8 +137,8 @@ void Map::AddToGrid(Creature* obj, Cell const& cell) template<> void Map::AddToGrid(GameObject* obj, Cell const& cell) { - NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); - grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj); + MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY()); + grid->AddGridObject(cell.CellX(), cell.CellY(), obj); obj->SetCurrentCell(cell); } @@ -313,11 +146,11 @@ void Map::AddToGrid(GameObject* obj, Cell const& cell) template<> void Map::AddToGrid(DynamicObject* obj, Cell const& cell) { - NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); + MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY()); if (obj->IsWorldObject()) - grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj); + grid->AddWorldObject(cell.CellX(), cell.CellY(), obj); else - grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj); + grid->AddGridObject(cell.CellX(), cell.CellY(), obj); obj->SetCurrentCell(cell); } @@ -325,19 +158,19 @@ void Map::AddToGrid(DynamicObject* obj, Cell const& cell) template<> void Map::AddToGrid(Corpse* obj, Cell const& cell) { - NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); + MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY()); // Corpses are a special object type - they can be added to grid via a call to AddToMap // or loaded through ObjectGridLoader. // Both corpses loaded from database and these freshly generated by Player::CreateCoprse are added to _corpsesByCell // ObjectGridLoader loads all corpses from _corpsesByCell even if they were already added to grid before it was loaded // so we need to explicitly check it here (Map::AddToGrid is only called from Player::BuildPlayerRepop, not from ObjectGridLoader) // to avoid failing an assertion in GridObject::AddToGrid - if (grid->isGridObjectDataLoaded()) + if (grid->IsObjectDataLoaded()) { if (obj->IsWorldObject()) - grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj); + grid->AddWorldObject(cell.CellX(), cell.CellY(), obj); else - grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj); + grid->AddGridObject(cell.CellX(), cell.CellY(), obj); } } @@ -363,21 +196,19 @@ void Map::SwitchGridContainers(Creature* obj, bool on) return; LOG_DEBUG("maps", "Switch object {} from grid[{}, {}] {}", obj->GetGUID().ToString(), cell.GridX(), cell.GridY(), on); - NGridType* ngrid = getNGrid(cell.GridX(), cell.GridY()); - ASSERT(ngrid); - - GridType& grid = ngrid->GetGridType(cell.CellX(), cell.CellY()); + MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY()); + ASSERT(grid); obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add if (on) { - grid.AddWorldObject(obj); + grid->AddWorldObject(cell.CellX(), cell.CellY(), obj); AddWorldObject(obj); } else { - grid.AddGridObject(obj); + grid->AddGridObject(cell.CellX(), cell.CellY(), obj); RemoveWorldObject(obj); } @@ -401,21 +232,19 @@ void Map::SwitchGridContainers(GameObject* obj, bool on) return; //LOG_DEBUG(LOG_FILTER_MAPS, "Switch object {} from grid[{}, {}] {}", obj->GetGUID().ToString(), cell.data.Part.grid_x, cell.data.Part.grid_y, on); - NGridType* ngrid = getNGrid(cell.GridX(), cell.GridY()); - ASSERT(ngrid); - - GridType& grid = ngrid->GetGridType(cell.CellX(), cell.CellY()); + MapGridType* grid = GetMapGrid(cell.GridX(), cell.GridY()); + ASSERT(grid); obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add if (on) { - grid.AddWorldObject(obj); + grid->AddWorldObject(cell.CellX(), cell.CellY(), obj); AddWorldObject(obj); } else { - grid.AddGridObject(obj); + grid->AddGridObject(cell.CellX(), cell.CellY(), obj); RemoveWorldObject(obj); } } @@ -436,78 +265,81 @@ void Map::DeleteFromWorld(Player* player) delete player; } -void Map::EnsureGridCreated(const GridCoord& p) +void Map::EnsureGridCreated(GridCoord const& gridCoord) { - if (getNGrid(p.x_coord, p.y_coord)) // pussywizard - return; - std::lock_guard guard(GridLock); - EnsureGridCreated_i(p); + _mapGridManager.CreateGrid(gridCoord.x_coord, gridCoord.y_coord); } -//Create NGrid so the object can be added to it -//But object data is not loaded here -void Map::EnsureGridCreated_i(const GridCoord& p) -{ - if (!getNGrid(p.x_coord, p.y_coord)) - { - // pussywizard: moved setNGrid to the end of the function - NGridType* ngt = new NGridType(p.x_coord * MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord); - - // build a linkage between this map and NGridType - buildNGridLinkage(ngt); // pussywizard: getNGrid(x, y) changed to: ngt - - //z coord - int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord; - int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord; - - if (!GridMaps[gx][gy]) - { - LoadMapAndVMap(gx, gy); - } - - // pussywizard: moved here - setNGrid(ngt, p.x_coord, p.y_coord); - } -} - -//Create NGrid and load the object data in it -bool Map::EnsureGridLoaded(const Cell& cell) +bool Map::EnsureGridLoaded(Cell const& cell) { EnsureGridCreated(GridCoord(cell.GridX(), cell.GridY())); - NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); - ASSERT(grid); - if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY())) + if (_mapGridManager.LoadGrid(cell.GridX(), cell.GridY())) { - //if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY())) - //{ - LOG_DEBUG("maps", "Loading grid[{}, {}] for map {} instance {}", cell.GridX(), cell.GridY(), GetId(), i_InstanceId); - - setGridObjectDataLoaded(true, cell.GridX(), cell.GridY()); - - ObjectGridLoader loader(*grid, this, cell); - loader.LoadN(); - Balance(); return true; - //} } return false; } +MapGridType* Map::GetMapGrid(uint16 const x, uint16 const y) +{ + return _mapGridManager.GetGrid(x, y); +} + +bool Map::IsGridLoaded(GridCoord const& gridCoord) const +{ + return _mapGridManager.IsGridLoaded(gridCoord.x_coord, gridCoord.y_coord); +} + +bool Map::IsGridCreated(GridCoord const& gridCoord) const +{ + return _mapGridManager.IsGridCreated(gridCoord.x_coord, gridCoord.y_coord); +} + void Map::LoadGrid(float x, float y) { EnsureGridLoaded(Cell(x, y)); } -void Map::LoadAllCells() +void Map::LoadAllGrids() { for (uint32 cellX = 0; cellX < TOTAL_NUMBER_OF_CELLS_PER_MAP; cellX++) for (uint32 cellY = 0; cellY < TOTAL_NUMBER_OF_CELLS_PER_MAP; cellY++) LoadGrid((cellX + 0.5f - CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL, (cellY + 0.5f - CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL); } +void Map::LoadGridsInRange(Position const& center, float radius) +{ + if (_mapGridManager.IsGridsFullyLoaded()) + return; + + float const x = center.GetPositionX(); + float const y = center.GetPositionY(); + + CellCoord cellCoord(Acore::ComputeCellCoord(x, y)); + if (!cellCoord.IsCoordValid()) + return; + + if (radius > SIZE_OF_GRIDS) + radius = SIZE_OF_GRIDS; + + CellArea area = Cell::CalculateCellArea(x, y, radius); + if (!area) + return; + + for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x) + { + for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y) + { + CellCoord cellCoord(x, y); + Cell cell(cellCoord); + EnsureGridLoaded(cell); + } + } +} + bool Map::AddPlayerToMap(Player* player) { CellCoord cellCoord = Acore::ComputeCellCoord(player->GetPositionX(), player->GetPositionY()); @@ -519,7 +351,7 @@ bool Map::AddPlayerToMap(Player* player) } Cell cell(cellCoord); - EnsureGridLoaded(cell); + LoadGridsInRange(*player, MAX_VISIBILITY_DISTANCE); AddToGrid(player, cell); // Check if we are adding to correct map @@ -660,11 +492,6 @@ bool Map::AddToMap(MotionTransport* obj, bool /*checkTransport*/) return true; } -bool Map::IsGridLoaded(const GridCoord& p) const -{ - return (getNGrid(p.x_coord, p.y_coord) && isGridObjectDataLoaded(p.x_coord, p.y_coord)); -} - void Map::VisitNearbyCellsOfPlayer(Player* player, TypeContainerVisitor& gridVisitor, TypeContainerVisitor& worldVisitor, TypeContainerVisitor& largeGridVisitor, @@ -725,7 +552,6 @@ void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor visitor(worker); - ngrid.VisitAllGrids(visitor); - } - - RemoveAllObjectsInRemoveList(); - - { - ObjectGridUnloader worker; - TypeContainerVisitor visitor(worker); - ngrid.VisitAllGrids(visitor); - } + _mapGridManager.UnloadGrid(grid.GetX(), grid.GetY()); ASSERT(i_objectsToRemove.empty()); - - delete &ngrid; - setNGrid(nullptr, x, y); - - int gx = (MAX_NUMBER_OF_GRIDS - 1) - x; - int gy = (MAX_NUMBER_OF_GRIDS - 1) - y; - - if (i_InstanceId == 0) - { - if (GridMaps[gx][gy]) - { - GridMaps[gx][gy]->unloadData(); - delete GridMaps[gx][gy]; - } - // x and y are swapped - VMAP::VMapFactory::createOrGetVMapMgr()->unloadMap(GetId(), gx, gy); - MMAP::MMapFactory::createOrGetMMapMgr()->unloadMap(GetId(), gx, gy); - } - - GridMaps[gx][gy] = nullptr; - - LOG_DEBUG("maps", "Unloading grid[{}, {}] for map {} finished", x, y, GetId()); + LOG_DEBUG("maps", "Unloading grid[{}, {}] for map {} finished", grid.GetX(), grid.GetY(), GetId()); return true; } @@ -1304,9 +1092,9 @@ void Map::UnloadAll() _creaturesToMove.clear(); _gameObjectsToMove.clear(); - for (GridRefMgr::iterator i = GridRefMgr::begin(); i != GridRefMgr::end();) + for (GridRefMgr::iterator i = GridRefMgr::begin(); i != GridRefMgr::end();) { - NGridType& grid(*i->GetSource()); + MapGridType& grid(*i->GetSource()); ++i; UnloadGrid(grid); // deletes the grid and removes it from the GridRefMgr } @@ -1341,696 +1129,45 @@ void Map::UnloadAll() _corpseBones.clear(); } -// ***************************** -// Grid function -// ***************************** -GridMap::GridMap() +std::shared_ptr Map::GetGridTerrainDataSharedPtr(GridCoord const& gridCoord) { - _flags = 0; - // Area data - _gridArea = 0; - _areaMap = nullptr; - // Height level data - _gridHeight = INVALID_HEIGHT; - _gridGetHeight = &GridMap::getHeightFromFlat; - _gridIntHeightMultiplier = 0; - m_V9 = nullptr; - m_V8 = nullptr; - _maxHeight = nullptr; - _minHeight = nullptr; - // Liquid data - _liquidGlobalEntry = 0; - _liquidGlobalFlags = 0; - _liquidOffX = 0; - _liquidOffY = 0; - _liquidWidth = 0; - _liquidHeight = 0; - _liquidLevel = INVALID_HEIGHT; - _liquidEntry = nullptr; - _liquidFlags = nullptr; - _liquidMap = nullptr; - _holes = nullptr; + // ensure GridMap is created + EnsureGridCreated(gridCoord); + return _mapGridManager.GetGrid(gridCoord.x_coord, gridCoord.y_coord)->GetTerrainDataSharedPtr(); } -GridMap::~GridMap() +GridTerrainData* Map::GetGridTerrainData(GridCoord const& gridCoord) { - unloadData(); + if (!MapGridManager::IsValidGridCoordinates(gridCoord.x_coord, gridCoord.y_coord)) + return nullptr; + + // ensure GridMap is created + EnsureGridCreated(gridCoord); + return _mapGridManager.GetGrid(gridCoord.x_coord, gridCoord.y_coord)->GetTerrainData(); } -bool GridMap::loadData(char* filename) +GridTerrainData* Map::GetGridTerrainData(float x, float y) { - // Unload old data if exist - unloadData(); - - map_fileheader header; - // Not return error if file not found - FILE* in = fopen(filename, "rb"); - if (!in) - return true; - - if (fread(&header, sizeof(header), 1, in) != 1) - { - fclose(in); - return false; - } - - if (header.mapMagic == MapMagic.asUInt && header.versionMagic == MapVersionMagic) - { - // loadup area data - if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize)) - { - LOG_ERROR("maps", "Error loading map area data\n"); - fclose(in); - return false; - } - // loadup height data - if (header.heightMapOffset && !loadHeightData(in, header.heightMapOffset, header.heightMapSize)) - { - LOG_ERROR("maps", "Error loading map height data\n"); - fclose(in); - return false; - } - // loadup liquid data - if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize)) - { - LOG_ERROR("maps", "Error loading map liquids data\n"); - fclose(in); - return false; - } - // loadup holes data (if any. check header.holesOffset) - if (header.holesSize && !loadHolesData(in, header.holesOffset, header.holesSize)) - { - LOG_ERROR("maps", "Error loading map holes data\n"); - fclose(in); - return false; - } - fclose(in); - return true; - } - LOG_ERROR("maps", "Map file '{}' is from an incompatible clientversion. Please recreate using the mapextractor.", filename); - fclose(in); - return false; -} - -void GridMap::unloadData() -{ - delete[] _areaMap; - delete[] m_V9; - delete[] m_V8; - delete[] _maxHeight; - delete[] _minHeight; - delete[] _liquidEntry; - delete[] _liquidFlags; - delete[] _liquidMap; - delete[] _holes; - _areaMap = nullptr; - m_V9 = nullptr; - m_V8 = nullptr; - _maxHeight = nullptr; - _minHeight = nullptr; - _liquidEntry = nullptr; - _liquidFlags = nullptr; - _liquidMap = nullptr; - _holes = nullptr; - _gridGetHeight = &GridMap::getHeightFromFlat; -} - -bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/) -{ - map_areaHeader header; - fseek(in, offset, SEEK_SET); - - if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapAreaMagic.asUInt) - return false; - - _gridArea = header.gridArea; - if (!(header.flags & MAP_AREA_NO_AREA)) - { - _areaMap = new uint16 [16 * 16]; - if (fread(_areaMap, sizeof(uint16), 16 * 16, in) != 16 * 16) - return false; - } - return true; -} - -bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/) -{ - map_heightHeader header; - fseek(in, offset, SEEK_SET); - - if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapHeightMagic.asUInt) - return false; - - _gridHeight = header.gridHeight; - if (!(header.flags & MAP_HEIGHT_NO_HEIGHT)) - { - if ((header.flags & MAP_HEIGHT_AS_INT16)) - { - m_uint16_V9 = new uint16 [129 * 129]; - m_uint16_V8 = new uint16 [128 * 128]; - if (fread(m_uint16_V9, sizeof(uint16), 129 * 129, in) != 129 * 129 || - fread(m_uint16_V8, sizeof(uint16), 128 * 128, in) != 128 * 128) - return false; - _gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535; - _gridGetHeight = &GridMap::getHeightFromUint16; - } - else if ((header.flags & MAP_HEIGHT_AS_INT8)) - { - m_uint8_V9 = new uint8 [129 * 129]; - m_uint8_V8 = new uint8 [128 * 128]; - if (fread(m_uint8_V9, sizeof(uint8), 129 * 129, in) != 129 * 129 || - fread(m_uint8_V8, sizeof(uint8), 128 * 128, in) != 128 * 128) - return false; - _gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255; - _gridGetHeight = &GridMap::getHeightFromUint8; - } - else - { - m_V9 = new float [129 * 129]; - m_V8 = new float [128 * 128]; - if (fread(m_V9, sizeof(float), 129 * 129, in) != 129 * 129 || - fread(m_V8, sizeof(float), 128 * 128, in) != 128 * 128) - return false; - _gridGetHeight = &GridMap::getHeightFromFloat; - } - } - else - _gridGetHeight = &GridMap::getHeightFromFlat; - - if (header.flags & MAP_HEIGHT_HAS_FLIGHT_BOUNDS) - { - _maxHeight = new int16[3 * 3]; - _minHeight = new int16[3 * 3]; - if (fread(_maxHeight, sizeof(int16), 3 * 3, in) != 3 * 3 || - fread(_minHeight, sizeof(int16), 3 * 3, in) != 3 * 3) - return false; - } - - return true; -} - -bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/) -{ - map_liquidHeader header; - fseek(in, offset, SEEK_SET); - - if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt) - return false; - - _liquidGlobalEntry = header.liquidType; - _liquidGlobalFlags = header.liquidFlags; - _liquidOffX = header.offsetX; - _liquidOffY = header.offsetY; - _liquidWidth = header.width; - _liquidHeight = header.height; - _liquidLevel = header.liquidLevel; - - if (!(header.flags & MAP_LIQUID_NO_TYPE)) - { - _liquidEntry = new uint16[16 * 16]; - if (fread(_liquidEntry, sizeof(uint16), 16 * 16, in) != 16 * 16) - return false; - - _liquidFlags = new uint8[16 * 16]; - if (fread(_liquidFlags, sizeof(uint8), 16 * 16, in) != 16 * 16) - return false; - } - if (!(header.flags & MAP_LIQUID_NO_HEIGHT)) - { - _liquidMap = new float[uint32(_liquidWidth) * uint32(_liquidHeight)]; - if (fread(_liquidMap, sizeof(float), _liquidWidth * _liquidHeight, in) != (uint32(_liquidWidth) * uint32(_liquidHeight))) - return false; - } - return true; -} - -bool GridMap::loadHolesData(FILE* in, uint32 offset, uint32 /*size*/) -{ - if (fseek(in, offset, SEEK_SET) != 0) - return false; - - _holes = new uint16[16 * 16]; - if (fread(_holes, sizeof(uint16), 16 * 16, in) != 16 * 16) - return false; - - return true; -} - -uint16 GridMap::getArea(float x, float y) const -{ - if (!_areaMap) - return _gridArea; - - x = 16 * (32 - x / SIZE_OF_GRIDS); - y = 16 * (32 - y / SIZE_OF_GRIDS); - int lx = (int)x & 15; - int ly = (int)y & 15; - return _areaMap[lx * 16 + ly]; -} - -float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const -{ - return _gridHeight; -} - -float GridMap::getHeightFromFloat(float x, float y) const -{ - if (!m_V8 || !m_V9) - return _gridHeight; - - x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); - y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); - - int x_int = (int)x; - int y_int = (int)y; - x -= x_int; - y -= y_int; - x_int &= (MAP_RESOLUTION - 1); - y_int &= (MAP_RESOLUTION - 1); - - if (isHole(x_int, y_int)) - return INVALID_HEIGHT; - - // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid - // +--------------> X - // | h1-------h2 Coordinates is: - // | | \ 1 / | h1 0, 0 - // | | \ / | h2 0, 1 - // | | 2 h5 3 | h3 1, 0 - // | | / \ | h4 1, 1 - // | | / 4 \ | h5 1/2, 1/2 - // | h3-------h4 - // V Y - // For find height need - // 1 - detect triangle - // 2 - solve linear equation from triangle points - // Calculate coefficients for solve h = a*x + b*y + c - - float a, b, c; - // Select triangle: - if (x + y < 1) - { - if (x > y) - { - // 1 triangle (h1, h2, h5 points) - float h1 = m_V9[(x_int) * 129 + y_int]; - float h2 = m_V9[(x_int + 1) * 129 + y_int]; - float h5 = 2 * m_V8[x_int * 128 + y_int]; - a = h2 - h1; - b = h5 - h1 - h2; - c = h1; - } - else - { - // 2 triangle (h1, h3, h5 points) - float h1 = m_V9[x_int * 129 + y_int ]; - float h3 = m_V9[x_int * 129 + y_int + 1]; - float h5 = 2 * m_V8[x_int * 128 + y_int]; - a = h5 - h1 - h3; - b = h3 - h1; - c = h1; - } - } - else - { - if (x > y) - { - // 3 triangle (h2, h4, h5 points) - float h2 = m_V9[(x_int + 1) * 129 + y_int ]; - float h4 = m_V9[(x_int + 1) * 129 + y_int + 1]; - float h5 = 2 * m_V8[x_int * 128 + y_int]; - a = h2 + h4 - h5; - b = h4 - h2; - c = h5 - h4; - } - else - { - // 4 triangle (h3, h4, h5 points) - float h3 = m_V9[(x_int) * 129 + y_int + 1]; - float h4 = m_V9[(x_int + 1) * 129 + y_int + 1]; - float h5 = 2 * m_V8[x_int * 128 + y_int]; - a = h4 - h3; - b = h3 + h4 - h5; - c = h5 - h4; - } - } - // Calculate height - return a * x + b * y + c; -} - -float GridMap::getHeightFromUint8(float x, float y) const -{ - if (!m_uint8_V8 || !m_uint8_V9) - return _gridHeight; - - x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); - y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); - - int x_int = (int)x; - int y_int = (int)y; - x -= x_int; - y -= y_int; - x_int &= (MAP_RESOLUTION - 1); - y_int &= (MAP_RESOLUTION - 1); - - if (isHole(x_int, y_int)) - return INVALID_HEIGHT; - - int32 a, b, c; - uint8* V9_h1_ptr = &m_uint8_V9[x_int * 128 + x_int + y_int]; - if (x + y < 1) - { - if (x > y) - { - // 1 triangle (h1, h2, h5 points) - int32 h1 = V9_h1_ptr[ 0]; - int32 h2 = V9_h1_ptr[129]; - int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int]; - a = h2 - h1; - b = h5 - h1 - h2; - c = h1; - } - else - { - // 2 triangle (h1, h3, h5 points) - int32 h1 = V9_h1_ptr[0]; - int32 h3 = V9_h1_ptr[1]; - int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int]; - a = h5 - h1 - h3; - b = h3 - h1; - c = h1; - } - } - else - { - if (x > y) - { - // 3 triangle (h2, h4, h5 points) - int32 h2 = V9_h1_ptr[129]; - int32 h4 = V9_h1_ptr[130]; - int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int]; - a = h2 + h4 - h5; - b = h4 - h2; - c = h5 - h4; - } - else - { - // 4 triangle (h3, h4, h5 points) - int32 h3 = V9_h1_ptr[ 1]; - int32 h4 = V9_h1_ptr[130]; - int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int]; - a = h4 - h3; - b = h3 + h4 - h5; - c = h5 - h4; - } - } - // Calculate height - return (float)((a * x) + (b * y) + c) * _gridIntHeightMultiplier + _gridHeight; -} - -float GridMap::getHeightFromUint16(float x, float y) const -{ - if (!m_uint16_V8 || !m_uint16_V9) - return _gridHeight; - - x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); - y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); - - int x_int = (int)x; - int y_int = (int)y; - x -= x_int; - y -= y_int; - x_int &= (MAP_RESOLUTION - 1); - y_int &= (MAP_RESOLUTION - 1); - - if (isHole(x_int, y_int)) - return INVALID_HEIGHT; - - int32 a, b, c; - uint16* V9_h1_ptr = &m_uint16_V9[x_int * 128 + x_int + y_int]; - if (x + y < 1) - { - if (x > y) - { - // 1 triangle (h1, h2, h5 points) - int32 h1 = V9_h1_ptr[ 0]; - int32 h2 = V9_h1_ptr[129]; - int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int]; - a = h2 - h1; - b = h5 - h1 - h2; - c = h1; - } - else - { - // 2 triangle (h1, h3, h5 points) - int32 h1 = V9_h1_ptr[0]; - int32 h3 = V9_h1_ptr[1]; - int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int]; - a = h5 - h1 - h3; - b = h3 - h1; - c = h1; - } - } - else - { - if (x > y) - { - // 3 triangle (h2, h4, h5 points) - int32 h2 = V9_h1_ptr[129]; - int32 h4 = V9_h1_ptr[130]; - int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int]; - a = h2 + h4 - h5; - b = h4 - h2; - c = h5 - h4; - } - else - { - // 4 triangle (h3, h4, h5 points) - int32 h3 = V9_h1_ptr[ 1]; - int32 h4 = V9_h1_ptr[130]; - int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int]; - a = h4 - h3; - b = h3 + h4 - h5; - c = h5 - h4; - } - } - // Calculate height - return (float)((a * x) + (b * y) + c) * _gridIntHeightMultiplier + _gridHeight; -} - -bool GridMap::isHole(int row, int col) const -{ - if (!_holes) - return false; - - int cellRow = row / 8; // 8 squares per cell - int cellCol = col / 8; - int holeRow = row % 8 / 2; - int holeCol = (col - (cellCol * 8)) / 2; - - uint16 hole = _holes[cellRow * 16 + cellCol]; - - return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0; -} - -float GridMap::getMinHeight(float x, float y) const -{ - if (!_minHeight) - return -500.0f; - - static uint32 const indices[] = - { - 3, 0, 4, - 0, 1, 4, - 1, 2, 4, - 2, 5, 4, - 5, 8, 4, - 8, 7, 4, - 7, 6, 4, - 6, 3, 4 - }; - - static float const boundGridCoords[] = - { - 0.0f, 0.0f, - 0.0f, -266.66666f, - 0.0f, -533.33331f, - -266.66666f, 0.0f, - -266.66666f, -266.66666f, - -266.66666f, -533.33331f, - -533.33331f, 0.0f, - -533.33331f, -266.66666f, - -533.33331f, -533.33331f - }; - - Cell cell(x, y); - float gx = x - (int32(cell.GridX()) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS; - float gy = y - (int32(cell.GridY()) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS; - - uint32 quarterIndex = 0; - if (cell.CellY() < MAX_NUMBER_OF_CELLS / 2) - { - if (cell.CellX() < MAX_NUMBER_OF_CELLS / 2) - { - quarterIndex = 4 + (gy > gx); - } - else - quarterIndex = 2 + ((-SIZE_OF_GRIDS - gx) > gy); - } - else if (cell.CellX() < MAX_NUMBER_OF_CELLS / 2) - { - quarterIndex = 6 + ((-SIZE_OF_GRIDS - gx) <= gy); - } - else - quarterIndex = gx > gy; - - quarterIndex *= 3; - - return G3D::Plane( - G3D::Vector3(boundGridCoords[indices[quarterIndex + 0] * 2 + 0], boundGridCoords[indices[quarterIndex + 0] * 2 + 1], _minHeight[indices[quarterIndex + 0]]), - G3D::Vector3(boundGridCoords[indices[quarterIndex + 1] * 2 + 0], boundGridCoords[indices[quarterIndex + 1] * 2 + 1], _minHeight[indices[quarterIndex + 1]]), - G3D::Vector3(boundGridCoords[indices[quarterIndex + 2] * 2 + 0], boundGridCoords[indices[quarterIndex + 2] * 2 + 1], _minHeight[indices[quarterIndex + 2]]) - ).distance(G3D::Vector3(gx, gy, 0.0f)); -} - -float GridMap::getLiquidLevel(float x, float y) const -{ - if (!_liquidMap) - return _liquidLevel; - - x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); - y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); - - int cx_int = ((int)x & (MAP_RESOLUTION - 1)) - _liquidOffY; - int cy_int = ((int)y & (MAP_RESOLUTION - 1)) - _liquidOffX; - - if (cx_int < 0 || cx_int >= _liquidHeight) - return INVALID_HEIGHT; - if (cy_int < 0 || cy_int >= _liquidWidth) - return INVALID_HEIGHT; - - return _liquidMap[cx_int * _liquidWidth + cy_int]; -} - -// Get water state on map -inline LiquidData const GridMap::GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const -{ - LiquidData liquidData; - - // Check water type (if no water return) - if (_liquidGlobalFlags || _liquidFlags) - { - // Get cell - float cx = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS); - float cy = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS); - - int x_int = (int) cx & (MAP_RESOLUTION - 1); - int y_int = (int) cy & (MAP_RESOLUTION - 1); - - // Check water type in cell - int idx=(x_int>>3)*16 + (y_int>>3); - uint8 type = _liquidFlags ? _liquidFlags[idx] : _liquidGlobalFlags; - uint32 entry = _liquidEntry ? _liquidEntry[idx] : _liquidGlobalEntry; - if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(entry)) - { - type &= MAP_LIQUID_TYPE_DARK_WATER; - uint32 liqTypeIdx = liquidEntry->Type; - if (entry < 21) - { - if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y))) - { - uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; - if (!overrideLiquid && area->zone) - { - area = sAreaTableStore.LookupEntry(area->zone); - if (area) - overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; - } - - if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid)) - { - entry = overrideLiquid; - liqTypeIdx = liq->Type; - } - } - } - - type |= 1 << liqTypeIdx; - } - - // Check req liquid type mask - if (type != 0 && (!ReqLiquidType || (ReqLiquidType & type) != 0)) - { - // Check water level: - // Check water height map - int lx_int = x_int - _liquidOffY; - int ly_int = y_int - _liquidOffX; - if (lx_int >= 0 && lx_int < _liquidHeight && ly_int >= 0 && ly_int < _liquidWidth) - { - // Get water level - float liquid_level = _liquidMap ? _liquidMap[lx_int * _liquidWidth + ly_int] : _liquidLevel; - // Get ground level - float ground_level = getHeight(x, y); - - // Check water level and ground level (sub 0.2 for fix some errors) - if (liquid_level >= ground_level && z >= ground_level - 0.2f) - { - // All ok in water -> store data - liquidData.Entry = entry; - liquidData.Flags = type; - liquidData.Level = liquid_level; - liquidData.DepthLevel = ground_level; - - // For speed check as int values - float delta = liquid_level - z; - - if (delta > collisionHeight) - liquidData.Status = LIQUID_MAP_UNDER_WATER; - else if (delta > 0.0f) - liquidData.Status = LIQUID_MAP_IN_WATER; - else if (delta > -0.1f) - liquidData.Status = LIQUID_MAP_WATER_WALK; - else - liquidData.Status = LIQUID_MAP_ABOVE_WATER; - } - } - } - } - - return liquidData; -} - -GridMap* Map::GetGrid(float x, float y) -{ - // half opt method - int gx = (int)(32 - x / SIZE_OF_GRIDS); //grid x - int gy = (int)(32 - y / SIZE_OF_GRIDS); //grid y - - // ensure GridMap is loaded - EnsureGridCreated(GridCoord(63 - gx, 63 - gy)); - - return GridMaps[gx][gy]; + GridCoord const gridCoord = Acore::ComputeGridCoord(x, y); + return GetGridTerrainData(gridCoord); } float Map::GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/, float collisionHeight) const { - if (const_cast(this)->GetGrid(x, y)) - { - // we need ground level (including grid height version) for proper return water level in point - float ground_z = GetHeight(phasemask, x, y, z + Z_OFFSET_FIND_HEIGHT, true, 50.0f); - if (ground) - *ground = ground_z; + // we need ground level (including grid height version) for proper return water level in point + float ground_z = GetHeight(phasemask, x, y, z + Z_OFFSET_FIND_HEIGHT, true, 50.0f); + if (ground) + *ground = ground_z; - LiquidData const& liquidData = const_cast(this)->GetLiquidData(phasemask, x, y, ground_z, collisionHeight, MAP_ALL_LIQUIDS); - switch (liquidData.Status) - { - case LIQUID_MAP_ABOVE_WATER: - return std::max(liquidData.Level, ground_z); - case LIQUID_MAP_NO_WATER: - return ground_z; - default: - return liquidData.Level; - } + LiquidData const& liquidData = const_cast(this)->GetLiquidData(phasemask, x, y, ground_z, collisionHeight, MAP_ALL_LIQUIDS); + switch (liquidData.Status) + { + case LIQUID_MAP_ABOVE_WATER: + return std::max(liquidData.Level, ground_z); + case LIQUID_MAP_NO_WATER: + return ground_z; + default: + return liquidData.Level; } return VMAP_INVALID_HEIGHT_VALUE; @@ -2102,18 +1239,18 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float float Map::GetGridHeight(float x, float y) const { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridTerrainData* gmap = const_cast(this)->GetGridTerrainData(x, y)) return gmap->getHeight(x, y); - return VMAP_INVALID_HEIGHT_VALUE; + return INVALID_HEIGHT; } float Map::GetMinHeight(float x, float y) const { - if (GridMap const* grid = const_cast(this)->GetGrid(x, y)) + if (GridTerrainData const* grid = const_cast(this)->GetGridTerrainData(x, y)) return grid->getMinHeight(x, y); - return -500.0f; + return MIN_HEIGHT; } static inline bool IsInWMOInterior(uint32 mogpFlags) @@ -2156,7 +1293,7 @@ bool Map::GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& flags if (hasVmapAreaInfo || hasDynamicAreaInfo) { // check if there's terrain between player height and object height - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridTerrainData* gmap = const_cast(this)->GetGridTerrainData(x, y)) { float mapHeight = gmap->getHeight(x, y); // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice... @@ -2179,7 +1316,7 @@ uint32 Map::GetAreaId(uint32 phaseMask, float x, float y, float z) const uint32 gridAreaId = 0; float gridMapHeight = INVALID_HEIGHT; - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridTerrainData* gmap = const_cast(this)->GetGridTerrainData(x, y)) { gridAreaId = gmap->getArea(x, y); gridMapHeight = gmap->getHeight(x, y); @@ -2290,7 +1427,7 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z, if (useGridLiquid) { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridTerrainData* gmap = const_cast(this)->GetGridTerrainData(x, y)) { LiquidData const& map_data = gmap->GetLiquidData(x, y, z, collisionHeight, ReqLiquidType); // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER: @@ -2312,7 +1449,7 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z, void Map::GetFullTerrainStatusForPosition(uint32 /*phaseMask*/, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, uint8 reqLiquidType) { - GridMap* gmap = GetGrid(x, y); + GridTerrainData* gmap = GetGridTerrainData(x, y); VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr(); VMAP::AreaAndLiquidData vmapData; @@ -2455,10 +1592,10 @@ void Map::GetFullTerrainStatusForPosition(uint32 /*phaseMask*/, float x, float y float Map::GetWaterLevel(float x, float y) const { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridTerrainData* gmap = const_cast(this)->GetGridTerrainData(x, y)) return gmap->getLiquidLevel(x, y); - else - return 0; + + return INVALID_HEIGHT; } bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const @@ -2625,16 +1762,6 @@ void Map::SendRemoveTransports(Player* player) player->GetSession()->SendPacket(&packet); } -inline void Map::setNGrid(NGridType* grid, uint32 x, uint32 y) -{ - if (x >= MAX_NUMBER_OF_GRIDS || y >= MAX_NUMBER_OF_GRIDS) - { - LOG_ERROR("maps", "map::setNGrid() Invalid grid coordinates found: {}, {}!", x, y); - ABORT(); - } - i_grids[x][y] = grid; -} - void Map::SendObjectUpdates() { UpdateDataMapType update_players; @@ -3717,7 +2844,7 @@ Corpse* Map::ConvertCorpseToBones(ObjectGuid const ownerGuid, bool insignia /*= // ignore bones creating option in case insignia if ((insignia || (IsBattlegroundOrArena() ? sWorld->getBoolConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld->getBoolConfig(CONFIG_DEATH_BONES_WORLD))) && - !IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) + !IsGridCreated(corpse->GetPositionX(), corpse->GetPositionY())) { // Create bones, don't change Corpse bones = new Corpse(); @@ -4139,6 +3266,26 @@ std::string Map::GetDebugInfo() const return sstr.str(); } +uint32 Map::GetCreatedGridsCount() +{ + return _mapGridManager.GetCreatedGridsCount(); +} + +uint32 Map::GetLoadedGridsCount() +{ + return _mapGridManager.GetLoadedGridsCount(); +} + +uint32 Map::GetCreatedCellsInGridCount(uint16 const x, uint16 const y) +{ + return _mapGridManager.GetCreatedCellsInGridCount(x, y); +} + +uint32 Map::GetCreatedCellsInMapCount() +{ + return _mapGridManager.GetCreatedCellsInMapCount(); +} + std::string InstanceMap::GetDebugInfo() const { std::stringstream sstr; diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 54f8d7c2c..33bb8238d 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -26,6 +26,7 @@ #include "GameObjectModel.h" #include "GridDefines.h" #include "GridRefMgr.h" +#include "MapGridManager.h" #include "MapRefMgr.h" #include "ObjectDefines.h" #include "ObjectGuid.h" @@ -33,6 +34,7 @@ #include "Position.h" #include "SharedDefines.h" #include "TaskScheduler.h" +#include "GridTerrainData.h" #include #include #include @@ -81,101 +83,9 @@ struct ScriptAction ScriptInfo const* script; // pointer to static script data }; -// ****************************************** -// Map file format defines -// ****************************************** -struct map_fileheader -{ - uint32 mapMagic; - uint32 versionMagic; - uint32 buildMagic; - uint32 areaMapOffset; - uint32 areaMapSize; - uint32 heightMapOffset; - uint32 heightMapSize; - uint32 liquidMapOffset; - uint32 liquidMapSize; - uint32 holesOffset; - uint32 holesSize; -}; - -#define MAP_AREA_NO_AREA 0x0001 - -struct map_areaHeader -{ - uint32 fourcc; - uint16 flags; - uint16 gridArea; -}; - -#define MAP_HEIGHT_NO_HEIGHT 0x0001 -#define MAP_HEIGHT_AS_INT16 0x0002 -#define MAP_HEIGHT_AS_INT8 0x0004 -#define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008 - -struct map_heightHeader -{ - uint32 fourcc; - uint32 flags; - float gridHeight; - float gridMaxHeight; -}; - -#define MAP_LIQUID_NO_TYPE 0x0001 -#define MAP_LIQUID_NO_HEIGHT 0x0002 - -struct map_liquidHeader -{ - uint32 fourcc; - uint8 flags; - uint8 liquidFlags; - uint16 liquidType; - uint8 offsetX; - uint8 offsetY; - uint8 width; - uint8 height; - float liquidLevel; -}; - -enum LiquidStatus -{ - LIQUID_MAP_NO_WATER = 0x00000000, - LIQUID_MAP_ABOVE_WATER = 0x00000001, - LIQUID_MAP_WATER_WALK = 0x00000002, - LIQUID_MAP_IN_WATER = 0x00000004, - LIQUID_MAP_UNDER_WATER = 0x00000008 -}; - -#define MAP_LIQUID_STATUS_SWIMMING (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER) -#define MAP_LIQUID_STATUS_IN_CONTACT (MAP_LIQUID_STATUS_SWIMMING | LIQUID_MAP_WATER_WALK) - -#define MAP_LIQUID_TYPE_NO_WATER 0x00 -#define MAP_LIQUID_TYPE_WATER 0x01 -#define MAP_LIQUID_TYPE_OCEAN 0x02 -#define MAP_LIQUID_TYPE_MAGMA 0x04 -#define MAP_LIQUID_TYPE_SLIME 0x08 - -#define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME) - -#define MAP_LIQUID_TYPE_DARK_WATER 0x10 - -#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface -#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE -#define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT #define DEFAULT_HEIGHT_SEARCH 50.0f // default search distance to find height at nearby locations #define MIN_UNLOAD_DELAY 1 // immediate unload -struct LiquidData -{ - LiquidData() = default; - - uint32 Entry{0}; - uint32 Flags{0}; - float Level{INVALID_HEIGHT}; - float DepthLevel{INVALID_HEIGHT}; - LiquidStatus Status{LIQUID_MAP_NO_WATER}; -}; - struct PositionFullTerrainStatus { PositionFullTerrainStatus() = default; @@ -196,71 +106,6 @@ enum LineOfSightChecks LINEOFSIGHT_ALL_CHECKS = LINEOFSIGHT_CHECK_VMAP | LINEOFSIGHT_CHECK_GOBJECT_ALL }; -class GridMap -{ - uint32 _flags; - union - { - float* m_V9; - uint16* m_uint16_V9; - uint8* m_uint8_V9; - }; - union - { - float* m_V8; - uint16* m_uint16_V8; - uint8* m_uint8_V8; - }; - int16* _maxHeight; - int16* _minHeight; - // Height level data - float _gridHeight; - float _gridIntHeightMultiplier; - - // Area data - uint16* _areaMap; - - // Liquid data - float _liquidLevel; - uint16* _liquidEntry; - uint8* _liquidFlags; - float* _liquidMap; - uint16 _gridArea; - uint16 _liquidGlobalEntry; - uint8 _liquidGlobalFlags; - uint8 _liquidOffX; - uint8 _liquidOffY; - uint8 _liquidWidth; - uint8 _liquidHeight; - uint16* _holes; - - bool loadAreaData(FILE* in, uint32 offset, uint32 size); - bool loadHeightData(FILE* in, uint32 offset, uint32 size); - bool loadLiquidData(FILE* in, uint32 offset, uint32 size); - bool loadHolesData(FILE* in, uint32 offset, uint32 size); - [[nodiscard]] bool isHole(int row, int col) const; - - // Get height functions and pointers - typedef float (GridMap::*GetHeightPtr) (float x, float y) const; - GetHeightPtr _gridGetHeight; - [[nodiscard]] float getHeightFromFloat(float x, float y) const; - [[nodiscard]] float getHeightFromUint16(float x, float y) const; - [[nodiscard]] float getHeightFromUint8(float x, float y) const; - [[nodiscard]] float getHeightFromFlat(float x, float y) const; - -public: - GridMap(); - ~GridMap(); - bool loadData(char* filaname); - void unloadData(); - - [[nodiscard]] uint16 getArea(float x, float y) const; - [[nodiscard]] inline float getHeight(float x, float y) const {return (this->*_gridGetHeight)(x, y);} - [[nodiscard]] float getMinHeight(float x, float y) const; - [[nodiscard]] float getLiquidLevel(float x, float y) const; - [[nodiscard]] LiquidData const GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const; -}; - // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform #if defined(__GNUC__) #pragma pack(1) @@ -307,9 +152,10 @@ enum EncounterCreditType : uint8 ENCOUNTER_CREDIT_CAST_SPELL = 1, }; -class Map : public GridRefMgr +class Map : public GridRefMgr { friend class MapReference; + friend class GridObjectLoader; public: Map(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent = nullptr); ~Map() override; @@ -348,6 +194,7 @@ public: [[nodiscard]] float GetVisibilityRange() const { return m_VisibleDistance; } void SetVisibilityRange(float range) { m_VisibleDistance = range; } + void OnCreateMap(); //function for setting up visibility distance for maps on per-type/per-Id basis virtual void InitVisibilityDistance(); @@ -358,26 +205,28 @@ public: template void Visit(const Cell& cell, TypeContainerVisitor& visitor); - [[nodiscard]] bool IsRemovalGrid(float x, float y) const - { - GridCoord p = Acore::ComputeGridCoord(x, y); - return !getNGrid(p.x_coord, p.y_coord); - } - - [[nodiscard]] bool IsGridLoaded(float x, float y) const + bool IsGridLoaded(GridCoord const& gridCoord) const; + bool IsGridLoaded(float x, float y) const { return IsGridLoaded(Acore::ComputeGridCoord(x, y)); } + bool IsGridCreated(GridCoord const& gridCoord) const; + bool IsGridCreated(float x, float y) const + { + return IsGridCreated(Acore::ComputeGridCoord(x, y)); + } void LoadGrid(float x, float y); - void LoadAllCells(); - bool UnloadGrid(NGridType& ngrid); + void LoadAllGrids(); + void LoadGridsInRange(Position const& center, float radius); + bool UnloadGrid(MapGridType& grid); virtual void UnloadAll(); - [[nodiscard]] uint32 GetId() const { return i_mapEntry->MapID; } + std::shared_ptr GetGridTerrainDataSharedPtr(GridCoord const& gridCoord); + GridTerrainData* GetGridTerrainData(GridCoord const& gridCoord); + GridTerrainData* GetGridTerrainData(float x, float y); - static bool ExistMap(uint32 mapid, int gx, int gy); - static bool ExistVMap(uint32 mapid, int gx, int gy); + [[nodiscard]] uint32 GetId() const { return i_mapEntry->MapID; } [[nodiscard]] Map const* GetParent() const { return m_parentMap; } @@ -627,8 +476,7 @@ public: // Do whatever you want to all the players in map [including GameMasters], i.e.: param exec = [&](Player* p) { p->Whatever(); } void DoForAllPlayers(std::function exec); - GridMap* GetGrid(float x, float y); - void EnsureGridCreated(const GridCoord&); + void EnsureGridCreated(GridCoord const& gridCoord); [[nodiscard]] bool AllTransportsEmpty() const; // pussywizard void AllTransportsRemovePassengers(); // pussywizard [[nodiscard]] TransportsContainer const& GetAllTransports() const { return _transports; } @@ -659,13 +507,12 @@ public: virtual std::string GetDebugInfo() const; -private: - void LoadMapAndVMap(int gx, int gy); - void LoadVMap(int gx, int gy); - void LoadMap(int gx, int gy, bool reload = false); + uint32 GetCreatedGridsCount(); + uint32 GetLoadedGridsCount(); + uint32 GetCreatedCellsInGridCount(uint16 const x, uint16 const y); + uint32 GetCreatedCellsInMapCount(); - // Load MMap Data - void LoadMMap(int gx, int gy); +private: template void InitializeObject(T* obj); void AddCreatureToMoveList(Creature* c); @@ -679,33 +526,22 @@ private: std::vector _gameObjectsToMove; std::vector _dynamicObjectsToMove; - [[nodiscard]] bool IsGridLoaded(const GridCoord&) const; - void EnsureGridCreated_i(const GridCoord&); + bool EnsureGridLoaded(Cell const& cell); + MapGridType* GetMapGrid(uint16 const x, uint16 const y); - void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } - - [[nodiscard]] NGridType* getNGrid(uint32 x, uint32 y) const - { - ASSERT(x < MAX_NUMBER_OF_GRIDS && y < MAX_NUMBER_OF_GRIDS); - return i_grids[x][y]; - } - - bool EnsureGridLoaded(Cell const&); - [[nodiscard]] bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x, y)->isGridObjectDataLoaded(); } - void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x, y)->setGridObjectDataLoaded(pLoaded); } - - void setNGrid(NGridType* grid, uint32 x, uint32 y); void ScriptsProcess(); - void UpdateActiveCells(const float& x, const float& y, const uint32 t_diff); - void SendObjectUpdates(); protected: + // Type specific code for add/remove to/from grid + template + void AddToGrid(T* object, Cell const& cell); + std::mutex Lock; - std::mutex GridLock; std::shared_mutex MMapLock; + MapGridManager _mapGridManager; MapEntry const* i_mapEntry; uint8 i_spawnMode; uint32 i_InstanceId; @@ -739,10 +575,8 @@ private: //InstanceMaps and BattlegroundMaps... Map* m_parentMap; - NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; - GridMap* GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; - std::bitset marked_cells; - std::bitset marked_cells_large; + std::bitset marked_cells; + std::bitset marked_cells_large; bool i_scriptLock; std::unordered_set i_objectsToRemove; @@ -752,10 +586,6 @@ private: typedef std::multimap ScriptScheduleMap; ScriptScheduleMap m_scriptSchedule; - // Type specific code for add/remove to/from grid - template - void AddToGrid(T* object, Cell const& cell); - template void DeleteFromWorld(T*); @@ -875,16 +705,14 @@ private: template inline void Map::Visit(Cell const& cell, TypeContainerVisitor& visitor) { - const uint32 x = cell.GridX(); - const uint32 y = cell.GridY(); - const uint32 cell_x = cell.CellX(); - const uint32 cell_y = cell.CellY(); + uint32 const grid_x = cell.GridX(); + uint32 const grid_y = cell.GridY(); - if (!cell.NoCreate() || IsGridLoaded(GridCoord(x, y))) - { - EnsureGridLoaded(cell); - getNGrid(x, y)->VisitGrid(cell_x, cell_y, visitor); - } + // If grid is not loaded, nothing to visit. + if (!IsGridLoaded(GridCoord(grid_x, grid_y))) + return; + + GetMapGrid(grid_x, grid_y)->VisitCell(cell.CellX(), cell.CellY(), visitor); } #endif diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 6566a2a20..8b42389e3 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -203,6 +203,7 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, InstanceMap* map = new InstanceMap(GetId(), InstanceId, difficulty, this); ASSERT(map->IsDungeon()); + m_InstancedMaps[InstanceId] = map; map->LoadRespawnTimes(); map->LoadCorpseData(); @@ -212,10 +213,11 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, else map->CreateInstanceScript(false, "", 0); + map->OnCreateMap(); + if (!save) // this is for sure a dungeon (assert above), no need to check here sInstanceSaveMgr->AddInstanceSave(GetId(), InstanceId, difficulty); - m_InstancedMaps[InstanceId] = map; return map; } @@ -237,10 +239,13 @@ BattlegroundMap* MapInstanced::CreateBattleground(uint32 InstanceId, Battlegroun BattlegroundMap* map = new BattlegroundMap(GetId(), InstanceId, this, spawnMode); ASSERT(map->IsBattlegroundOrArena()); + m_InstancedMaps[InstanceId] = map; + map->SetBG(bg); bg->SetBgMap(map); - m_InstancedMaps[InstanceId] = map; + map->OnCreateMap(); + return map; } diff --git a/src/server/game/Maps/MapMgr.cpp b/src/server/game/Maps/MapMgr.cpp index 3a52e5fe3..2b1fe2b3b 100644 --- a/src/server/game/Maps/MapMgr.cpp +++ b/src/server/game/Maps/MapMgr.cpp @@ -19,6 +19,7 @@ #include "Chat.h" #include "DatabaseEnv.h" #include "GridDefines.h" +#include "GridTerrainLoader.h" #include "Group.h" #include "InstanceSaveMgr.h" #include "LFGMgr.h" @@ -83,13 +84,17 @@ Map* MapMgr::CreateBaseMap(uint32 id) if (entry->Instanceable()) map = new MapInstanced(id); else - { map = new Map(id, 0, REGULAR_DIFFICULTY); + + i_maps[id] = map; + + if (!entry->Instanceable()) + { map->LoadRespawnTimes(); map->LoadCorpseData(); } - i_maps[id] = map; + map->OnCreateMap(); } } @@ -303,7 +308,7 @@ bool MapMgr::ExistMapAndVMap(uint32 mapid, float x, float y) int gx = 63 - p.x_coord; int gy = 63 - p.y_coord; - return Map::ExistMap(mapid, gx, gy) && Map::ExistVMap(mapid, gx, gy); + return GridTerrainLoader::ExistMap(mapid, gx, gy) && GridTerrainLoader::ExistVMap(mapid, gx, gy); } bool MapMgr::IsValidMAP(uint32 mapid, bool startUp) diff --git a/src/server/game/Maps/MapMgr.h b/src/server/game/Maps/MapMgr.h index 9cf80a979..2872ddd7c 100644 --- a/src/server/game/Maps/MapMgr.h +++ b/src/server/game/Maps/MapMgr.h @@ -24,6 +24,7 @@ #include "MapInstanced.h" #include "MapUpdater.h" #include "Object.h" +#include "Timer.h" class Transport; class StaticTransport; diff --git a/src/server/game/Movement/Waypoints/WaypointMgr.cpp b/src/server/game/Movement/Waypoints/WaypointMgr.cpp index de437b2cb..7a2596fbf 100644 --- a/src/server/game/Movement/Waypoints/WaypointMgr.cpp +++ b/src/server/game/Movement/Waypoints/WaypointMgr.cpp @@ -20,6 +20,7 @@ #include "GridDefines.h" #include "Log.h" #include "QueryResult.h" +#include "Timer.h" WaypointMgr::WaypointMgr() { diff --git a/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp b/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp index a43907365..1f8402644 100644 --- a/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp @@ -134,10 +134,9 @@ void ScriptMgr::OnDestroyMap(Map* map) }); } -void ScriptMgr::OnLoadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy) +void ScriptMgr::OnLoadGridMap(Map* map, GridTerrainData* gmap, uint32 gx, uint32 gy) { ASSERT(map); - ASSERT(gmap); ForeachMaps(map, [&](WorldMapScript* script) @@ -158,7 +157,7 @@ void ScriptMgr::OnLoadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy) }); } -void ScriptMgr::OnUnloadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy) +void ScriptMgr::OnUnloadGridMap(Map* map, GridTerrainData* gmap, uint32 gx, uint32 gy) { ASSERT(map); ASSERT(gmap); diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index af4b49490..26159984b 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -189,8 +189,8 @@ public: /* FormulaScript */ public: /* MapScript */ void OnCreateMap(Map* map); void OnDestroyMap(Map* map); - void OnLoadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy); - void OnUnloadGridMap(Map* map, GridMap* gmap, uint32 gx, uint32 gy); + void OnLoadGridMap(Map* map, GridTerrainData* gmap, uint32 gx, uint32 gy); + void OnUnloadGridMap(Map* map, GridTerrainData* gmap, uint32 gx, uint32 gy); void OnPlayerEnterMap(Map* map, Player* player); void OnPlayerLeaveMap(Map* map, Player* player); void OnMapUpdate(Map* map, uint32 diff); diff --git a/src/server/game/Scripting/ScriptObject.h b/src/server/game/Scripting/ScriptObject.h index 1dd8500cd..fe6cb2c12 100644 --- a/src/server/game/Scripting/ScriptObject.h +++ b/src/server/game/Scripting/ScriptObject.h @@ -98,10 +98,10 @@ public: virtual void OnDestroy(TMap* /*map*/) { } // Called when a grid map is loaded. - virtual void OnLoadGridMap(TMap* /*map*/, GridMap* /*gmap*/, uint32 /*gx*/, uint32 /*gy*/) { } + virtual void OnLoadGridMap(TMap* /*map*/, GridTerrainData* /*gmap*/, uint32 /*gx*/, uint32 /*gy*/) { } // Called when a grid map is unloaded. - virtual void OnUnloadGridMap(TMap* /*map*/, GridMap* /*gmap*/, uint32 /*gx*/, uint32 /*gy*/) { } + virtual void OnUnloadGridMap(TMap* /*map*/, GridTerrainData* /*gmap*/, uint32 /*gx*/, uint32 /*gy*/) { } // Called when a player enters the map. virtual void OnPlayerEnter(TMap* /*map*/, Player* /*player*/) { } diff --git a/src/server/game/Scripting/ScriptObjectFwd.h b/src/server/game/Scripting/ScriptObjectFwd.h index a7a899e02..35f425eae 100644 --- a/src/server/game/Scripting/ScriptObjectFwd.h +++ b/src/server/game/Scripting/ScriptObjectFwd.h @@ -41,7 +41,7 @@ class CreatureAI; class DynamicObject; class GameObject; class GameObjectAI; -class GridMap; +class GridTerrainData; class Group; class Guardian; class Guild; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index c5f72b809..4b766bc21 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2160,10 +2160,6 @@ void Spell::SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* refere x = pos->GetPositionX(); y = pos->GetPositionY(); - CellCoord p(Acore::ComputeCellCoord(x, y)); - Cell cell(p); - cell.SetNoCreate(); - Map* map = referer->GetMap(); if (searchInWorld) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index c4282b112..80c36b456 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1969,7 +1969,7 @@ void World::SetInitialWorldSettings() if (map) { LOG_INFO("server.loading", ">> Loading All Grids For Map {}", map->GetId()); - map->LoadAllCells(); + map->LoadAllGrids(); } } } diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index a8d767dfd..3a48e5d33 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -104,7 +104,8 @@ public: { "moveflags", HandleDebugMoveflagsCommand, SEC_ADMINISTRATOR, Console::No }, { "unitstate", HandleDebugUnitStateCommand, SEC_ADMINISTRATOR, Console::No }, { "objectcount", HandleDebugObjectCountCommand, SEC_ADMINISTRATOR, Console::Yes}, - { "dummy", HandleDebugDummyCommand, SEC_ADMINISTRATOR, Console::No } + { "dummy", HandleDebugDummyCommand, SEC_ADMINISTRATOR, Console::No }, + { "mapdata", HandleDebugMapDataCommand, SEC_ADMINISTRATOR, Console::No } }; static ChatCommandTable commandTable = { @@ -1373,6 +1374,20 @@ public: handler->SendSysMessage("This command does nothing right now. Edit your local core (cs_debug.cpp) to make it do whatever you need for testing."); return true; } + + static bool HandleDebugMapDataCommand(ChatHandler* handler) + { + Cell cell(handler->GetPlayer()->GetPositionX(), handler->GetPlayer()->GetPositionY()); + Map* map = handler->GetPlayer()->GetMap(); + + handler->PSendSysMessage("GridX {} GridY {}", cell.GridX(), cell.GridY()); + handler->PSendSysMessage("CellX {} CellY {}", cell.CellX(), cell.CellY()); + handler->PSendSysMessage("Created Grids: {} / {}", map->GetCreatedGridsCount(), MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS); + handler->PSendSysMessage("Loaded Grids: {} / {}", map->GetLoadedGridsCount(), MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS); + handler->PSendSysMessage("Created Cells In Grid: {} / {}", map->GetCreatedCellsInGridCount(cell.GridX(), cell.GridY()), MAX_NUMBER_OF_CELLS * MAX_NUMBER_OF_CELLS); + handler->PSendSysMessage("Created Cells In Map: {} / {}", map->GetCreatedCellsInMapCount(), TOTAL_NUMBER_OF_CELLS_PER_MAP * TOTAL_NUMBER_OF_CELLS_PER_MAP); + return true; + } }; void AddSC_debug_commandscript() diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index cbfc4517c..9f7bd9510 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -25,6 +25,7 @@ #include "GameGraveyard.h" #include "GameTime.h" #include "GridNotifiers.h" +#include "GridTerrainLoader.h" #include "Group.h" #include "GuildMgr.h" #include "IPLocation.h" @@ -589,8 +590,8 @@ public: int gridX = 63 - gridCoord.x_coord; int gridY = 63 - gridCoord.y_coord; - uint32 haveMap = Map::ExistMap(object->GetMapId(), gridX, gridY) ? 1 : 0; - uint32 haveVMap = Map::ExistVMap(object->GetMapId(), gridX, gridY) ? 1 : 0; + uint32 haveMap = GridTerrainLoader::ExistMap(object->GetMapId(), gridX, gridY) ? 1 : 0; + uint32 haveVMap = GridTerrainLoader::ExistVMap(object->GetMapId(), gridX, gridY) ? 1 : 0; uint32 haveMMAP = MMAP::MMapFactory::createOrGetMMapMgr()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()) ? 1 : 0; if (haveVMap) @@ -2404,10 +2405,6 @@ public: { Player* player = handler->GetSession()->GetPlayer(); - CellCoord p(Acore::ComputeCellCoord(player->GetPositionX(), player->GetPositionY())); - Cell cell(p); - cell.SetNoCreate(); - Acore::RespawnDo u_do; Acore::WorldObjectWorker worker(player, u_do); Cell::VisitGridObjects(player, worker, player->GetGridActivationRange()); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp index 1dc1995f4..70bcad38e 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp @@ -172,7 +172,6 @@ struct boss_nightbane : public BossAI { if (action == ACTION_START_INTRO) { - me->GetMap()->LoadGrid(-11260.0f, -1771.0f); // load grid at far end of intro path me->GetMap()->SetVisibilityRange(DEFAULT_VISIBILITY_INSTANCE + 100.0f); // see nightbane me->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING); _phase = PHASE_INTRO; diff --git a/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp b/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp index d51538887..99193ef24 100644 --- a/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp +++ b/src/server/scripts/EasternKingdoms/Stratholme/instance_stratholme.cpp @@ -89,8 +89,6 @@ public: if (_baronRunTime > 0) if (Aura* aura = player->AddAura(SPELL_BARON_ULTIMATUM, player)) aura->SetDuration(_baronRunTime * MINUTE * IN_MILLISECONDS); - if (_barthilasrunProgress == DONE) - instance->LoadGrid(3663.229980f, -3619.139893f); } void OnCreatureCreate(Creature* creature) override @@ -261,7 +259,6 @@ public: { if (_zigguratState1 == 2 && _zigguratState2 == 2 && _zigguratState3 == 2) { - instance->LoadGrid(4035.83f, -3336.31f); if (Creature* baron = instance->GetCreature(_baronRivendareGUID)) baron->AI()->Talk(SAY_BRAON_ZIGGURAT_FALL_YELL); @@ -301,7 +298,6 @@ public: DoCastSpellOnPlayers(SPELL_BARON_ULTIMATUM); events.ScheduleEvent(EVENT_BARON_TIME, 60000); - instance->LoadGrid(4035.83f, -3336.31f); if (Creature* baron = instance->GetCreature(_baronRivendareGUID)) baron->AI()->Talk(SAY_BARON_INIT_YELL); } @@ -505,7 +501,6 @@ public: case EVENT_BARON_TIME: { --_baronRunTime; - instance->LoadGrid(4035.83f, -3336.31f); Creature* baron = instance->GetCreature(_baronRivendareGUID); if (baron && !baron->IsInCombat()) { @@ -536,7 +531,6 @@ public: } case EVENT_EXECUTE_PRISONER: { - instance->LoadGrid(4035.83f, -3336.31f); Creature* baron = instance->GetCreature(_baronRivendareGUID); if (baron && baron->IsAlive()) { diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp index 5e6524d3d..93d9618d0 100644 --- a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp +++ b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp @@ -116,7 +116,6 @@ public: ++_defendersKilled; if (_defendersKilled == DEFENDERS_COUNT) { - instance->LoadGrid(-425.89f, -86.07f); if (Creature* jammal = instance->GetCreature(_jammalanGUID)) jammal->AI()->Talk(0); if (GameObject* forcefield = instance->GetGameObject(_forcefieldGUID)) diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp index 03c85d228..34743573d 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp @@ -103,8 +103,6 @@ public: void OnPlayerEnter(Player* player) override { - instance->LoadGrid(1477.94f, 643.22f); - instance->LoadGrid(1641.45f, 988.08f); if (GameObject* gobj = GetGameObject(DATA_ICEBARRIER)) gobj->SendUpdateToPlayer(player); } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp index e0b161d2b..3a0723c82 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp @@ -227,10 +227,6 @@ public: { if (InstanceScript* instance = player->GetInstanceScript()) { - // Instance map's enormous, Hakkar's GRID is not loaded by the time players enter. - // Without this, the creature never says anything, because it doesn't load in time. - player->GetMap()->LoadGrid(-11783.99f, -1655.27f); - if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { hakkar->setActive(true); @@ -254,10 +250,6 @@ public: { if (InstanceScript* instance = player->GetInstanceScript()) { - // Instance map's enormous, Hakkar's GRID is not loaded by the time players enter. - // Without this, the creature never says anything, because it doesn't load in time. - player->GetMap()->LoadGrid(-11783.99f, -1655.27f); - if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { if (hakkar->GetAI()) @@ -280,10 +272,6 @@ public: { if (InstanceScript* instance = player->GetInstanceScript()) { - // Instance map's enormous, Hakkar's GRID is not loaded by the time players enter. - // Without this, the creature never says anything, because it doesn't load in time. - player->GetMap()->LoadGrid(-11783.99f, -1655.27f); - if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { if (hakkar->GetAI()) @@ -306,10 +294,6 @@ public: { if (InstanceScript* instance = player->GetInstanceScript()) { - // Instance map's enormous, Hakkar's GRID is not loaded by the time players enter. - // Without this, the creature never says anything, because it doesn't load in time. - player->GetMap()->LoadGrid(-11783.99f, -1655.27f); - if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { if (hakkar->GetAI()) @@ -332,10 +316,6 @@ public: { if (InstanceScript* instance = player->GetInstanceScript()) { - // Instance map's enormous, Hakkar's GRID is not loaded by the time players enter. - // Without this, the creature never says anything, because it doesn't load in time. - player->GetMap()->LoadGrid(-11783.99f, -1655.27f); - if (Creature* hakkar = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_HAKKAR))) { if (hakkar->GetAI()) diff --git a/src/server/scripts/Events/firework_show/firework_show.cpp b/src/server/scripts/Events/firework_show/firework_show.cpp index bbe92223a..111a754f9 100644 --- a/src/server/scripts/Events/firework_show/firework_show.cpp +++ b/src/server/scripts/Events/firework_show/firework_show.cpp @@ -28,6 +28,7 @@ #include "firework_show_Undercity.h" #include "GameObjectAI.h" #include "GameObjectScript.h" +#include "Timer.h" // , show std::map, FireworkShow const *> const FireworkShowStore = { diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp index 9c3779987..c6a17339a 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp @@ -67,8 +67,6 @@ public: if (instance->GetPlayersCountExceptGMs() == 1) SetData(DATA_ARTHAS_REPOSITION, 2); - EnsureGridLoaded(); - if (plr->getRace() != RACE_HUMAN && plr->getRace() != RACE_DWARF && plr->getRace() != RACE_GNOME) plr->CastSpell(plr, ((plr->getGender() == GENDER_MALE) ? SPELL_HUMAN_MALE : SPELL_HUMAN_FEMALE), true); } @@ -224,7 +222,6 @@ public: { if (!arthas->IsAlive()) { - EnsureGridLoaded(); arthas->setDeathState(DeathState::Dead); arthas->Respawn(); } @@ -352,16 +349,6 @@ public: } } - void EnsureGridLoaded() - { - instance->LoadGrid(LeaderIntroPos1.GetPositionX(), LeaderIntroPos1.GetPositionY()); - instance->LoadGrid(LeaderIntroPos2.GetPositionX(), LeaderIntroPos2.GetPositionY()); - instance->LoadGrid(LeaderIntroPos3.GetPositionX(), LeaderIntroPos3.GetPositionY()); - instance->LoadGrid(LeaderIntroPos4.GetPositionX(), LeaderIntroPos4.GetPositionY()); - instance->LoadGrid(LeaderIntroPos5.GetPositionX(), LeaderIntroPos5.GetPositionY()); - instance->LoadGrid(LeaderIntroPos6.GetPositionX(), LeaderIntroPos6.GetPositionY()); - } - std::string GetSaveData() override { OUT_SAVE_INST_DATA; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp index 952869243..fdbd0b4f7 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp @@ -69,8 +69,6 @@ public: if (instance->GetPlayersCountExceptGMs() <= 1) CleanupInstance(); - EnsureGridLoaded(); - if (_encounterProgress < ENCOUNTER_PROGRESS_BARRELS) player->SendUpdateWorldState(WORLD_STATE_BARRELS_PLANTED, _barrelCount); } @@ -197,9 +195,6 @@ public: { case EVENT_INITIAL_BARRELS_FLAME: { - instance->LoadGrid(instancePositions[0].GetPositionX(), instancePositions[0].GetPositionY()); - instance->LoadGrid(instancePositions[1].GetPositionX(), instancePositions[1].GetPositionY()); - for (ObjectGuid const& guid : _prisonersSet) if (Creature* orc = instance->GetCreature(guid)) { @@ -220,9 +215,6 @@ public: } case EVENT_FINAL_BARRELS_FLAME: { - instance->LoadGrid(instancePositions[0].GetPositionX(), instancePositions[0].GetPositionY()); - instance->LoadGrid(instancePositions[1].GetPositionX(), instancePositions[1].GetPositionY()); - if (_encounterProgress == ENCOUNTER_PROGRESS_NONE) { Map::PlayerList const& players = instance->GetPlayers(); @@ -250,7 +242,6 @@ public: } case EVENT_SUMMON_LIEUTENANT: { - instance->LoadGrid(instancePositions[2].GetPositionX(), instancePositions[2].GetPositionY()); instance->SummonCreature(NPC_LIEUTENANT_DRAKE, instancePositions[2]); break; } @@ -261,7 +252,6 @@ public: if (!thrall->IsAlive()) { ++_attemptsCount; - EnsureGridLoaded(); thrall->SetVisible(false); Reposition(thrall); thrall->setDeathState(DeathState::Dead); @@ -293,12 +283,6 @@ public: } } - void EnsureGridLoaded() - { - for (uint8 i = 0; i < THRALL_POSITIONS_COUNT; ++i) - instance->LoadGrid(thrallPositions[i].GetPositionX(), thrallPositions[i].GetPositionY()); - } - void ReadSaveDataMore(std::istringstream& data) override { data >> _encounterProgress; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp index 9265e4e91..3946eca1f 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp @@ -74,7 +74,6 @@ public: // prevent getting stuck if event fails during boss break _noBossSpawnDelay = true; - instance->LoadGrid(-2023.0f, 7121.0f); if (Creature* medivh = GetCreature(DATA_MEDIVH)) { medivh->Respawn(); diff --git a/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp b/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp index 52d569572..247a414df 100644 --- a/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp +++ b/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp @@ -95,11 +95,9 @@ public: { case TYPE_EAST_WING_PROGRESS: _eastWingProgress = data; - instance->LoadGrid(-56.59f, -269.12f); break; case TYPE_WEST_WING_PROGRESS: _westWingProgress = data; - instance->LoadGrid(132.626f, 625.913f); break; case TYPE_NORTH_WING_PROGRESS: _northWingProgress = data; @@ -113,7 +111,6 @@ public: _pylonsState |= data; if (_pylonsState == ALL_PYLONS_OFF) // all five active, 31 { - instance->LoadGrid(-38.08f, 812.44f); if (Creature* immol = instance->GetCreature(_immoltharGUID)) { immol->setActive(true); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp index 7938f9b75..98b2b1e87 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp @@ -82,9 +82,6 @@ struct boss_kurinnaxx : public BossAI { if (killer) { - killer->GetMap()->LoadGrid(-9502.80f, 2042.65f); // Ossirian grid - killer->GetMap()->LoadGrid(-8538.17f, 1486.09f); // Andorov run path grid - if (Player* player = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) { if (Creature* creature = player->SummonCreature(NPC_ANDOROV, -8538.177f, 1486.0956f, 32.39054f, 3.7638654f, TEMPSUMMON_CORPSE_DESPAWN, 0)) diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp index a4680ea55..40d4b02c4 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp @@ -87,7 +87,6 @@ public: _rajaxWaveCounter == 0 && // if non-zero, encounter is in progress !_andorovGUID) // cleared if he is dead { - instance->LoadGrid(-8538.17f, 1486.09f); // Andorov run path grid if (Creature* creature = player->SummonCreature(NPC_ANDOROV, -8538.177f, 1486.0956f, 32.39054f, 3.7638654f, TEMPSUMMON_CORPSE_DESPAWN, 0)) { creature->setActive(true); diff --git a/src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp b/src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp index b8097f4c1..0fddc3be9 100644 --- a/src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp +++ b/src/server/scripts/Kalimdor/WailingCaverns/instance_wailing_caverns.cpp @@ -64,7 +64,6 @@ public: if (type == TYPE_LORD_COBRAHN && _encounters[TYPE_LORD_SERPENTIS] != DONE) { - instance->LoadGrid(-120.163f, -24.624f); if (Creature* serpentis = instance->GetCreature(SerpentisGUID)) serpentis->AI()->Talk(SAY_SERPENTIS); } @@ -72,7 +71,6 @@ public: if (type != TYPE_MUTANUS && _encounters[TYPE_LORD_COBRAHN] == DONE && _encounters[TYPE_LORD_PYTHAS] == DONE && _encounters[TYPE_LADY_ANACONDRA] == DONE && _encounters[TYPE_LORD_SERPENTIS] == DONE) { - instance->LoadGrid(-134.97f, 125.402f); if (Creature* disciple = instance->GetCreature(DiscipleOfNaralexGUID)) disciple->AI()->Talk(SAY_DISCIPLE); } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp index c2dbb9b1e..d70eb3b62 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp @@ -63,7 +63,6 @@ public: { if (GetBossState(DATA_HALION_INTRO_DONE) != DONE && GetBossState(DATA_GENERAL_ZARITHRIAN) == DONE) { - instance->LoadGrid(3156.0f, 537.0f); if (Creature* halionController = instance->GetCreature(HalionControllerGUID)) halionController->AI()->DoAction(ACTION_INTRO_HALION); } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp index 7669ed17a..fd43fce38 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp @@ -325,7 +325,6 @@ public: } else { - instance->LoadGrid(PathWaypoints[PATH_WP_COUNT - 1].GetPositionX(), PathWaypoints[PATH_WP_COUNT - 1].GetPositionY()); creature->UpdatePosition(PathWaypoints[PATH_WP_COUNT - 1], true); creature->StopMovingOnCurrentPos(); } @@ -515,7 +514,6 @@ public: { break; } - instance->LoadGrid(LeaderEscapePos.GetPositionX(), LeaderEscapePos.GetPositionY()); if (Creature* c = instance->GetCreature(NPC_LeaderGUID)) { if (!c->IsAlive()) @@ -567,7 +565,6 @@ public: case DATA_LICH_KING: if (data == DONE) { - instance->LoadGrid(PathWaypoints[0].GetPositionX(), PathWaypoints[0].GetPositionY()); EncounterMask |= (1 << DATA_LICH_KING); if (Creature* c = instance->GetCreature(NPC_LeaderGUID)) c->setActive(false); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp index e91e0b954..337415ebb 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp @@ -78,7 +78,6 @@ public: { InstanceScript::OnPlayerEnter(player); - instance->LoadGrid(LeaderIntroPos.GetPositionX(), LeaderIntroPos.GetPositionY()); if (Creature* c = instance->GetCreature(GetGuidData(DATA_LEADER_FIRST_GUID))) c->AI()->SetData(DATA_START_INTRO, 0); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 08932e308..884cda64a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -1537,7 +1537,6 @@ public: if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && instance->GetBossState(DATA_SINDRAGOSA) != IN_PROGRESS) { - player->GetMap()->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); if (Creature* sindragosa = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_SINDRAGOSA))) sindragosa->AI()->DoAction(ACTION_START_FROSTWYRM); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 3d7970ead..0393ace0c 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -747,8 +747,6 @@ public: me->setActive(true); me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->SetImmuneToAll(true); - // Load Grid with Sister Svalna - me->GetMap()->LoadGrid(4356.71f, 2484.33f); if (Creature* svalna = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SISTER_SVALNA))) svalna->AI()->DoAction(ACTION_START_GAUNTLET); for (uint32 i = 0; i < 4; ++i) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index f2640d9c5..e62411087 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -651,7 +651,6 @@ public: FrostwyrmGUIDs.erase(creature->GetSpawnId()); if (FrostwyrmGUIDs.empty()) { - instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos)) boss->AI()->DoAction(ACTION_START_FROSTWYRM); } @@ -1190,7 +1189,6 @@ public: if (GameObject* pillars = instance->GetGameObject(PillarsUnchainedGUID)) pillars->SetRespawnTime(7 * DAY); - instance->LoadGrid(JainaSpawnPos.GetPositionX(), JainaSpawnPos.GetPositionY()); instance->SummonCreature(NPC_LADY_JAINA_PROUDMOORE_QUEST, JainaSpawnPos); instance->SummonCreature(NPC_MURADIN_BRONZEBEARD_QUEST, MuradinSpawnPos); instance->SummonCreature(NPC_UTHER_THE_LIGHTBRINGER_QUEST, UtherSpawnPos); diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index f9b1357e1..550a84743 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -821,8 +821,6 @@ public: if (state == DONE) { _speakTimer = 1; - // Load KT's grid so he can talk - instance->LoadGrid(3763.43f, -5115.87f); } else if (state == NOT_STARTED) { @@ -1061,8 +1059,6 @@ public: switch (events.ExecuteEvent()) { case EVENT_KELTHUZAD_WING_TAUNT: - // Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work. - instance->LoadGrid(3749.67f, -5114.06f); if (Creature* kelthuzad = instance->GetCreature(_kelthuzadGUID)) { kelthuzad->AI()->Talk(_currentWingTaunt); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index a987a7c82..04ab6e9a7 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -178,7 +178,6 @@ public: void OnPlayerEnter(Player* player) override { // mimiron tram: - instance->LoadGrid(2307.0f, 284.632f); if (GameObject* MimironTram = instance->GetGameObject(m_mimironTramGUID)) { player->UpdateVisibilityOf(MimironTram); @@ -537,10 +536,7 @@ public: break; case GO_KEEPERS_GATE: if (GetData(TYPE_MIMIRON) == DONE && GetData(TYPE_FREYA) == DONE && GetData(TYPE_HODIR) == DONE && GetData(TYPE_THORIM) == DONE) - { - instance->LoadGrid(1903.0f, 248.0f); gameObject->RemoveGameObjectFlag(GO_FLAG_LOCKED); - } m_keepersgateGUID = gameObject->GetGUID(); break; @@ -752,8 +748,6 @@ public: case EVENT_TOWER_OF_FROST_DESTROYED: case EVENT_TOWER_OF_FLAMES_DESTROYED: { - instance->LoadGrid(364.0f, -16.0f); //make sure leviathan is loaded - instance->LoadGrid(364.0f, 32.0f); //make sure Mimiron's and Thorim's Targetting Crystal are loaded m_leviathanTowers[type - EVENT_TOWER_OF_LIFE_DESTROYED] = data; for (uint8 i = 0; i < 2; ++i) { diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp index d59e2fb17..77d1b0a73 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp @@ -89,7 +89,7 @@ void UpdateCreatureHalaa(ObjectGuid::LowType spawnId, Map* map, float x, float y sObjectMgr->AddCreatureToGrid(spawnId, &data); // Spawn if necessary (loaded grids only) - if (!map->Instanceable() && !map->IsRemovalGrid(x, y)) + if (!map->Instanceable() && !map->IsGridCreated(x, y)) { Creature* creature = new Creature(); if (!creature->LoadCreatureFromDB(spawnId, map, true, true)) diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp index 84a4c6656..a3354a2a2 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp @@ -125,7 +125,6 @@ struct boss_kelidan_the_breaker : public BossAI { Talk(SAY_DIE); _JustDied(); - me->GetMap()->LoadGrid(0, -111.0f); } void ApplyImmunities(bool apply) diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp index 2ed91f6f9..c490108ed 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp @@ -99,7 +99,6 @@ public: if (type == DATA_ENTERED_ROOM && data == DATA_ENTERED_ROOM && RescueTimer == 100 * MINUTE * IN_MILLISECONDS) { DoCastSpellOnPlayers(SPELL_KARGATHS_EXECUTIONER_1); - instance->LoadGrid(230, -80); if (Creature* kargath = GetCreature(DATA_KARGATH)) sCreatureTextMgr->SendChat(kargath, GetTeamIdInInstance() == TEAM_ALLIANCE ? 3 : 4, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); From 91da92f33fad2f6daabef4e63862e801fae82d81 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Sat, 15 Feb 2025 11:45:12 +0100 Subject: [PATCH 36/97] fix(Core/SpellQueue): Fix undefined behavior when processing SpellQueue. (#21459) --- src/server/game/Entities/Player/PlayerUpdates.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index 7dccbf189..dcc77209d 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -2377,7 +2377,15 @@ void Player::ProcessSpellQueue() if (CanExecutePendingSpellCastRequest(spellInfo)) { ExecuteOrCancelSpellCastRequest(&request); - SpellQueue.pop_front(); // Remove from the queue + + // ExecuteOrCancelSpellCastRequest() can lead to clearing the SpellQueue. + // Example scenario: + // Handling a spell → Dealing damage to yourself (e.g., spell_pri_vampiric_touch) → + // Killing yourself → Player::setDeathState() → SpellQueue.clear(). + // Calling std::deque::pop_front() on an empty deque results in undefined behavior, + // so an additional check is added. + if (!SpellQueue.empty()) + SpellQueue.pop_front(); } else // If the first spell can't execute, stop processing break; From fe206c71385aac5e12e13f436baa9273885ca3f2 Mon Sep 17 00:00:00 2001 From: demetrzz <60552737+demetrzz@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:02:27 +0300 Subject: [PATCH 37/97] fix(Scripts/Spells): Corrected shaman 8/8 T2 set bonus damage proc (#21432) Co-authored-by: pavel_k --- src/server/scripts/Spells/spell_shaman.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 28b61ef54..ba882e45b 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -877,11 +877,10 @@ class spell_sha_item_lightning_shield_trigger : public AuraScript { return ValidateSpellInfo({ SPELL_SHAMAN_ITEM_MANA_SURGE }); } - - void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { PreventDefaultAction(); - GetTarget()->CastSpell(GetTarget(), SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE, true, nullptr, aurEff); + GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE, true, nullptr, aurEff); } void Register() override From 19847395eb371ab9eb8df5c3ef5464c0557d8a27 Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Sat, 15 Feb 2025 13:12:13 +0100 Subject: [PATCH 38/97] fix(CI/Windows): Bump openssl version (#21458) --- apps/installer/includes/os_configs/windows.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/installer/includes/os_configs/windows.sh b/apps/installer/includes/os_configs/windows.sh index 39d8eca6b..59c657899 100644 --- a/apps/installer/includes/os_configs/windows.sh +++ b/apps/installer/includes/os_configs/windows.sh @@ -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 --force --version=3.3.2 +choco install -y --skip-checksums $INSTALL_ARGS openssl --force --version=3.4.1 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 From 8f0036959906f250434d64296b04bb19df29729b Mon Sep 17 00:00:00 2001 From: Smirnov Sergey Date: Sat, 15 Feb 2025 15:26:52 +0300 Subject: [PATCH 39/97] fix (DB/SAI) [Howling Fjord] Attack to Valgarde. Dragonflayer Invader and Worg. Valgarde Defender. (#21434) --- .../fix-AttackToValgard-rev1.sql | 238 ++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 data/sql/updates/pending_db_world/fix-AttackToValgard-rev1.sql diff --git a/data/sql/updates/pending_db_world/fix-AttackToValgard-rev1.sql b/data/sql/updates/pending_db_world/fix-AttackToValgard-rev1.sql new file mode 100644 index 000000000..2f07103c8 --- /dev/null +++ b/data/sql/updates/pending_db_world/fix-AttackToValgard-rev1.sql @@ -0,0 +1,238 @@ +-- Dragonflayer Invader - Set detection_range +UPDATE `creature_template` SET `detection_range` = 25 WHERE (`entry` = 24051); + +-- Dragonflayer Invader - Set position, spawntimesecs, MovementType +UPDATE `creature` SET `position_x` = 762.207, `position_y` = -4894.027, `position_z` = 2.9162, `orientation` = 4.143, `spawntimesecs` = 15, `MovementType` = 2 WHERE (`guid` = 118766 AND `id1` = 24051); +UPDATE `creature` SET `position_x` = 762.207, `position_y` = -4894.027, `position_z` = 2.9162, `orientation` = 4.143, `spawntimesecs` = 37, `MovementType` = 2 WHERE (`guid` = 118770 AND `id1` = 24051); +UPDATE `creature` SET `position_x` = 766.356, `position_y` = -4971.977, `position_z` = 2.2148, `orientation` = 2.621, `spawntimesecs` = 20, `MovementType` = 2 WHERE (`guid` = 118767 AND `id1` = 24051); +UPDATE `creature` SET `position_x` = 766.356, `position_y` = -4971.977, `position_z` = 2.2148, `orientation` = 2.621, `spawntimesecs` = 24, `MovementType` = 2 WHERE (`guid` = 118771 AND `id1` = 24051); +UPDATE `creature` SET `position_x` = 803.852, `position_y` = -4963.192, `position_z` = 0.5461, `orientation` = 3.055, `spawntimesecs` = 28, `MovementType` = 2 WHERE (`guid` = 118768 AND `id1` = 24051); +UPDATE `creature` SET `position_x` = 803.852, `position_y` = -4963.192, `position_z` = 0.5461, `orientation` = 3.055, `spawntimesecs` = 32, `MovementType` = 2 WHERE (`guid` = 118772 AND `id1` = 24051); +UPDATE `creature` SET `position_x` = 789.250, `position_y` = -4909.428, `position_z` = 0.1650, `orientation` = 3.562, `spawntimesecs` = 18, `MovementType` = 2 WHERE (`guid` = 118769 AND `id1` = 24051); +UPDATE `creature` SET `position_x` = 789.250, `position_y` = -4909.428, `position_z` = 0.1650, `orientation` = 3.562, `spawntimesecs` = 44, `MovementType` = 2 WHERE (`guid` = 118773 AND `id1` = 24051); + +-- Dragonflayer Invader - SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE (`entry` = 24051); +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24051); +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 +(24051, 0, 0, 0, 9, 0, 100, 0, 5700, 11700, 5700, 11700, 8, 25, 11, 27577, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Invader - In Combat - Cast Intercept'), +(24051, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Invader - Corpse removed after 5s'), +(24051, 0, 2, 0, 9, 0, 100, 0, 8700, 14700, 8700, 14700, 10, 25, 11, 42870, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Invader - In Combat - Throw Dragonflayer Harpoon'), +(24051, 0, 3, 0, 4, 0, 25, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Invader - When AGRO - Talk'); + +-- Dragonflayer Invader - Set PathID and Waypoints +DELETE FROM `creature_addon` WHERE (`guid` = 118766 AND `path_id` = 1187660); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (118766, 1187660, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 118770 AND `path_id` = 1187700); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (118770, 1187700, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 118769 AND `path_id` = 1187690); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (118769, 1187690, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 118773 AND `path_id` = 1187730); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (118773, 1187730, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 118767 AND `path_id` = 1187670); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (118767, 1187670, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 118771 AND `path_id` = 1187710); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (118771, 1187710, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 118768 AND `path_id` = 1187680); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (118768, 1187680, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 118772 AND `path_id` = 1187720); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (118772, 1187720, 0, 0, 1, 0, 0, NULL); + +DELETE FROM `waypoint_data` WHERE (`id` = 1187660); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1187660, 1, 751.2, -4911.4, 2.8, NULL, 0, 1, 0, 100, 0), +(1187660, 2, 738.44, -4927.28, 5.868, NULL, 0, 1, 0, 100, 0), +(1187660, 3, 714.15, -4936.8, 6.437, NULL, 0, 1, 0, 100, 0); + +DELETE FROM `waypoint_data` WHERE (`id` = 1187700); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1187700, 1, 751.2, -4911.4, 2.8, NULL, 0, 1, 0, 100, 0), +(1187700, 2, 738.44, -4927.28, 5.868, NULL, 0, 1, 0, 100, 0), +(1187700, 3, 714.15, -4936.8, 6.437, NULL, 0, 1, 0, 100, 0); + +DELETE FROM `waypoint_data` WHERE (`id` = 1187690); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1187690, 1, 742.35, -4934.59, 5.643, NULL, 0, 1, 0, 100, 0), +(1187690, 2, 713.52, -4951.19, 4.560, NULL, 0, 1, 0, 100, 0); + +DELETE FROM `waypoint_data` WHERE (`id` = 1187730); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1187730, 1, 742.35, -4934.59, 5.643, NULL, 0, 1, 0, 100, 0), +(1187730, 2, 713.52, -4951.19, 4.560, NULL, 0, 1, 0, 100, 0); + +DELETE FROM `waypoint_data` WHERE (`id` = 1187670); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1187670, 1, 747.06, -4958.82, 2.191, NULL, 0, 1, 0, 100, 0), +(1187670, 2, 732.09, -4983.97, 4.683, NULL, 0, 1, 0, 100, 0); + +DELETE FROM `waypoint_data` WHERE (`id` = 1187710); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1187710, 1, 747.06, -4958.82, 2.191, NULL, 0, 1, 0, 100, 0), +(1187710, 2, 732.09, -4983.97, 4.683, NULL, 0, 1, 0, 100, 0); + +DELETE FROM `waypoint_data` WHERE (`id` = 1187680); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1187680, 1, 747.06, -4958.82, 2.191, NULL, 0, 1, 0, 100, 0), +(1187680, 2, 732.09, -4983.97, 4.683, NULL, 0, 1, 0, 100, 0); + +DELETE FROM `waypoint_data` WHERE (`id` = 1187720); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1187720, 1, 747.06, -4958.82, 2.191, NULL, 0, 1, 0, 100, 0), +(1187720, 2, 732.09, -4983.97, 4.683, NULL, 0, 1, 0, 100, 0); + +-- Dragonflayer Worg - Set detection_range, skinloot +UPDATE `creature_template` SET `detection_range` = 25, `skinloot` = 0 WHERE (`entry` = 24063); + +-- Dragonflayer Worg - Set position, spawntimesecs, MovementType +UPDATE `creature` SET `position_x` = 765.90, `position_y` = -4908.08, `position_z` = 1.91220, `orientation` = 4.45437, `spawntimesecs` = 12, `MovementType` = 2 WHERE (`guid` = 120557 AND `id1` = 24063); +UPDATE `creature` SET `position_x` = 769.99, `position_y` = -4892.57, `position_z` = 2.75514, `orientation` = 3.57080, `spawntimesecs` = 25, `MovementType` = 2 WHERE (`guid` = 120558 AND `id1` = 24063); +UPDATE `creature` SET `position_x` = 764.44, `position_y` = -4947.20, `position_z` = 2.50482, `orientation` = 1.99215, `spawntimesecs` = 15, `MovementType` = 2 WHERE (`guid` = 120559 AND `id1` = 24063); +UPDATE `creature` SET `position_x` = 779.27, `position_y` = -4960.70, `position_z` = 1.67408, `orientation` = 3.18596, `spawntimesecs` = 28, `MovementType` = 2 WHERE (`guid` = 120560 AND `id1` = 24063); +UPDATE `creature` SET `position_x` = 809.12, `position_y` = -4942.37, `position_z` = 0.99842, `orientation` = 3.28884, `spawntimesecs` = 23, `MovementType` = 2 WHERE (`guid` = 120561 AND `id1` = 24063); + +-- Dragonflayer Worg - SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE (`entry` = 24063); +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24063); +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 +(24063, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Worg - Corpse removed after 5s'), +(24063, 0, 2, 0, 0, 0, 70, 0, 5000, 10000, 5000, 10000, 0, 0, 11, 7367, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Worg - Cast Infected Bite'); + +-- Dragonflayer Worg - Set PathID +DELETE FROM `creature_addon` WHERE (`guid` = 120557 AND `path_id` = 1205570); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (120557, 1205570, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 120558 AND `path_id` = 1205580); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (120558, 1205580, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 120559 AND `path_id` = 1205590); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (120559, 1205590, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 120560 AND `path_id` = 1205600); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (120560, 1205600, 0, 0, 1, 0, 0, NULL); +DELETE FROM `creature_addon` WHERE (`guid` = 120561 AND `path_id` = 1205610); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) +VALUES (120561, 1205610, 0, 0, 1, 0, 0, NULL); + +-- Dragonflayer Worg - Set Waypoints +DELETE FROM `waypoint_data` WHERE (`id` = 1205570); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1205570, 1, 761.489, -4920.273, 2.7210, NULL, 0, 1, 0, 100, 0), +(1205570, 2, 734.507, -4943.745, 5.4293, NULL, 0, 1, 0, 100, 0), +(1205570, 3, 720.222, -4967.502, 5.9298, NULL, 0, 1, 0, 100, 0); +DELETE FROM `waypoint_data` WHERE (`id` = 1205580); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1205580, 1, 742.317, -4907.741, 3.3050, NULL, 0, 1, 0, 100, 0), +(1205580, 2, 735.411, -4925.406, 6.1833, NULL, 0, 1, 0, 100, 0), +(1205580, 3, 716.655, -4939.511, 5.9821, NULL, 0, 1, 0, 100, 0); +DELETE FROM `waypoint_data` WHERE (`id` = 1205590); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1205590, 1, 757.529, -4931.115, 4.1180, NULL, 0, 1, 0, 100, 0), +(1205590, 2, 733.010, -4944.042, 5.4884, NULL, 0, 1, 0, 100, 0), +(1205590, 3, 716.655, -4939.511, 5.9821, NULL, 0, 1, 0, 100, 0); +DELETE FROM `waypoint_data` WHERE (`id` = 1205600); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1205600, 1, 718.531, -4963.948, 5.33493, 4.47765, 0, 1, 0, 100, 0), +(1205600, 2, 718.978, -4979.252, 6.09930, 4.61902, 0, 1, 0, 100, 0); +DELETE FROM `waypoint_data` WHERE (`id` = 1205610); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) +VALUES +(1205610, 1, 809.12, -4942.37, 0.99842, NULL, 0, 1, 0, 100, 0), +(1205610, 2, 749.53, -4933.65, 5.18420, NULL, 0, 1, 0, 100, 0), +(1205610, 3, 734.90, -4979.91, 4.04356, NULL, 0, 1, 0, 100, 0), +(1205610, 4, 722.70, -4987.73, 6.33793, NULL, 0, 1, 0, 100, 0); + +-- Valgarde Defender - Set Comment +UPDATE `creature` SET `Comment` = "has guid specific SAI" WHERE (`id1` = 23739) AND (`guid` IN (113665, 113664, 113644, 113663)); + +-- Valgarde Defender - Add 'DONT_OVERRIDE_SAI_ENTRY' Flag +UPDATE `creature_template` SET `flags_extra` = `flags_extra`|134217728 WHERE (`entry` = 23739); + +-- Valgarde Defender - Set position and spawntimesecs for Defenders outside the gate +UPDATE `creature` SET `position_x` = 717.426, `position_y` = -4977.064, `position_z` = 6.1085, `orientation` = 0.9687, `spawntimesecs` = 45, `MovementType` = 0 WHERE (`guid` = 113665 AND `id1` = 23739); +UPDATE `creature` SET `position_x` = 717.615, `position_y` = -4991.929, `position_z` = 6.7516, `orientation` = 0.1786, `spawntimesecs` = 45, `MovementType` = 0 WHERE (`guid` = 113664 AND `id1` = 23739); +UPDATE `creature` SET `position_x` = 705.699, `position_y` = -4934.567, `position_z` = 6.4967, `orientation` = 0.3325, `spawntimesecs` = 45, `MovementType` = 0 WHERE (`guid` = 113644 AND `id1` = 23739); +UPDATE `creature` SET `position_x` = 709.157, `position_y` = -4947.396, `position_z` = 4.4368, `orientation` = 0.4260, `spawntimesecs` = 45, `MovementType` = 0 WHERE (`guid` = 113663 AND `id1` = 23739); + +-- Valgarde Defender - SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE (`entry` = 23739); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23739); +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 +(23739, 0, 0, 0, 0, 0, 100, 0, 0, 0, 2300, 3900, 0, 0, 11, 6660, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - In Combat - Cast Shoot'), +(23739, 0, 1, 0, 0, 0, 100, 0, 5000, 10000, 3000, 5000, 0, 0, 11, 31827, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - In Combat - Cast Heroic Strike'); + +-- Valgarde Defender - Set Guid SmartAI for Defenders outside the gate +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = -113665); +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 +(-113665, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - Corpse removed after 5s'), +(-113665, 0, 3, 0, 4, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - When AGRO - Talk'), +(-113665, 0, 4, 0, 0, 0, 100, 0, 1000, 2000, 1000, 2000, 0, 0, 39, 25, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - In Combat - Call HELP'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = -113664); +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 +(-113664, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - Corpse removed after 5s'), +(-113664, 0, 3, 0, 4, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - When AGRO - Talk'), +(-113664, 0, 4, 0, 0, 0, 100, 0, 1000, 2000, 1000, 2000, 0, 0, 39, 25, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - In Combat - Call HELP'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = -113644); +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 +(-113644, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - Corpse removed after 5s'), +(-113644, 0, 3, 0, 4, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - When AGRO - Talk'), +(-113644, 0, 4, 0, 0, 0, 100, 0, 1000, 2000, 1000, 2000, 0, 0, 39, 25, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - In Combat - Call HELP'); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = -113663); +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 +(-113663, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - Corpse removed after 5s'), +(-113663, 0, 3, 0, 4, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - When AGRO - Talk'), +(-113663, 0, 4, 0, 0, 0, 100, 0, 1000, 2000, 1000, 2000, 0, 0, 39, 25, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Defender - In Combat - Call HELP'); + +-- Valgarde Defender - Text speach +DELETE FROM `creature_text` WHERE `CreatureID` = 23739; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) +VALUES +(23739, 0, 0, 'Don\'t let those monsters through the gate! Stand firm, soldiers!', 12, 0, 100, 0, 0, 0, 22692, 0, 'Valgarde Defender'), +(23739, 0, 1, 'FIRE! FIRE!', 12, 0, 100, 0, 0, 0, 22689, 0, 'Valgarde Defender'), +(23739, 0, 2, 'Shoot it between the eyes! Those beasts are vulnerable there!', 12, 0, 100, 0, 0, 0, 22690, 0, 'Valgarde Defender'), +(23739, 0, 3, 'Invader incoming!', 12, 0, 100, 0, 0, 0, 22691, 0, 'Valgarde Defender'), +(23739, 0, 4, 'It\'s coming right for us!', 12, 0, 100, 0, 0, 0, 22688, 0, 'Valgarde Defender'); + +-- Valgarde Harpoon Target - SmartAI and Template Movement (Movement values Sniffed). +DELETE FROM `creature_template_movement` WHERE (`CreatureId` = 23821); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(23821, 0, 0, 1, 1, 0, 0, 0); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23821; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23821); +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 +(23821, 0, 0, 0, 8, 0, 100, 512, 61588, 0, 0, 0, 0, 0, 11, 52955, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Harpoon Target - On Spellhit \'Blazing Harpoon\' - Cast \'Torch\''), +(23821, 0, 1, 1, 1, 0, 100, 513, 1000, 1000, 1000, 1000, 0, 0, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Harpoon Target - Out of Combat - Disable Combat Movement (No Repeat)'), +(23821, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Harpoon Target - Out of Combat - Set Reactstate Passive (No Repeat)'); From e5dbc39cc5eacbdd0db3b2a2a5858046721b3989 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 15 Feb 2025 12:27:57 +0000 Subject: [PATCH 40/97] chore(DB): import pending files Referenced commit(s): 8f0036959906f250434d64296b04bb19df29729b --- .../fix-AttackToValgard-rev1.sql => db_world/2025_02_15_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/fix-AttackToValgard-rev1.sql => db_world/2025_02_15_00.sql} (99%) diff --git a/data/sql/updates/pending_db_world/fix-AttackToValgard-rev1.sql b/data/sql/updates/db_world/2025_02_15_00.sql similarity index 99% rename from data/sql/updates/pending_db_world/fix-AttackToValgard-rev1.sql rename to data/sql/updates/db_world/2025_02_15_00.sql index 2f07103c8..5196f5299 100644 --- a/data/sql/updates/pending_db_world/fix-AttackToValgard-rev1.sql +++ b/data/sql/updates/db_world/2025_02_15_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_14_00 -> 2025_02_15_00 -- Dragonflayer Invader - Set detection_range UPDATE `creature_template` SET `detection_range` = 25 WHERE (`entry` = 24051); From fae07daa4ca28a1ad2f469776d643b33f59507bc Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Sat, 15 Feb 2025 14:08:49 +0100 Subject: [PATCH 41/97] fix(Scripts/Outland): LoadMinionData buffer overflow (#21461) --- src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp | 3 ++- .../MagtheridonsLair/instance_magtheridons_lair.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp b/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp index df6afb52e..b475bda97 100644 --- a/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp +++ b/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp @@ -38,7 +38,8 @@ MinionData const minionData[] = { NPC_KROSH_FIREHAND, DATA_MAULGAR }, { NPC_OLM_THE_SUMMONER, DATA_MAULGAR }, { NPC_KIGGLER_THE_CRAZED, DATA_MAULGAR }, - { NPC_BLINDEYE_THE_SEER, DATA_MAULGAR } + { NPC_BLINDEYE_THE_SEER, DATA_MAULGAR }, + { 0, 0 } // END }; class instance_gruuls_lair : public InstanceMapScript diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp index f4c9e6b19..f14512908 100644 --- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp @@ -32,7 +32,8 @@ DoorData const doorData[] = MinionData const minionData[] = { - { NPC_HELLFIRE_CHANNELER, DATA_MAGTHERIDON } + { NPC_HELLFIRE_CHANNELER, DATA_MAGTHERIDON }, + { 0, 0 } // END }; class instance_magtheridons_lair : public InstanceMapScript From 0d37ff292b581d6652746e87b59a9f94fe211846 Mon Sep 17 00:00:00 2001 From: sudlud Date: Sat, 15 Feb 2025 14:10:46 +0100 Subject: [PATCH 42/97] fix(CI/nopch-module-build): ensure build continues after errors (#21457) --- .github/actions/linux-build/action.yml | 9 ++++++++- .github/workflows/core_modules_build.yml | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/actions/linux-build/action.yml b/.github/actions/linux-build/action.yml index caf3c6047..fc1bc2466 100644 --- a/.github/actions/linux-build/action.yml +++ b/.github/actions/linux-build/action.yml @@ -31,6 +31,11 @@ inputs: description: Max allowed error count before compilation stops required: false type: number + keepgoing: + default: false + description: Flag to continue build after errors + required: false + type: boolean runs: using: composite steps: @@ -121,7 +126,9 @@ runs: - name: build shell: bash working-directory: "${{ github.workspace }}/build" - run: cmake --build . --config "Release" -j "$(($(nproc) + 2))" + run: | + # '--' passes '--keep-going' to the underlying build system (make) + cmake --build . --config "Release" -j "$(($(nproc) + 2))" ${{ inputs.keepgoing == 'true' && '-- --keep-going' || '' }} - name: install shell: bash diff --git a/.github/workflows/core_modules_build.yml b/.github/workflows/core_modules_build.yml index 38d930cec..45683f2b4 100644 --- a/.github/workflows/core_modules_build.yml +++ b/.github/workflows/core_modules_build.yml @@ -50,3 +50,4 @@ jobs: modules: true pch: false maxerrors: 0 + keepgoing: true From a5a8ef92b41bb7972e97d375005f66266544354f Mon Sep 17 00:00:00 2001 From: Rocco Silipo <108557877+Rorschach91@users.noreply.github.com> Date: Sat, 15 Feb 2025 17:13:57 +0100 Subject: [PATCH 43/97] fix (DB/Creature) Correct a missing link in Valgarde Harpoon Target SmartAI (#21462) --- .../updates/pending_db_world/Valgarde_harpoon_target.sql | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 data/sql/updates/pending_db_world/Valgarde_harpoon_target.sql diff --git a/data/sql/updates/pending_db_world/Valgarde_harpoon_target.sql b/data/sql/updates/pending_db_world/Valgarde_harpoon_target.sql new file mode 100644 index 000000000..eeaf5d2cd --- /dev/null +++ b/data/sql/updates/pending_db_world/Valgarde_harpoon_target.sql @@ -0,0 +1,9 @@ + +-- Fix Missing Link +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23821; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 23821); +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 +(23821, 0, 0, 0, 8, 0, 100, 512, 61588, 0, 0, 0, 0, 0, 11, 52955, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Harpoon Target - On Spellhit \'Blazing Harpoon\' - Cast \'Torch\''), +(23821, 0, 1, 2, 1, 0, 100, 513, 1000, 1000, 1000, 1000, 0, 0, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Harpoon Target - Out of Combat - Disable Combat Movement (No Repeat)'), +(23821, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Valgarde Harpoon Target - Out of Combat - Set Reactstate Passive (No Repeat)'); From b8b38e1e7e1836967fc547a30d14b5359672ba9e Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Sat, 15 Feb 2025 17:22:59 +0100 Subject: [PATCH 44/97] fix(Core/Spells): Hand of Protection no longer removes Nalorak's Mangle (#21413) --- src/server/game/Spells/SpellInfoCorrections.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index c59c4fdf8..85349a0c5 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4870,6 +4870,12 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].RealPointsPerLevel = 0; }); + // Mangle (Nalorakk) + ApplySpellFix({ 42389 }, [](SpellInfo* spellInfo) + { + spellInfo->SchoolMask = SPELL_SCHOOL_MASK_NATURE; + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; From b542e64abf209439854efd1d423798d746a4aac4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 15 Feb 2025 16:23:57 +0000 Subject: [PATCH 45/97] chore(DB): import pending files Referenced commit(s): b8b38e1e7e1836967fc547a30d14b5359672ba9e --- .../Valgarde_harpoon_target.sql => db_world/2025_02_15_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/Valgarde_harpoon_target.sql => db_world/2025_02_15_01.sql} (96%) diff --git a/data/sql/updates/pending_db_world/Valgarde_harpoon_target.sql b/data/sql/updates/db_world/2025_02_15_01.sql similarity index 96% rename from data/sql/updates/pending_db_world/Valgarde_harpoon_target.sql rename to data/sql/updates/db_world/2025_02_15_01.sql index eeaf5d2cd..7a0da52ec 100644 --- a/data/sql/updates/pending_db_world/Valgarde_harpoon_target.sql +++ b/data/sql/updates/db_world/2025_02_15_01.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_15_00 -> 2025_02_15_01 -- Fix Missing Link UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 23821; From c78217baa2317e748ebb4a03209700ed08f35089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E9=B9=BF?= <18535853+PkllonG@users.noreply.github.com> Date: Sun, 16 Feb 2025 01:10:48 +0800 Subject: [PATCH 46/97] fix(Core/Creature): Correctly get flag from cinfo in IsDungeonBoss & IsImmuneToKnockback (#21456) --- src/server/game/Entities/Creature/Creature.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index c26c50589..9d62cfd23 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -3181,7 +3181,8 @@ bool Creature::IsDungeonBoss() const if (GetOwnerGUID().IsPlayer()) return false; - return HasFlagsExtra(CREATURE_FLAG_EXTRA_DUNGEON_BOSS); + CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(GetEntry()); + return cinfo && cinfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_DUNGEON_BOSS); } bool Creature::IsImmuneToKnockback() const @@ -3189,7 +3190,8 @@ bool Creature::IsImmuneToKnockback() const if (GetOwnerGUID().IsPlayer()) return false; - return HasFlagsExtra(CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK); + CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(GetEntry()); + return cinfo && cinfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK); } bool Creature::HasWeapon(WeaponAttackType type) const From 75752880e24ded1c7f498041b1e1b473baaff955 Mon Sep 17 00:00:00 2001 From: demetrzz <60552737+demetrzz@users.noreply.github.com> Date: Sun, 16 Feb 2025 00:15:37 +0300 Subject: [PATCH 47/97] fix(Apps/Codestyle) corrected wrong text in the sql codestyle check (#21466) Co-authored-by: pavel_k --- apps/codestyle/codestyle-sql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/codestyle/codestyle-sql.py b/apps/codestyle/codestyle-sql.py index 79f13241f..92666d06c 100644 --- a/apps/codestyle/codestyle-sql.py +++ b/apps/codestyle/codestyle-sql.py @@ -148,7 +148,7 @@ def insert_delete_safety_check(file: io, file_path: str) -> None: if line.startswith("--"): continue if "INSERT" in line and "DELETE" not in previous_line: - print(f"No DELETE keyword found after the INSERT in {file_path} at line {line_number}\nIf this error is intended, please advert a maintainer") + print(f"No DELETE keyword found before 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) From a05833eeed722ddc2670d43a298e2e617d1b38ce Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Sat, 15 Feb 2025 22:22:30 +0100 Subject: [PATCH 48/97] fix(Core/Common): Container fixes use after free (#21460) --- src/common/Utilities/Containers.h | 24 +++++++++++++------ src/server/game/Entities/Object/Position.h | 5 ++++ .../instance_the_black_morass.cpp | 4 +++- .../Outland/TempestKeep/botanica/boss_laj.cpp | 5 +++- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h index 3a5c3b180..ca89e7de0 100644 --- a/src/common/Utilities/Containers.h +++ b/src/common/Utilities/Containers.h @@ -138,18 +138,28 @@ namespace Acore::Containers } /* - * Select a random element from a container. + * @brief Selects a random element from a container that matches the given predicate + * + * @param container Source container to select from + * @param predicate Unary predicate to filter elements + * @return Iterator to the randomly selected element, or end iterator if no elements match the predicate * * Note: container cannot be empty */ template - inline auto SelectRandomContainerElementIf(C const& container, Predicate&& predicate) -> typename std::add_const::type& + inline auto SelectRandomContainerElementIf(C const& container, Predicate&& predicate) -> decltype(std::begin(container)) { - C containerCopy; - std::copy_if(std::begin(container), std::end(container), std::inserter(containerCopy, std::end(containerCopy)), predicate); - auto it = std::begin(containerCopy); - std::advance(it, urand(0, uint32(std::size(containerCopy)) - 1)); - return *it; + std::vector matchingElements; + + for (auto it = std::begin(container); it != std::end(container); ++it) + if (predicate(*it)) + matchingElements.push_back(it); + + if (matchingElements.empty()) + return std::end(container); + + auto randomIt = matchingElements[urand(0, matchingElements.size() - 1)]; + return randomIt; } /* diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index d44da6547..39751a12a 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -64,6 +64,11 @@ struct Position return !(operator==(a)); } + inline bool operator!=(Position const& a) const + { + return !(operator==(a)); + } + operator G3D::Vector3() const { return { m_positionX, m_positionY, m_positionZ }; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp index 3946eca1f..1551eefbd 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp @@ -205,10 +205,12 @@ public: { if (_availableRiftPositions.size() > 1) { - spawnPos = Acore::Containers::SelectRandomContainerElementIf(_availableRiftPositions, [&](Position pos) -> bool + auto spawnPosItr = Acore::Containers::SelectRandomContainerElementIf(_availableRiftPositions, [&](Position const& pos) -> bool { return pos != lastPosition; }); + if (spawnPosItr != _availableRiftPositions.end()) + spawnPos = *spawnPosItr; } else { diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp index aea7b72d3..486454021 100644 --- a/src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_laj.cpp @@ -93,10 +93,13 @@ struct boss_laj : public BossAI ScheduleTimedEvent(30s, [&] { me->RemoveAurasDueToSpell(_lastTransform.spellId); - _lastTransform = Acore::Containers::SelectRandomContainerElementIf(_transformContainer, [&](LajTransformData data) -> bool + auto lastTransformItr = Acore::Containers::SelectRandomContainerElementIf(_transformContainer, [&](LajTransformData const& data) -> bool { return data.spellId != _lastTransform.spellId; }); + if (lastTransformItr == _transformContainer.end()) + return; + _lastTransform = *lastTransformItr; me->SetDisplayId(_lastTransform.modelId); DoCastSelf(_lastTransform.spellId, true); }, 35s); From 61f04f69dbf3262a1a2e30340b0d8bc552c4c60d Mon Sep 17 00:00:00 2001 From: demetrzz <60552737+demetrzz@users.noreply.github.com> Date: Sun, 16 Feb 2025 00:29:57 +0300 Subject: [PATCH 49/97] fix(Scripts/Naxxramas): Maexxna's Outer Web Door (#21445) Co-authored-by: pavel_k --- src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp index e2f22a615..eb4757c6f 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -132,12 +132,9 @@ public: events.Reset(); summons.DespawnAll(); if (pInstance) - { if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_MAEXXNA_GATE))) - { - go->SetGoState(GO_STATE_ACTIVE); - } - } + if (pInstance->GetBossState(BOSS_FAERLINA) == DONE) + go->SetGoState(GO_STATE_ACTIVE); } void JustEngagedWith(Unit* who) override From c96ff8a6dc6db08b865c43325e156b52a298bf24 Mon Sep 17 00:00:00 2001 From: Mykhailo Redko Date: Sat, 15 Feb 2025 23:47:22 +0200 Subject: [PATCH 50/97] fix(Core/Spells): Chain heal shoudln't jump to other players who are at full hp. (#21387) --- src/server/game/Spells/Spell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 4b766bc21..1b9ff3a15 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2256,7 +2256,7 @@ void Spell::SearchChainTargets(std::list& targets, uint32 chainTar if (Unit* unit = (*itr)->ToUnit()) { uint32 deficit = unit->GetMaxHealth() - unit->GetHealth(); - if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2)) + if (deficit > maxHPDeficit && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit, VMAP::ModelIgnoreFlags::M2)) { foundItr = itr; maxHPDeficit = deficit; From 971ebcae31b39212f3be1ad4718c6d1423606069 Mon Sep 17 00:00:00 2001 From: iThorgrim <125808072+iThorgrim@users.noreply.github.com> Date: Sat, 15 Feb 2025 23:10:38 +0100 Subject: [PATCH 51/97] feat(Core/Scripting): Add Player skill based hook (#21273) Co-authored-by: IntelligentQuantum Co-authored-by: Ludwig --- .../game/Entities/Player/PlayerUpdates.cpp | 16 ++++++++++++---- .../Scripting/ScriptDefines/PlayerScript.cpp | 15 +++++++++++++++ .../game/Scripting/ScriptDefines/PlayerScript.h | 7 +++++++ src/server/game/Scripting/ScriptMgr.h | 3 +++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index dcc77209d..fcf47d5c1 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -708,7 +708,7 @@ void Player::UpdateAllRatings() // skill+step, checking for max value bool Player::UpdateSkill(uint32 skill_id, uint32 step) { - if (!skill_id) + if (!skill_id || !sScriptMgr->CanPlayerUpdateSkill(this, skill_id)) return false; SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); @@ -720,6 +720,8 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) uint32 value = SKILL_VALUE(data); uint32 max = SKILL_MAX(data); + sScriptMgr->OnBeforePlayerUpdateSkill(this, skill_id, value, max, step); + if ((!max) || (!value) || (value >= max)) return false; @@ -736,6 +738,8 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) UpdateSkillEnchantments(skill_id, value, new_value); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id); + + sScriptMgr->OnPlayerUpdateSkill(this, skill_id, value, max, step, new_value); return true; } @@ -911,7 +915,7 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) LOG_DEBUG("entities.player.skills", "UpdateSkillPro(SkillId {}, Chance {:3.1f}%)", SkillId, Chance / 10.0f); - if (!SkillId) + if (!SkillId || !sScriptMgr->CanPlayerUpdateSkill(this, SkillId)) return false; if (Chance <= 0) // speedup in 0 chance case @@ -929,8 +933,10 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); uint32 data = GetUInt32Value(valueIndex); - uint16 SkillValue = SKILL_VALUE(data); - uint16 MaxValue = SKILL_MAX(data); + uint32 SkillValue = SKILL_VALUE(data); + uint32 MaxValue = SKILL_MAX(data); + + sScriptMgr->OnBeforePlayerUpdateSkill(this, SkillId, SkillValue, MaxValue, step); if (!MaxValue || !SkillValue || SkillValue >= MaxValue) return false; @@ -962,6 +968,8 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro Chance={:3.1f}% taken", Chance / 10.0f); + + sScriptMgr->OnPlayerUpdateSkill(this, SkillId, SkillValue, MaxValue, step, new_value); return true; } diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 9d69dc3ba..78bea7872 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -895,6 +895,21 @@ 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::CanPlayerUpdateSkill(Player* player, uint32 skillId) +{ + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_CAN_UPDATE_SKILL, !script->CanPlayerUpdateSkill(player, skillId)); +} + +void ScriptMgr::OnBeforePlayerUpdateSkill(Player* player, uint32 skillId, uint32& value, uint32 max, uint32 step) +{ + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_UPDATE_SKILL, script->OnBeforePlayerUpdateSkill(player, skillId, value, max, step)); +} + +void ScriptMgr::OnPlayerUpdateSkill(Player* player, uint32 skillId, uint32 value, uint32 max, uint32 step, uint32 newValue) +{ + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_SKILL, script->OnPlayerUpdateSkill(player, skillId, value, max, step, newValue)); +} + bool ScriptMgr::CanPlayerResurrect(Player* player) { CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_RESURRECT, !script->CanPlayerResurrect(player)); diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.h b/src/server/game/Scripting/ScriptDefines/PlayerScript.h index 3ffffadf9..1fee803df 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.h +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.h @@ -204,6 +204,9 @@ enum PlayerHook PLAYERHOOK_CAN_SEND_ERROR_ALREADY_LOOTED, PLAYERHOOK_ON_AFTER_CREATURE_LOOT, PLAYERHOOK_ON_AFTER_CREATURE_LOOT_MONEY, + PLAYERHOOK_ON_CAN_UPDATE_SKILL, + PLAYERHOOK_ON_BEFORE_UPDATE_SKILL, + PLAYERHOOK_ON_UPDATE_SKILL, PLAYERHOOK_CAN_RESURRECT, PLAYERHOOK_END }; @@ -767,6 +770,10 @@ public: */ virtual void OnAfterCreatureLootMoney(Player* /*player*/) { } + virtual bool CanPlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/) { return true; } + virtual void OnBeforePlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/, uint32& /*value*/, uint32 /*max*/, uint32 /*step*/) { } + virtual void OnPlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/, uint32 /*value*/, uint32 /*max*/, uint32 /*step*/, uint32 /*newValue*/) { } + /** * @brief This hook is called, to avoid player resurrect * diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 26159984b..b05d146f0 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -459,6 +459,9 @@ public: /* PlayerScript */ void OnAfterCreatureLoot(Player* player); void OnAfterCreatureLootMoney(Player* player); bool OnCanPlayerFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell); + bool CanPlayerUpdateSkill(Player* player, uint32 skillId); + void OnBeforePlayerUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step); + void OnPlayerUpdateSkill(Player* player, uint32 skillId, uint32 value, uint32 max, uint32 step, uint32 newValue); bool CanPlayerResurrect(Player* player); // Anti cheat From e3432102f7e66968f53c6e9afb11d7844e9517be Mon Sep 17 00:00:00 2001 From: iThorgrim <125808072+iThorgrim@users.noreply.github.com> Date: Sat, 15 Feb 2025 23:34:25 +0100 Subject: [PATCH 52/97] fix(Core/World): Load metric and log configs at start (#21243) --- src/server/game/World/World.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 80c36b456..298184eb4 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -171,11 +171,11 @@ void World::LoadConfigSettings(bool reload) LOG_ERROR("server.loading", "World settings reload fail: can't read settings."); return; } - - sLog->LoadFromConfig(); - sMetric->LoadFromConfigs(); } + sLog->LoadFromConfig(); + sMetric->LoadFromConfigs(); + // Set realm id and enable db logging sLog->SetRealmId(realm.Id.Realm); From 409ad14e14a584438ed8780bebc128f04387ddfe Mon Sep 17 00:00:00 2001 From: p-tkachuk Date: Sun, 16 Feb 2025 00:26:27 +0100 Subject: [PATCH 53/97] fix(DB/SAI) Quest Feedin' Da Goolz (12652) (#21264) Co-authored-by: Hexadecimal Co-authored-by: Jelle Meeus --- .../rev_1737738749227497700.sql | 16 ++++ src/server/scripts/Northrend/zone_zuldrak.cpp | 83 ------------------- 2 files changed, 16 insertions(+), 83 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1737738749227497700.sql diff --git a/data/sql/updates/pending_db_world/rev_1737738749227497700.sql b/data/sql/updates/pending_db_world/rev_1737738749227497700.sql new file mode 100644 index 000000000..c06516787 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1737738749227497700.sql @@ -0,0 +1,16 @@ +UPDATE `creature_template` SET `ScriptName`='', `AIName` = 'SmartAI' WHERE (`entry` = 28591); + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28591) 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 +(28591, 0, 0, 1, 11, 0, 100, 512, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Ghoul Feeding KC Bunny - On Respawn - Store Targetlist'), +(28591, 0, 1, 2, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 100, 1, 0, 0, 0, 0, 0, 19, 28565, 30, 0, 0, 0, 0, 0, 0, 'Ghoul Feeding KC Bunny - On Respawn - Send Target 1'), +(28591, 0, 2, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 45, 28591, 0, 0, 0, 0, 0, 19, 28565, 30, 0, 0, 0, 0, 0, 0, 'Ghoul Feeding KC Bunny - On Respawn - Set Data 28591 0'), +(28591, 0, 3, 4, 38, 0, 100, 1, 28565, 0, 0, 0, 0, 0, 11, 52030, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 'Ghoul Feeding KC Bunny - On Data Set 28565 0 - Cast \'Kill Credit\' (No Repeat)'), +(28591, 0, 4, 5, 61, 0, 100, 513, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Ghoul Feeding KC Bunny - On Data Set 28565 0 - Despawn Instant (No Repeat)'), +(28591, 0, 5, 0, 61, 0, 100, 513, 0, 0, 0, 0, 0, 0, 41, 3000, 0, 0, 0, 0, 0, 20, 190656, 5, 0, 0, 0, 0, 0, 0, 'Ghoul Feeding KC Bunny - On Data Set 28565 0 - Despawn In 3000 ms (No Repeat)'); + +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28565) 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 +(28565, 0, 0, 0, 38, 0, 100, 0, 28591, 0, 40000, 40000, 0, 0, 69, 1, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Decaying Ghoul - On Data Set 28591 0 - Move To Stored'), +(28565, 0, 1, 2, 34, 0, 100, 512, 8, 1, 0, 0, 0, 0, 45, 28565, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 'Decaying Ghoul - On Reached Point 1 - Set Data 28565 0'), +(28565, 0, 2, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Decaying Ghoul - On Reached Point 1 - Play Emote 7'); diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp index 9114f4b6b..3493ce2fa 100644 --- a/src/server/scripts/Northrend/zone_zuldrak.cpp +++ b/src/server/scripts/Northrend/zone_zuldrak.cpp @@ -233,88 +233,6 @@ public: } }; -enum eFeedinDaGoolz -{ - NPC_DECAYING_GHOUL = 28565, - GO_BOWL = 190656, -}; - -class npc_feedin_da_goolz : public CreatureScript -{ -public: - npc_feedin_da_goolz() : CreatureScript("npc_feedin_da_goolz") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_feedin_da_goolzAI(creature); - } - - struct npc_feedin_da_goolzAI : public NullCreatureAI - { - npc_feedin_da_goolzAI(Creature* creature) : NullCreatureAI(creature) { findTimer = 1; checkTimer = 0; } - - uint32 findTimer; - uint32 checkTimer; - ObjectGuid ghoulFed; - - void UpdateAI(uint32 diff) override - { - if (findTimer) - { - findTimer += diff; - if (findTimer >= 1000) - { - if (Creature* ghoul = me->FindNearestCreature(NPC_DECAYING_GHOUL, 30.0f, true)) - { - ghoul->SetReactState(REACT_DEFENSIVE); - float o = me->GetAngle(ghoul); - ghoul->GetMotionMaster()->MovePoint(1, me->GetPositionX() + 2 * cos(o), me->GetPositionY() + 2 * std::sin(o), me->GetPositionZ()); - checkTimer = 1; - findTimer = 0; - } - else - findTimer = 1; - } - return; - } - - if (checkTimer) - { - checkTimer += diff; - if (checkTimer >= 1500) - { - checkTimer = 1; - if (!ghoulFed) - { - if (Creature* ghoul = me->FindNearestCreature(NPC_DECAYING_GHOUL, 3.0f, true)) - { - ghoulFed = ghoul->GetGUID(); - ghoul->HandleEmoteCommand(EMOTE_ONESHOT_EAT); - } - } - else - { - if (GameObject* bowl = me->FindNearestGameObject(GO_BOWL, 10.0f)) - bowl->Delete(); - - if (Creature* ghoul = ObjectAccessor::GetCreature(*me, ghoulFed)) - { - ghoul->SetReactState(REACT_AGGRESSIVE); - ghoul->GetMotionMaster()->MoveTargetedHome(); - } - - if (Unit* owner = me->ToTempSummon()->GetSummonerUnit()) - if (Player* player = owner->ToPlayer()) - player->KilledMonsterCredit(me->GetEntry()); - - me->DespawnOrUnsummon(1); - } - } - } - } - }; -}; - enum overlordDrakuru { SPELL_SHADOW_BOLT = 54113, @@ -953,7 +871,6 @@ void AddSC_zuldrak() // Ours new npc_finklestein(); new go_finklestein_cauldron(); - new npc_feedin_da_goolz(); new npc_overlord_drakuru_betrayal(); new npc_drakuru_shackles(); new npc_captured_rageclaw(); From df7c23d76362797274ad8ca5f871a19e3910e634 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 15 Feb 2025 23:27:32 +0000 Subject: [PATCH 54/97] chore(DB): import pending files Referenced commit(s): 409ad14e14a584438ed8780bebc128f04387ddfe --- .../rev_1737738749227497700.sql => db_world/2025_02_15_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1737738749227497700.sql => db_world/2025_02_15_02.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1737738749227497700.sql b/data/sql/updates/db_world/2025_02_15_02.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1737738749227497700.sql rename to data/sql/updates/db_world/2025_02_15_02.sql index c06516787..030fd5373 100644 --- a/data/sql/updates/pending_db_world/rev_1737738749227497700.sql +++ b/data/sql/updates/db_world/2025_02_15_02.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_15_01 -> 2025_02_15_02 UPDATE `creature_template` SET `ScriptName`='', `AIName` = 'SmartAI' WHERE (`entry` = 28591); DELETE FROM `smart_scripts` WHERE (`entryorguid` = 28591) AND (`source_type` = 0); From 98ceb1c06774f22518d59fc16862901bdd894e66 Mon Sep 17 00:00:00 2001 From: Exitare Date: Sun, 16 Feb 2025 05:59:41 -0800 Subject: [PATCH 55/97] fix(Core/PlayerScript) Align player script function names (#21020) Co-authored-by: sudlud --- .../game/Achievements/AchievementMgr.cpp | 12 +- .../game/Battlegrounds/BattlegroundQueue.cpp | 4 +- src/server/game/DungeonFinding/LFGMgr.cpp | 2 +- src/server/game/DungeonFinding/LFGScripts.cpp | 10 +- src/server/game/DungeonFinding/LFGScripts.h | 10 +- .../game/Entities/Creature/GossipDef.cpp | 14 +- .../Entities/Creature/TemporarySummon.cpp | 2 +- .../game/Entities/GameObject/GameObject.cpp | 2 +- src/server/game/Entities/Pet/Pet.cpp | 6 +- .../game/Entities/Player/KillRewarder.cpp | 4 +- src/server/game/Entities/Player/Player.cpp | 112 ++-- .../game/Entities/Player/PlayerMisc.cpp | 2 +- .../game/Entities/Player/PlayerQuest.cpp | 14 +- .../game/Entities/Player/PlayerStorage.cpp | 28 +- .../game/Entities/Player/PlayerUpdates.cpp | 20 +- src/server/game/Entities/Unit/StatSystem.cpp | 8 +- src/server/game/Entities/Unit/Unit.cpp | 6 +- src/server/game/Groups/Group.cpp | 4 +- .../game/Handlers/AuctionHouseHandler.cpp | 2 +- .../game/Handlers/BattleGroundHandler.cpp | 10 +- src/server/game/Handlers/CharacterHandler.cpp | 4 +- src/server/game/Handlers/ChatHandler.cpp | 24 +- src/server/game/Handlers/GroupHandler.cpp | 4 +- src/server/game/Handlers/ItemHandler.cpp | 2 +- src/server/game/Handlers/LootHandler.cpp | 6 +- src/server/game/Handlers/MailHandler.cpp | 8 +- src/server/game/Handlers/MiscHandler.cpp | 6 +- src/server/game/Handlers/NPCHandler.cpp | 2 +- src/server/game/Handlers/PetitionsHandler.cpp | 10 +- src/server/game/Handlers/QuestHandler.cpp | 2 +- src/server/game/Handlers/SpellHandler.cpp | 2 +- src/server/game/Handlers/TradeHandler.cpp | 4 +- src/server/game/Loot/LootMgr.cpp | 2 +- src/server/game/Maps/MapMgr.cpp | 2 +- src/server/game/Misc/GameGraveyard.cpp | 2 +- .../Scripting/ScriptDefines/AllMapScript.cpp | 2 +- .../Scripting/ScriptDefines/PlayerScript.cpp | 554 +++++++++--------- .../Scripting/ScriptDefines/PlayerScript.h | 314 +++++----- src/server/game/Scripting/ScriptMgr.h | 244 ++++---- src/server/game/Server/WorldSession.cpp | 6 +- src/server/game/Spells/SpellEffects.cpp | 2 +- src/server/scripts/Events/midsummer.cpp | 2 +- src/server/scripts/World/action_ip_logger.cpp | 10 +- src/server/scripts/World/chat_log.cpp | 10 +- src/server/scripts/World/server_mail.cpp | 2 +- 45 files changed, 749 insertions(+), 749 deletions(-) diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 404305b78..e679c271e 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -581,7 +581,7 @@ void AchievementMgr::SaveToDB(CharacterDatabaseTransaction trans) iter->second.changed = false; - sScriptMgr->OnAchievementSave(trans, GetPlayer(), iter->first, iter->second); + sScriptMgr->OnPlayerAchievementSave(trans, GetPlayer(), iter->first, iter->second); } } @@ -610,7 +610,7 @@ void AchievementMgr::SaveToDB(CharacterDatabaseTransaction trans) iter->second.changed = false; - sScriptMgr->OnCriteriaSave(trans, GetPlayer(), iter->first, iter->second); + sScriptMgr->OnPlayerCriteriaSave(trans, GetPlayer(), iter->first, iter->second); } } } @@ -2099,7 +2099,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, if (entry->timeLimit && timedIter == _timedAchievements.end()) return; - if (!sScriptMgr->OnBeforeCriteriaProgress(GetPlayer(), entry)) + if (!sScriptMgr->OnPlayerBeforeCriteriaProgress(GetPlayer(), entry)) { return; } @@ -2165,7 +2165,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, SendCriteriaUpdate(entry, progress, timeElapsed, true); - sScriptMgr->OnCriteriaProgress(GetPlayer(), entry); + sScriptMgr->OnPlayerCriteriaProgress(GetPlayer(), entry); } void AchievementMgr::RemoveCriteriaProgress(const AchievementCriteriaEntry* entry) @@ -2273,7 +2273,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) return; } - if (!sScriptMgr->OnBeforeAchievementComplete(GetPlayer(), achievement)) + if (!sScriptMgr->OnPlayerBeforeAchievementComplete(GetPlayer(), achievement)) { return; } @@ -2288,7 +2288,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) ca.date = GameTime::GetGameTime().count(); ca.changed = true; - sScriptMgr->OnAchievementComplete(GetPlayer(), achievement); + sScriptMgr->OnPlayerAchievementComplete(GetPlayer(), achievement); // pussywizard: set all progress counters to 0, so progress will be deleted from db during save { diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index a858acdb7..81832437b 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -1355,11 +1355,11 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) CharacterDatabase.Execute(stmt); } - sScriptMgr->OnBattlegroundDesertion(player, BG_DESERTION_TYPE_NO_ENTER_BUTTON); + sScriptMgr->OnPlayerBattlegroundDesertion(player, BG_DESERTION_TYPE_NO_ENTER_BUTTON); } if (bg && bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN)) - sScriptMgr->OnBattlegroundDesertion(player, ARENA_DESERTION_TYPE_NO_ENTER_BUTTON); + sScriptMgr->OnPlayerBattlegroundDesertion(player, ARENA_DESERTION_TYPE_NO_ENTER_BUTTON); LOG_DEBUG("bg.battleground", "Battleground: removing player {} from bg queue for instance {} because of not pressing enter battle in time.", player->GetGUID().ToString(), m_BgInstanceGUID); diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 2c540afa1..3752520fc 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -523,7 +523,7 @@ namespace lfg if (grp && (grp->isBGGroup() || grp->isBFGroup())) return; - if (!sScriptMgr->CanJoinLfg(player, roles, dungeons, comment)) + if (!sScriptMgr->OnPlayerCanJoinLfg(player, roles, dungeons, comment)) return; // pussywizard: can't join LFG/LFR while using LFR diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 53823525b..c6a2d5c30 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -41,7 +41,7 @@ namespace lfg { } - void LFGPlayerScript::OnLevelChanged(Player* player, uint8 /*oldLevel*/) + void LFGPlayerScript::OnPlayerLevelChanged(Player* player, uint8 /*oldLevel*/) { if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER | LFG_OPTION_ENABLE_SEASONAL_BOSSES)) return; @@ -49,7 +49,7 @@ namespace lfg sLFGMgr->InitializeLockedDungeons(player, player->GetGroup()); } - void LFGPlayerScript::OnLogout(Player* player) + void LFGPlayerScript::OnPlayerLogout(Player* player) { if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER | LFG_OPTION_ENABLE_SEASONAL_BOSSES)) return; @@ -69,7 +69,7 @@ namespace lfg sLFGMgr->LfrSearchRemove(player); } - void LFGPlayerScript::OnLogin(Player* player) + void LFGPlayerScript::OnPlayerLogin(Player* player) { if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER | LFG_OPTION_ENABLE_SEASONAL_BOSSES)) return; @@ -93,14 +93,14 @@ namespace lfg /// @todo - Restore LfgPlayerData and send proper status to player if it was in a group } - void LFGPlayerScript::OnBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool /*permanent*/) + void LFGPlayerScript::OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool /*permanent*/) { MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); if (mapEntry->IsDungeon() && difficulty > DUNGEON_DIFFICULTY_NORMAL) sLFGMgr->InitializeLockedDungeons(player, player->GetGroup()); } - void LFGPlayerScript::OnMapChanged(Player* player) + void LFGPlayerScript::OnPlayerMapChanged(Player* player) { Map const* map = player->GetMap(); diff --git a/src/server/game/DungeonFinding/LFGScripts.h b/src/server/game/DungeonFinding/LFGScripts.h index 8173fb1bc..918c7eac2 100644 --- a/src/server/game/DungeonFinding/LFGScripts.h +++ b/src/server/game/DungeonFinding/LFGScripts.h @@ -34,11 +34,11 @@ namespace lfg LFGPlayerScript(); // Player Hooks - void OnLevelChanged(Player* player, uint8 oldLevel) override; - void OnLogout(Player* player) override; - void OnLogin(Player* player) override; - void OnBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool permanent) override; - void OnMapChanged(Player* player) override; + void OnPlayerLevelChanged(Player* player, uint8 oldLevel) override; + void OnPlayerLogout(Player* player) override; + void OnPlayerLogin(Player* player) override; + void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapId, bool permanent) override; + void OnPlayerMapChanged(Player* player) override; }; class LFGGroupScript : public GroupScript diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 0ec2ffa35..bd0b472d4 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -455,14 +455,14 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU uint32 moneyRew = 0; Player* player = _session->GetPlayer(); - if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))) + if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player))) { moneyRew = quest->GetRewMoneyMaxLevel(); } moneyRew += quest->GetRewOrReqMoney(player ? player->GetLevel() : 0); // reward money (below max lvl) data << moneyRew; uint32 questXp; - if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)) + if (player && !sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player)) { questXp = player->CalculateQuestRewardXP(quest); } @@ -470,7 +470,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU { questXp = 0; } - sScriptMgr->OnQuestComputeXP(player, quest, questXp); + sScriptMgr->OnPlayerQuestComputeXP(player, quest, questXp); data << questXp; } @@ -555,7 +555,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const { uint32 moneyRew = 0; Player* player = _session->GetPlayer(); - if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))) + if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player))) { moneyRew = quest->GetRewMoneyMaxLevel(); } @@ -707,14 +707,14 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI uint32 moneyRew = 0; Player* player = _session->GetPlayer(); - if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))) + if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player))) { moneyRew = quest->GetRewMoneyMaxLevel(); } moneyRew += quest->GetRewOrReqMoney(player ? player->GetLevel() : 0); // reward money (below max lvl) data << moneyRew; uint32 questXp; - if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)) + if (player && !sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player)) { questXp = player->CalculateQuestRewardXP(quest); } @@ -722,7 +722,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI { questXp = 0; } - sScriptMgr->OnQuestComputeXP(player, quest, questXp); + sScriptMgr->OnPlayerQuestComputeXP(player, quest, questXp); data << questXp; // rewarded honor points. Multiply with 10 to satisfy client diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp index a0c044a5d..f6b4285af 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.cpp +++ b/src/server/game/Entities/Creature/TemporarySummon.cpp @@ -204,7 +204,7 @@ void TempSummon::InitStats(uint32 duration) Unit* owner = GetSummonerUnit(); if (owner) if (Player* player = owner->ToPlayer()) - sScriptMgr->OnBeforeTempSummonInitStats(player, this, duration); + sScriptMgr->OnPlayerBeforeTempSummonInitStats(player, this, duration); m_timer = duration; m_lifetime = duration; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 6c942d576..298edcde8 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1759,7 +1759,7 @@ void GameObject::Use(Unit* user) LOG_DEBUG("entities.gameobject", "Fishing check (skill: {} zone min skill: {} chance {} roll: {}", skill, zone_skill, chance, roll); - if (sScriptMgr->OnUpdateFishingSkill(player, skill, zone_skill, chance, roll)) + if (sScriptMgr->OnPlayerUpdateFishingSkill(player, skill, zone_skill, chance, roll)) { player->UpdateFishingSkill(); } diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 1c3262654..5302a9878 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -237,7 +237,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c return false; bool forceLoadFromDB = false; - sScriptMgr->OnBeforeLoadPetFromDB(owner, petEntry, petnumber, current, forceLoadFromDB); + sScriptMgr->OnPlayerBeforeLoadPetFromDB(owner, petEntry, petnumber, current, forceLoadFromDB); if (!forceLoadFromDB && (owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET) && !owner->CanSeeDKPet())) // DK Pet exception return false; @@ -1033,7 +1033,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) PetType petType = MAX_PET_TYPE; if (owner->IsPlayer()) { - sScriptMgr->OnBeforeGuardianInitStatsForLevel(owner->ToPlayer(), this, cinfo, petType); + sScriptMgr->OnPlayerBeforeGuardianInitStatsForLevel(owner->ToPlayer(), this, cinfo, petType); if (IsPet()) { @@ -1427,7 +1427,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); if (owner->IsPlayer()) - sScriptMgr->OnAfterGuardianInitStatsForLevel(owner->ToPlayer(), this); + sScriptMgr->OnPlayerAfterGuardianInitStatsForLevel(owner->ToPlayer(), this); return true; } diff --git a/src/server/game/Entities/Player/KillRewarder.cpp b/src/server/game/Entities/Player/KillRewarder.cpp index 1ce4308aa..606dd1547 100644 --- a/src/server/game/Entities/Player/KillRewarder.cpp +++ b/src/server/game/Entities/Player/KillRewarder.cpp @@ -167,7 +167,7 @@ void KillRewarder::_RewardXP(Player* player, float rate) AddPct(xp, (*i)->GetAmount()); // 4.2.3. Give XP to player. - sScriptMgr->OnGivePlayerXP(player, xp, _victim, PlayerXPSource::XPSOURCE_KILL); + sScriptMgr->OnPlayerGiveXP(player, xp, _victim, PlayerXPSource::XPSOURCE_KILL); player->GiveXP(xp, _victim, _groupRate); if (Pet* pet = player->GetPet()) // 4.2.4. If player has pet, reward pet with XP (100% for single player, 50% for group case). @@ -210,7 +210,7 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon) if (!_isPvP || _isBattleGround) { float xpRate = _group ? _groupRate * float(player->GetLevel()) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels. - sScriptMgr->OnRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%. + sScriptMgr->OnPlayerRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%. if (_xp) { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1787b8ccb..b875c363d 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1430,7 +1430,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (duel && GetMapId() != mapid && GetMap()->GetGameObject(GetGuidValue(PLAYER_DUEL_ARBITER))) DuelComplete(DUEL_FLED); - if (!sScriptMgr->OnBeforePlayerTeleport(this, mapid, x, y, z, orientation, options, target)) + if (!sScriptMgr->OnPlayerBeforeTeleport(this, mapid, x, y, z, orientation, options, target)) return false; if (GetMapId() == mapid && !newInstance) @@ -2247,7 +2247,7 @@ void Player::SetGameMaster(bool on) if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - sScriptMgr->OnFfaPvpStateUpdate(this, false); + sScriptMgr->OnPlayerFfaPvpStateUpdate(this, false); } ResetContestedPvP(); @@ -2284,7 +2284,7 @@ void Player::SetGameMaster(bool on) if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - sScriptMgr->OnFfaPvpStateUpdate(this, true); + sScriptMgr->OnPlayerFfaPvpStateUpdate(this, true); } } // restore FFA PvP area state, remove not allowed for GM mounts @@ -2548,7 +2548,7 @@ void Player::GiveLevel(uint8 level) pet->SynchronizeLevelWithOwner(); MailLevelReward const* mailReward = sObjectMgr->GetMailLevelReward(level, getRaceMask()); - if (mailReward && sScriptMgr->CanGiveMailRewardAtGiveLevel(this, level)) + if (mailReward && sScriptMgr->OnPlayerCanGiveMailRewardAtGiveLevel(this, level)) { //- TODO: Poor design of mail system CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); @@ -2606,7 +2606,7 @@ void Player::InitStatsForLevel(bool reapplyMods) sObjectMgr->GetPlayerLevelInfo(getRace(true), getClass(), GetLevel(), &info); uint32 maxPlayerLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); - sScriptMgr->OnSetMaxLevel(this, maxPlayerLevel); + sScriptMgr->OnPlayerSetMaxLevel(this, maxPlayerLevel); SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, maxPlayerLevel); SetUInt32Value(PLAYER_NEXT_LEVEL_XP, sObjectMgr->GetXPForLevel(GetLevel())); @@ -2738,7 +2738,7 @@ void Player::InitStatsForLevel(bool reapplyMods) if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY); - sScriptMgr->OnFfaPvpStateUpdate(this, false); + sScriptMgr->OnPlayerFfaPvpStateUpdate(this, false); } // restore if need some important flags @@ -4302,7 +4302,7 @@ void Player::DeleteFromDB(ObjectGuid::LowType lowGuid, uint32 accountId, bool up Corpse::DeleteFromDB(playerGuid, trans); - sScriptMgr->OnDeleteFromDB(trans, lowGuid); + sScriptMgr->OnPlayerDeleteFromDB(trans, lowGuid); CharacterDatabase.CommitTransaction(trans); break; @@ -4493,7 +4493,7 @@ void Player::BuildPlayerRepop() void Player::ResurrectPlayer(float restore_percent, bool applySickness) { - if (!sScriptMgr->CanPlayerResurrect(this)) + if (!sScriptMgr->OnPlayerCanResurrect(this)) return; WorldPacket data(SMSG_DEATH_RELEASE_LOC, 4 * 4); // remove spirit healer position @@ -4946,7 +4946,7 @@ void Player::RepopAtGraveyard() AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetAreaId()); - if (!sScriptMgr->CanRepopAtGraveyard(this)) + if (!sScriptMgr->OnPlayerCanRepopAtGraveyard(this)) return; // Such zones are considered unreachable as a ghost and the player must be automatically revived @@ -5499,7 +5499,7 @@ uint16 Player::GetMaxSkillValue(uint32 skill) const uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); - sScriptMgr->OnGetMaxSkillValue(const_cast(this), skill, result, false); + sScriptMgr->OnPlayerGetMaxSkillValue(const_cast(this), skill, result, false); result += SKILL_TEMP_BONUS(bonus); result += SKILL_PERM_BONUS(bonus); return result < 0 ? 0 : result; @@ -5516,7 +5516,7 @@ uint16 Player::GetPureMaxSkillValue(uint32 skill) const int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); - sScriptMgr->OnGetMaxSkillValue(const_cast(this), skill, result, true); + sScriptMgr->OnPlayerGetMaxSkillValue(const_cast(this), skill, result, true); return result < 0 ? 0 : result; } @@ -5795,7 +5795,7 @@ void Player::CheckAreaExploreAndOutdoor() } } - if (!sScriptMgr->CanAreaExploreAndOutdoor(this)) + if (!sScriptMgr->OnPlayerCanAreaExploreAndOutdoor(this)) return; if (!areaId) @@ -5854,7 +5854,7 @@ void Player::CheckAreaExploreAndOutdoor() XP = uint32(sObjectMgr->GetBaseXP(areaEntry->area_level) * sWorld->getRate(RATE_XP_EXPLORE)); } - sScriptMgr->OnGivePlayerXP(this, XP, nullptr, PlayerXPSource::XPSOURCE_EXPLORE); + sScriptMgr->OnPlayerGiveXP(this, XP, nullptr, PlayerXPSource::XPSOURCE_EXPLORE); GiveXP(XP, nullptr); SendExplorationExperience(areaId, XP); } @@ -6165,7 +6165,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar // [39+] Nothing uint32 victim_title = victim->GetUInt32Value(PLAYER_CHOSEN_TITLE); uint32 killer_title = 0; - sScriptMgr->OnVictimRewardBefore(this, victim, killer_title, victim_title); + sScriptMgr->OnPlayerVictimRewardBefore(this, victim, killer_title, victim_title); // Get Killer titles, CharTitlesEntry::bit_index // Ranks: // title[1..14] -> rank[5..18] @@ -6192,7 +6192,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, GetAreaId()); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, victim); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, victim); - sScriptMgr->OnVictimRewardAfter(this, victim, killer_title, victim_rank, honor_f); + sScriptMgr->OnPlayerVictimRewardAfter(this, victim, killer_title, victim_rank, honor_f); } else { @@ -6244,7 +6244,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar if (!uVictim) { uint32 xp = uint32(honor * (3 + GetLevel() * 0.30f)); - sScriptMgr->OnGivePlayerXP(this, xp, nullptr, PlayerXPSource::XPSOURCE_BATTLEGROUND); + sScriptMgr->OnPlayerGiveXP(this, xp, nullptr, PlayerXPSource::XPSOURCE_BATTLEGROUND); GiveXP(xp, nullptr); } } @@ -6638,7 +6638,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply uint32 ssd_level = GetLevel(); uint32 CustomScalingStatValue = 0; - sScriptMgr->OnCustomScalingStatValueBefore(this, proto, slot, apply, CustomScalingStatValue); + sScriptMgr->OnPlayerCustomScalingStatValueBefore(this, proto, slot, apply, CustomScalingStatValue); uint32 ScalingStatValue = proto->ScalingStatValue > 0 ? proto->ScalingStatValue : CustomScalingStatValue; @@ -6670,7 +6670,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply continue; // OnCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv) - sScriptMgr->OnCustomScalingStatValue(this, proto, statType, val, i, ScalingStatValue, ssv); + sScriptMgr->OnPlayerCustomScalingStatValue(this, proto, statType, val, i, ScalingStatValue, ssv); } } else @@ -6681,7 +6681,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply statType = proto->ItemStat[i].ItemStatType; val = proto->ItemStat[i].ItemStatValue; - sScriptMgr->OnApplyItemModsBefore(this, slot, apply, i, statType, val); + sScriptMgr->OnPlayerApplyItemModsBefore(this, slot, apply, i, statType, val); } if (val == 0) @@ -6872,7 +6872,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply } // Add armor bonus from ArmorDamageModifier if > 0 - if (proto->ArmorDamageModifier > 0 && sScriptMgr->CanArmorDamageModifier(this)) + if (proto->ArmorDamageModifier > 0 && sScriptMgr->OnPlayerCanArmorDamageModifier(this)) HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply); if (proto->Block) @@ -6914,7 +6914,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply } feral_bonus += proto->getFeralBonus(dpsMod); - sScriptMgr->OnGetFeralApBonus(this, feral_bonus, dpsMod, proto, ssv); + sScriptMgr->OnPlayerGetFeralApBonus(this, feral_bonus, dpsMod, proto, ssv); if (feral_bonus) ApplyFeralAPBonus(feral_bonus, apply); } @@ -6924,7 +6924,7 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt { uint32 CustomScalingStatValue = 0; - sScriptMgr->OnCustomScalingStatValueBefore(this, proto, slot, apply, CustomScalingStatValue); + sScriptMgr->OnPlayerCustomScalingStatValueBefore(this, proto, slot, apply, CustomScalingStatValue); uint32 ScalingStatValue = proto->ScalingStatValue > 0 ? proto->ScalingStatValue : CustomScalingStatValue; @@ -6970,7 +6970,7 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt if (apply) { - sScriptMgr->OnApplyWeaponDamage(this, slot, proto, minDamage, maxDamage, i); + sScriptMgr->OnPlayerApplyWeaponDamage(this, slot, proto, minDamage, maxDamage, i); if (minDamage > 0.f) { @@ -7052,7 +7052,7 @@ void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attac if (aura->GetSpellInfo()->EquippedItemClass == -1) return; - if (!sScriptMgr->CanApplyWeaponDependentAuraDamageMod(this, item, attackType, aura, apply)) + if (!sScriptMgr->OnPlayerCanApplyWeaponDependentAuraDamageMod(this, item, attackType, aura, apply)) return; BaseModGroup mod = BASEMOD_END; @@ -7186,7 +7186,7 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, { if (apply) { - if (!sScriptMgr->CanApplyEquipSpell(this, spellInfo, item, apply, form_change)) + if (!sScriptMgr->OnPlayerCanApplyEquipSpell(this, spellInfo, item, apply, form_change)) return; // Cannot be used in this stance/form @@ -7282,7 +7282,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto) { - if (!sScriptMgr->CanCastItemCombatSpell(this, target, attType, procVictim, procEx, item, proto)) + if (!sScriptMgr->OnPlayerCanCastItemCombatSpell(this, target, attType, procVictim, procEx, item, proto)) return; // Can do effect if any damage done to target @@ -7414,7 +7414,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex) { - if (!sScriptMgr->CanCastItemUseSpell(this, item, targets, cast_count, glyphIndex)) + if (!sScriptMgr->OnPlayerCanCastItemUseSpell(this, item, targets, cast_count, glyphIndex)) return; ItemTemplate const* proto = item->GetTemplate(); @@ -7679,7 +7679,7 @@ void Player::_ApplyAmmoBonuses() else currentAmmoDPS = (ammo_proto->Damage[0].DamageMin + ammo_proto->Damage[0].DamageMax) / 2; - sScriptMgr->OnApplyAmmoBonuses(this, ammo_proto, currentAmmoDPS); + sScriptMgr->OnPlayerApplyAmmoBonuses(this, ammo_proto, currentAmmoDPS); if (currentAmmoDPS == GetAmmoDPS()) return; @@ -9377,7 +9377,7 @@ void Player::StopCastingCharm(Aura* except /*= nullptr*/) void Player::Say(std::string_view text, Language language, WorldObject const* /*= nullptr*/) { std::string _text(text); - if (!sScriptMgr->CanPlayerUseChat(this, CHAT_MSG_SAY, language, _text)) + if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_SAY, language, _text)) { return; } @@ -9398,7 +9398,7 @@ void Player::Yell(std::string_view text, Language language, WorldObject const* / { std::string _text(text); - if (!sScriptMgr->CanPlayerUseChat(this, CHAT_MSG_YELL, language, _text)) + if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_YELL, language, _text)) { return; } @@ -9419,7 +9419,7 @@ void Player::TextEmote(std::string_view text, WorldObject const* /*= nullptr*/, { std::string _text(text); - if (!sScriptMgr->CanPlayerUseChat(this, CHAT_MSG_EMOTE, LANG_UNIVERSAL, _text)) + if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_EMOTE, LANG_UNIVERSAL, _text)) { return; } @@ -9448,7 +9448,7 @@ void Player::Whisper(std::string_view text, Language language, Player* target, b std::string _text(text); - if (!sScriptMgr->CanPlayerUseChat(this, CHAT_MSG_WHISPER, language, _text, target)) + if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_WHISPER, language, _text, target)) { return; } @@ -10712,7 +10712,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c } } - sScriptMgr->OnBeforeStoreOrEquipNewItem(this, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore); + sScriptMgr->OnPlayerBeforeStoreOrEquipNewItem(this, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore); Item* it = bStore ? StoreNewItem(vDest, item, true) : EquipNewItem(uiDest, item, true); if (it) @@ -10741,7 +10741,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c } } - sScriptMgr->OnAfterStoreOrEquipNewItem(this, vendorslot, it, count, bag, slot, pProto, pVendor, crItem, bStore); + sScriptMgr->OnPlayerAfterStoreOrEquipNewItem(this, vendorslot, it, count, bag, slot, pProto, pVendor, crItem, bStore); return true; } @@ -10749,7 +10749,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c // Return true is the bought item has a max count to force refresh of window by caller bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot) { - sScriptMgr->OnBeforeBuyItemFromVendor(this, vendorguid, vendorslot, item, count, bag, slot); + sScriptMgr->OnPlayerBeforeBuyItemFromVendor(this, vendorguid, vendorslot, item, count, bag, slot); // this check can be used from the hook to implement a custom vendor process if (item == 0) @@ -10941,7 +10941,7 @@ uint32 Player::GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const } } - sScriptMgr->OnGetMaxPersonalArenaRatingRequirement(this, minarenaslot, max_personal_rating); + sScriptMgr->OnPlayerGetMaxPersonalArenaRatingRequirement(this, minarenaslot, max_personal_rating); return max_personal_rating; } @@ -11375,11 +11375,11 @@ void Player::LeaveBattleground(Battleground* bg) stmt->SetData(1, BG_DESERTION_TYPE_LEAVE_BG); CharacterDatabase.Execute(stmt); } - sScriptMgr->OnBattlegroundDesertion(this, BG_DESERTION_TYPE_LEAVE_BG); + sScriptMgr->OnPlayerBattlegroundDesertion(this, BG_DESERTION_TYPE_LEAVE_BG); } if (bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN)) - sScriptMgr->OnBattlegroundDesertion(this, ARENA_DESERTION_TYPE_LEAVE_BG); + sScriptMgr->OnPlayerBattlegroundDesertion(this, ARENA_DESERTION_TYPE_LEAVE_BG); // xinef: reset corpse reclaim time m_deathExpireTime = GameTime::GetGameTime().count(); @@ -11539,7 +11539,7 @@ bool Player::IsVisibleGloballyFor(Player const* u) const if (!AccountMgr::IsPlayerAccount(u->GetSession()->GetSecurity())) return GetSession()->GetSecurity() <= u->GetSession()->GetSecurity(); - if (!sScriptMgr->NotVisibleGloballyFor(const_cast(this), u)) + if (!sScriptMgr->OnPlayerNotVisibleGloballyFor(const_cast(this), u)) return true; // non faction visibility non-breakable for non-GMs @@ -11668,7 +11668,7 @@ void Player::SendInitialPacketsBeforeAddToMap() SetMover(this); - sScriptMgr->OnSendInitialPacketsBeforeAddToMap(this, data); + sScriptMgr->OnPlayerSendInitialPacketsBeforeAddToMap(this, data); } void Player::SendInitialPacketsAfterAddToMap() @@ -13560,7 +13560,7 @@ LootItem* Player::StoreLootItem(uint8 lootSlot, Loot* loot, InventoryResult& msg LootItem* item = loot->LootItemInSlot(lootSlot, this, &qitem, &ffaitem, &conditem); if (!item || item->is_looted) { - if (!sScriptMgr->CanSendErrorAlreadyLooted(this)) + if (!sScriptMgr->OnPlayerCanSendErrorAlreadyLooted(this)) { SendEquipError(EQUIP_ERR_ALREADY_LOOTED, nullptr, nullptr); } @@ -13642,7 +13642,7 @@ LootItem* Player::StoreLootItem(uint8 lootSlot, Loot* loot, InventoryResult& msg if (loot->containerGUID) sLootItemStorage->RemoveStoredLootItem(loot->containerGUID, item->itemid, item->count, loot, item->itemIndex); - sScriptMgr->OnLootItem(this, newitem, item->count, this->GetLootGUID()); + sScriptMgr->OnPlayerLootItem(this, newitem, item->count, this->GetLootGUID()); } else { @@ -13673,13 +13673,13 @@ uint32 Player::CalculateTalentsPoints() const } talentPointsForLevel += m_extraBonusTalentCount; - sScriptMgr->OnCalculateTalentsPoints(this, talentPointsForLevel); + sScriptMgr->OnPlayerCalculateTalentsPoints(this, talentPointsForLevel); return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT)); } bool Player::canFlyInZone(uint32 mapid, uint32 zone, SpellInfo const* bySpell) { - if (!sScriptMgr->OnCanPlayerFlyInZone(this, mapid,zone,bySpell)) + if (!sScriptMgr->OnPlayerCanFlyInZone(this, mapid,zone,bySpell)) { return false; } @@ -15300,7 +15300,7 @@ void Player::ActivateSpec(uint8 spec) ++iter; } - sScriptMgr->OnAfterSpecSlotChanged(this, GetActiveSpec()); + sScriptMgr->OnPlayerAfterSpecSlotChanged(this, GetActiveSpec()); } void Player::LoadActions(PreparedQueryResult result) @@ -15397,7 +15397,7 @@ void Player::SetIsSpectator(bool on) if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - sScriptMgr->OnFfaPvpStateUpdate(this, false); + sScriptMgr->OnPlayerFfaPvpStateUpdate(this, false); } ResetContestedPvP(); SetDisplayId(23691); @@ -15422,7 +15422,7 @@ void Player::SetIsSpectator(bool on) if (!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - sScriptMgr->OnFfaPvpStateUpdate(this, true); + sScriptMgr->OnPlayerFfaPvpStateUpdate(this, true); } } @@ -16227,7 +16227,7 @@ uint32 Player::DoRandomRoll(uint32 minimum, uint32 maximum) void Player::SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value) { - if (sScriptMgr->NotSetArenaTeamInfoField(this, slot, type, value)) + if (sScriptMgr->OnPlayerNotSetArenaTeamInfoField(this, slot, type, value)) SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value); } @@ -16235,7 +16235,7 @@ uint32 Player::GetArenaPersonalRating(uint8 slot) const { uint32 result = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING); - sScriptMgr->OnGetArenaPersonalRating(const_cast(this), slot, result); + sScriptMgr->OnPlayerGetArenaPersonalRating(const_cast(this), slot, result); return result; } @@ -16244,7 +16244,7 @@ uint32 Player::GetArenaTeamId(uint8 slot) const { uint32 result = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_ID); - sScriptMgr->OnGetArenaTeamId(const_cast(this), slot, result); + sScriptMgr->OnPlayerGetArenaTeamId(const_cast(this), slot, result); return result; } @@ -16253,7 +16253,7 @@ bool Player::IsFFAPvP() { bool result = Unit::IsFFAPvP(); - sScriptMgr->OnIsFFAPvP(this, result); + sScriptMgr->OnPlayerIsFFAPvP(this, result); return result; } @@ -16262,7 +16262,7 @@ bool Player::IsPvP() { bool result = Unit::IsPvP(); - sScriptMgr->OnIsPvP(this, result); + sScriptMgr->OnPlayerIsPvP(this, result); return result; } @@ -16271,7 +16271,7 @@ uint16 Player::GetMaxSkillValueForLevel() const { uint16 result = Unit::GetMaxSkillValueForLevel(); - sScriptMgr->OnGetMaxSkillValueForLevel(const_cast(this), result); + sScriptMgr->OnPlayerGetMaxSkillValueForLevel(const_cast(this), result); return result; } @@ -16280,21 +16280,21 @@ float Player::GetQuestRate(bool isDFQuest) { float result = isDFQuest ? sWorld->getRate(RATE_XP_QUEST_DF) : sWorld->getRate(RATE_XP_QUEST); - sScriptMgr->OnGetQuestRate(this, result); + sScriptMgr->OnPlayerGetQuestRate(this, result); return result; } void Player::SetServerSideVisibility(ServerSideVisibilityType type, AccountTypes sec) { - sScriptMgr->OnSetServerSideVisibility(this, type, sec); + sScriptMgr->OnPlayerSetServerSideVisibility(this, type, sec); m_serverSideVisibility.SetValue(type, sec); } void Player::SetServerSideVisibilityDetect(ServerSideVisibilityType type, AccountTypes sec) { - sScriptMgr->OnSetServerSideVisibilityDetect(this, type, sec); + sScriptMgr->OnPlayerSetServerSideVisibilityDetect(this, type, sec); m_serverSideVisibilityDetect.SetValue(type, sec); } diff --git a/src/server/game/Entities/Player/PlayerMisc.cpp b/src/server/game/Entities/Player/PlayerMisc.cpp index 8c32b2cae..715e20fec 100644 --- a/src/server/game/Entities/Player/PlayerMisc.cpp +++ b/src/server/game/Entities/Player/PlayerMisc.cpp @@ -399,7 +399,7 @@ void Player::UpdateFFAPvPFlag(time_t currTime) if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - sScriptMgr->OnFfaPvpStateUpdate(this, false); + sScriptMgr->OnPlayerFfaPvpStateUpdate(this, false); } for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) (*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); diff --git a/src/server/game/Entities/Player/PlayerQuest.cpp b/src/server/game/Entities/Player/PlayerQuest.cpp index dcf74d0f3..3dbb7231c 100644 --- a/src/server/game/Entities/Player/PlayerQuest.cpp +++ b/src/server/game/Entities/Player/PlayerQuest.cpp @@ -602,7 +602,7 @@ void Player::CompleteQuest(uint32 quest_id) return; } - if (!sScriptMgr->OnBeforePlayerQuestComplete(this, quest_id)) + if (!sScriptMgr->OnPlayerBeforeQuestComplete(this, quest_id)) { return; } @@ -699,7 +699,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, Item* item = StoreNewItem(dest, itemId, true); SendNewItem(item, quest->RewardChoiceItemCount[reward], true, false, false, false); - sScriptMgr->OnQuestRewardItem(this, item, quest->RewardChoiceItemCount[reward]); + sScriptMgr->OnPlayerQuestRewardItem(this, item, quest->RewardChoiceItemCount[reward]); } else { @@ -720,7 +720,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, Item* item = StoreNewItem(dest, itemId, true); SendNewItem(item, quest->RewardItemIdCount[i], true, false, false, false); - sScriptMgr->OnQuestRewardItem(this, item, quest->RewardItemIdCount[i]); + sScriptMgr->OnPlayerQuestRewardItem(this, item, quest->RewardItemIdCount[i]); } else problematicItems.emplace_back(itemId, quest->RewardItemIdCount[i]); @@ -745,15 +745,15 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, // Not give XP in case already completed once repeatable quest uint32 XP = rewarded ? 0 : CalculateQuestRewardXP(quest); - sScriptMgr->OnQuestComputeXP(this, quest, XP); + sScriptMgr->OnPlayerQuestComputeXP(this, quest, XP); int32 moneyRew = 0; - if (GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(this)) + if (GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(this)) { moneyRew = quest->GetRewMoneyMaxLevel(); } else { - sScriptMgr->OnGivePlayerXP(this, XP, nullptr, isLFGReward ? PlayerXPSource::XPSOURCE_QUEST_DF : PlayerXPSource::XPSOURCE_QUEST); + sScriptMgr->OnPlayerGiveXP(this, XP, nullptr, isLFGReward ? PlayerXPSource::XPSOURCE_QUEST_DF : PlayerXPSource::XPSOURCE_QUEST); GiveXP(XP, nullptr, 1.0f, isLFGReward); } @@ -1953,7 +1953,7 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid) if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficulty()) || (qInfo->IsPVPQuest() && (GetGroup()->isBFGroup() || GetGroup()->isBGGroup())))) { - if (!sScriptMgr->PassedQuestKilledMonsterCredit(this, qInfo, entry, real_entry, guid)) + if (!sScriptMgr->OnPlayerPassedQuestKilledMonsterCredit(this, qInfo, entry, real_entry, guid)) continue; if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL) /*&& !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAST)*/) diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index 4b3a28cc3..8de9e8a0c 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -1811,7 +1811,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool ItemTemplate const* pProto = pItem->GetTemplate(); if (pProto) { - if (!sScriptMgr->CanEquipItem(const_cast(this), slot, dest, pItem, swap, not_loading)) + if (!sScriptMgr->OnPlayerCanEquipItem(const_cast(this), slot, dest, pItem, swap, not_loading)) return EQUIP_ERR_CANT_DO_RIGHT_NOW; // item used @@ -1983,7 +1983,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool InventoryResult Player::CanUnequipItem(uint16 pos, bool swap) const { - if (!sScriptMgr->CanUnequipItem(const_cast(this), pos, swap)) + if (!sScriptMgr->OnPlayerCanUnequipItem(const_cast(this), pos, swap)) return EQUIP_ERR_CANT_DO_RIGHT_NOW; // Applied only to equipped items and bank bags @@ -2326,7 +2326,7 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const InventoryResult result = EQUIP_ERR_OK; - if (!sScriptMgr->CanUseItem(const_cast(this), proto, result)) + if (!sScriptMgr->OnPlayerCanUseItem(const_cast(this), proto, result)) { return result; } @@ -2566,7 +2566,7 @@ Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update CharacterDatabase.Execute(stmt); } - sScriptMgr->OnStoreNewItem(this, pItem, count); + sScriptMgr->OnPlayerStoreNewItem(this, pItem, count); } return pItem; } @@ -2710,7 +2710,7 @@ Item* Player::EquipNewItem(uint16 pos, uint32 item, bool update) if (!_item) return nullptr; - if (!IsEquipmentPos(pos) || sScriptMgr->CanSaveEquipNewItem(this, _item, pos, update)) + if (!IsEquipmentPos(pos) || sScriptMgr->OnPlayerCanSaveEquipNewItem(this, _item, pos, update)) { // pussywizard: obtaining blue or better items saves to db if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item)) @@ -2819,7 +2819,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update) pItem2->SetState(ITEM_CHANGED, this); ApplyEquipCooldown(pItem2); - sScriptMgr->OnEquip(this, pItem2, bag, slot, update); + sScriptMgr->OnPlayerEquip(this, pItem2, bag, slot, update); return pItem2; } @@ -2827,7 +2827,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update) UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry()); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot); - sScriptMgr->OnEquip(this, pItem, bag, slot, update); + sScriptMgr->OnPlayerEquip(this, pItem, bag, slot, update); UpdateForQuestWorldObjects(); return pItem; } @@ -2851,7 +2851,7 @@ void Player::QuickEquipItem(uint16 pos, Item* pItem) UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry()); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot); - sScriptMgr->OnEquip(this, pItem, (pos >> 8), slot, true); + sScriptMgr->OnPlayerEquip(this, pItem, (pos >> 8), slot, true); } } @@ -2869,7 +2869,7 @@ void Player::SetVisibleItemSlot(uint8 slot, Item* pItem) SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 0); } - sScriptMgr->OnAfterPlayerSetVisibleItemSlot(this, slot, pItem); + sScriptMgr->OnPlayerAfterSetVisibleItemSlot(this, slot, pItem); } void Player::VisualizeItem(uint8 slot, Item* pItem) @@ -2990,7 +2990,7 @@ void Player::MoveItemFromInventory(uint8 bag, uint8 slot, bool update) it->DestroyForPlayer(this); } - sScriptMgr->OnAfterPlayerMoveItemFromInventory(this, it, bag, slot, update); + sScriptMgr->OnPlayerAfterMoveItemFromInventory(this, it, bag, slot, update); } } @@ -4326,7 +4326,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool if (pEnchant->requiredSkill > 0 && pEnchant->requiredSkillValue > GetSkillValue(pEnchant->requiredSkill)) return; - if (!sScriptMgr->CanApplyEnchantment(this, item, slot, apply, apply_dur, ignore_condition)) + if (!sScriptMgr->OnPlayerCanApplyEnchantment(this, item, slot, apply, apply_dur, ignore_condition)) return; // If we're dealing with a gem inside a prismatic socket we need to check the prismatic socket requirements @@ -4433,7 +4433,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool } } - sScriptMgr->OnApplyEnchantmentItemModsBefore(this, item, slot, apply, enchant_spell_id, enchant_amount); + sScriptMgr->OnPlayerApplyEnchantmentItemModsBefore(this, item, slot, apply, enchant_spell_id, enchant_amount); LOG_DEBUG("entities.player.items", "Adding {} to stat nb {}", enchant_amount, enchant_spell_id); switch (enchant_spell_id) @@ -5876,7 +5876,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff) else if (IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot)) { uint16 dest; - if (sScriptMgr->CheckItemInSlotAtLoadInventory(this, item, slot, err, dest)) + if (sScriptMgr->OnPlayerCheckItemInSlotAtLoadInventory(this, item, slot, err, dest)) err = CanEquipItem(slot, dest, item, false, false); if (err == EQUIP_ERR_OK) QuickEquipItem(dest, item); @@ -6826,7 +6826,7 @@ bool Player::Satisfy(DungeonProgressionRequirements const* ar, uint32 target_map || missingPlayerItems.size() || missingPlayerQuests.size() || missingPlayerAchievements.size() || missingLeaderItems.size() || missingLeaderQuests.size() || missingLeaderAchievements.size()) { - if (!sScriptMgr->NotAvoidSatisfy(partyLeader, ar, target_map, report)) + if (!sScriptMgr->OnPlayerNotAvoidSatisfy(partyLeader, ar, target_map, report)) return true; if (report) diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp index fcf47d5c1..e2862ace6 100644 --- a/src/server/game/Entities/Player/PlayerUpdates.cpp +++ b/src/server/game/Entities/Player/PlayerUpdates.cpp @@ -55,7 +55,7 @@ void Player::Update(uint32 p_time) if (!IsInWorld()) return; - sScriptMgr->OnBeforePlayerUpdate(this, p_time); + sScriptMgr->OnPlayerBeforeUpdate(this, p_time); // undelivered mail if (m_nextMailDelivereTime && m_nextMailDelivereTime <= GameTime::GetGameTime().count()) @@ -708,7 +708,7 @@ void Player::UpdateAllRatings() // skill+step, checking for max value bool Player::UpdateSkill(uint32 skill_id, uint32 step) { - if (!skill_id || !sScriptMgr->CanPlayerUpdateSkill(this, skill_id)) + if (!skill_id || !sScriptMgr->OnPlayerCanUpdateSkill(this, skill_id)) return false; SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); @@ -720,7 +720,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) uint32 value = SKILL_VALUE(data); uint32 max = SKILL_MAX(data); - sScriptMgr->OnBeforePlayerUpdateSkill(this, skill_id, value, max, step); + sScriptMgr->OnPlayerBeforeUpdateSkill(this, skill_id, value, max, step); if ((!max) || (!value) || (value >= max)) return false; @@ -768,7 +768,7 @@ bool Player::UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 gathering_skill_gain = sWorld->getIntConfig(CONFIG_SKILL_GAIN_GATHERING); - sScriptMgr->OnUpdateGatheringSkill(this, SkillId, SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25, gathering_skill_gain); + sScriptMgr->OnPlayerUpdateGatheringSkill(this, SkillId, SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25, gathering_skill_gain); // For skinning and Mining chance decrease with level. 1-74 - no decrease, // 75-149 - 2 times, 225-299 - 8 times @@ -846,7 +846,7 @@ bool Player::UpdateCraftSkill(uint32 spellid) uint32 craft_skill_gain = sWorld->getIntConfig(CONFIG_SKILL_GAIN_CRAFTING); - sScriptMgr->OnUpdateCraftingSkill(this, _spell_idx->second, SkillValue, craft_skill_gain); + sScriptMgr->OnPlayerUpdateCraftingSkill(this, _spell_idx->second, SkillValue, craft_skill_gain); return UpdateSkillPro( _spell_idx->second->SkillLine, @@ -915,7 +915,7 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) LOG_DEBUG("entities.player.skills", "UpdateSkillPro(SkillId {}, Chance {:3.1f}%)", SkillId, Chance / 10.0f); - if (!SkillId || !sScriptMgr->CanPlayerUpdateSkill(this, SkillId)) + if (!SkillId || !sScriptMgr->OnPlayerCanUpdateSkill(this, SkillId)) return false; if (Chance <= 0) // speedup in 0 chance case @@ -936,7 +936,7 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) uint32 SkillValue = SKILL_VALUE(data); uint32 MaxValue = SKILL_MAX(data); - sScriptMgr->OnBeforePlayerUpdateSkill(this, SkillId, SkillValue, MaxValue, step); + sScriptMgr->OnPlayerBeforeUpdateSkill(this, SkillId, SkillValue, MaxValue, step); if (!MaxValue || !SkillValue || SkillValue >= MaxValue) return false; @@ -1383,7 +1383,7 @@ void Player::UpdateEquipSpellsAtFormChange() ApplyEquipSpell(spellInfo, nullptr, false, true); // remove spells that not fit to form - if (!sScriptMgr->CanApplyEquipSpellsItemSet(this, eff)) + if (!sScriptMgr->OnPlayerCanApplyEquipSpellsItemSet(this, eff)) break; ApplyEquipSpell(spellInfo, nullptr, true, true); // add spells that fit form but not active @@ -1461,7 +1461,7 @@ void Player::UpdateFFAPvPState(bool reset /*= true*/) { if (!IsFFAPvP()) { - sScriptMgr->OnFfaPvpStateUpdate(this, true); + sScriptMgr->OnPlayerFfaPvpStateUpdate(this, true); SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) @@ -1483,7 +1483,7 @@ void Player::UpdateFFAPvPState(bool reset /*= true*/) if (HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - sScriptMgr->OnFfaPvpStateUpdate(this, false); + sScriptMgr->OnPlayerFfaPvpStateUpdate(this, false); } for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 0706808ae..49a00a5ae 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -302,7 +302,7 @@ void Player::UpdateMaxHealth() value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina(); value *= GetModifierValue(unitMod, TOTAL_PCT); - sScriptMgr->OnAfterUpdateMaxHealth(this, value); + sScriptMgr->OnPlayerAfterUpdateMaxHealth(this, value); SetMaxHealth((uint32)value); } @@ -317,7 +317,7 @@ void Player::UpdateMaxPower(Powers power) value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower; value *= GetModifierValue(unitMod, TOTAL_PCT); - sScriptMgr->OnAfterUpdateMaxPower(this, power, value); + sScriptMgr->OnPlayerAfterUpdateMaxPower(this, power, value); SetMaxPower(power, uint32(value)); } @@ -332,7 +332,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) float val2 = 0.0f; float level = float(GetLevel()); - sScriptMgr->OnBeforeUpdateAttackPowerAndDamage(this, level, val2, ranged); + sScriptMgr->OnPlayerBeforeUpdateAttackPowerAndDamage(this, level, val2, ranged); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; @@ -499,7 +499,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; - sScriptMgr->OnAfterUpdateAttackPowerAndDamage(this, level, base_attPower, attPowerMod, attPowerMultiplier, ranged); + sScriptMgr->OnPlayerAfterUpdateAttackPowerAndDamage(this, level, base_attPower, attPowerMod, attPowerMultiplier, ranged); SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 43b2568dc..60721d04d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17880,7 +17880,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp if (Unit* owner = killer->GetOwner()) { Unit::ProcDamageAndSpell(owner, victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto, nullptr, -1, spell); - sScriptMgr->OnCreatureKilledByPet( killer->GetCharmerOrOwnerPlayerOrPlayerItself(), victim->ToCreature()); + sScriptMgr->OnPlayerCreatureKilledByPet( killer->GetCharmerOrOwnerPlayerOrPlayerItself(), victim->ToCreature()); } if (killer != victim) @@ -18080,9 +18080,9 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp if (Player* killerPlr = killer->ToPlayer()) { if (Player* killedPlr = victim->ToPlayer()) - sScriptMgr->OnPVPKill(killerPlr, killedPlr); + sScriptMgr->OnPlayerPVPKill(killerPlr, killedPlr); else if (Creature* killedCre = victim->ToCreature()) - sScriptMgr->OnCreatureKill(killerPlr, killedCre); + sScriptMgr->OnPlayerCreatureKill(killerPlr, killedCre); } else if (Creature* killerCre = killer->ToCreature()) { diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 2b294cd68..b3c65b3d3 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1478,7 +1478,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) AllowedLooterSet looters = item->GetAllowedLooters(); Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters); if (_item) - sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), NEED, roll); + sScriptMgr->OnPlayerGroupRollRewardItem(player, _item, _item->GetCount(), NEED, roll); player->UpdateLootAchievements(item, roll->getLoot()); } else @@ -1548,7 +1548,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) AllowedLooterSet looters = item->GetAllowedLooters(); Item* _item = player->StoreNewItem(dest, roll->itemid, true, item->randomPropertyId, looters); if (_item) - sScriptMgr->OnGroupRollRewardItem(player, _item, _item->GetCount(), GREED, roll); + sScriptMgr->OnPlayerGroupRollRewardItem(player, _item, _item->GetCount(), GREED, roll); player->UpdateLootAchievements(item, roll->getLoot()); } else diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 505ad62d6..a3205df4b 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -417,7 +417,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData) AuctionEntry* auction = auctionHouse->GetAuction(auctionId); Player* player = GetPlayer(); - if (!sScriptMgr->CanPlaceAuctionBid(player, auction)) + if (!sScriptMgr->OnPlayerCanPlaceAuctionBid(player, auction)) { SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_RESTRICTED_ACCOUNT); return; diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index 0735dd2d1..d8ae919de 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -140,7 +140,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData) // queue result (default ok) GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bg->GetBgTypeID()); - if (!sScriptMgr->CanJoinInBattlegroundQueue(_player, guid, bgTypeId, joinAsGroup, err) && err <= 0) + if (!sScriptMgr->OnPlayerCanJoinInBattlegroundQueue(_player, guid, bgTypeId, joinAsGroup, err) && err <= 0) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); @@ -424,7 +424,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData) BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenaType); BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); - if (!sScriptMgr->CanBattleFieldPort(_player, arenaType, bgTypeId, action)) + if (!sScriptMgr->OnPlayerCanBattleFieldPort(_player, arenaType, bgTypeId, action)) return; // get group info from queue @@ -579,11 +579,11 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData) CharacterDatabase.Execute(stmt); } - sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_LEAVE_QUEUE); + sScriptMgr->OnPlayerBattlegroundDesertion(_player, BG_DESERTION_TYPE_LEAVE_QUEUE); } if (bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN)) - sScriptMgr->OnBattlegroundDesertion(_player, ARENA_DESERTION_TYPE_LEAVE_QUEUE); + sScriptMgr->OnPlayerBattlegroundDesertion(_player, ARENA_DESERTION_TYPE_LEAVE_QUEUE); } } @@ -748,7 +748,7 @@ void WorldSession::HandleBattlemasterJoinArena(WorldPacket& recvData) // queue result (default ok) GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult(bgt->GetBgTypeID()); - if (!sScriptMgr->CanJoinInArenaQueue(_player, guid, arenaslot, bgTypeId, asGroup, isRated, err) && err <= 0) + if (!sScriptMgr->OnPlayerCanJoinInArenaQueue(_player, guid, arenaslot, bgTypeId, asGroup, isRated, err) && err <= 0) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index a6478b461..c0b378156 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -962,7 +962,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder) if (sWorld->IsFFAPvPRealm() && !pCurrChar->IsGameMaster() && !pCurrChar->HasPlayerFlag(PLAYER_FLAGS_RESTING)) if (!pCurrChar->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { - sScriptMgr->OnFfaPvpStateUpdate(pCurrChar,true); + sScriptMgr->OnPlayerFfaPvpStateUpdate(pCurrChar,true); pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } @@ -1124,7 +1124,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder) if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST)) { pCurrChar->RemoveAtLoginFlag(AT_LOGIN_FIRST); - sScriptMgr->OnFirstLogin(pCurrChar); + sScriptMgr->OnPlayerFirstLogin(pCurrChar); } METRIC_EVENT("player_events", "Login", pCurrChar->GetName()); diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index 963fdcb29..26b4a4495 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -347,7 +347,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) ++_addonMessageReceiveCount; } - sScriptMgr->OnBeforeSendChatMessage(_player, type, lang, msg); + sScriptMgr->OnPlayerBeforeSendChatMessage(_player, type, lang, msg); switch (type) { @@ -433,7 +433,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) if (type == CHAT_MSG_PARTY_LEADER && !group->IsLeader(sender->GetGUID())) return; - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, group)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) { return; } @@ -451,7 +451,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) { if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId())) { - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, guild)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, guild)) { return; } @@ -469,7 +469,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) { if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId())) { - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, guild)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, guild)) { return; } @@ -492,7 +492,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) return; } - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, group)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) { return; } @@ -515,7 +515,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) return; } - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, group)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) { return; } @@ -533,7 +533,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) if (!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID())) || group->isBGGroup()) return; - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, group)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) { return; } @@ -553,7 +553,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) if (!group || !group->isBGGroup()) return; - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, group)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) { return; } @@ -572,7 +572,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetGUID())) return; - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, group)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) { return; } @@ -599,7 +599,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) { if (Channel* chn = cMgr->GetChannel(channel, sender)) { - if (!sScriptMgr->CanPlayerUseChat(sender, type, lang, msg, chn)) + if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg, chn)) { return; } @@ -632,7 +632,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sender->ToggleAFK(); } - if (!sScriptMgr->CanPlayerUseChat(sender, type, lang, msg)) + if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg)) { return; } @@ -660,7 +660,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sender->ToggleDND(); } - if (!sScriptMgr->CanPlayerUseChat(sender, type, lang, msg)) + if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg)) { return; } diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index aac4ade3c..ee4e0676a 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -85,7 +85,7 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData) return; } - if (!sScriptMgr->CanGroupInvite(invitingPlayer, membername)) + if (!sScriptMgr->OnPlayerCanGroupInvite(invitingPlayer, membername)) return; if (invitingPlayer->IsSpectator() || invitedPlayer->IsSpectator()) @@ -230,7 +230,7 @@ void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recvData) return; } - if (!sScriptMgr->CanGroupAccept(GetPlayer(), group)) + if (!sScriptMgr->OnPlayerCanGroupAccept(GetPlayer(), group)) return; if (group->GetLeaderGUID() == GetPlayer()->GetGUID()) diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index fa2f17e62..455fe1591 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -756,7 +756,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData) Item* pItem = _player->GetItemByGuid(itemguid); if (pItem) { - if (!sScriptMgr->CanSellItem(_player, pItem, creature)) + if (!sScriptMgr->OnPlayerCanSellItem(_player, pItem, creature)) return; // prevent sell not owner item diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index cd644bef9..f1b00066b 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -93,7 +93,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData) loot = &creature->loot; } - sScriptMgr->OnAfterCreatureLoot(player); + sScriptMgr->OnPlayerAfterCreatureLoot(player); InventoryResult msg; LootItem* lootItem = player->StoreLootItem(lootSlot, loot, msg); @@ -179,7 +179,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) if (loot) { - sScriptMgr->OnBeforeLootMoney(player, loot); + sScriptMgr->OnPlayerBeforeLootMoney(player, loot); loot->NotifyMoneyRemoved(); if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { @@ -211,7 +211,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) } else { - sScriptMgr->OnAfterCreatureLootMoney(player); + sScriptMgr->OnPlayerAfterCreatureLootMoney(player); player->ModifyMoney(loot->gold); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 387c80298..76cb7fc0d 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -269,7 +269,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) return; } - if (!sScriptMgr->CanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, item)) + if (!sScriptMgr->OnPlayerCanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, item)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_INTERNAL_ERROR); return; @@ -278,7 +278,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) items[i] = item; } - if (!items_count && !sScriptMgr->CanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, nullptr)) + if (!items_count && !sScriptMgr->OnPlayerCanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, nullptr)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_INTERNAL_ERROR); return; @@ -422,14 +422,14 @@ void WorldSession::HandleMailReturnToSender(WorldPacket& recvData) for (MailItemInfoVec::iterator itr = m->items.begin(); itr != m->items.end(); ++itr) { Item* item = player->GetMItem(itr->item_guid); - if (item && !sScriptMgr->CanSendMail(player, ObjectGuid(HighGuid::Player, m->sender), mailbox, m->subject, m->body, m->money, m->COD, item)) + if (item && !sScriptMgr->OnPlayerCanSendMail(player, ObjectGuid(HighGuid::Player, m->sender), mailbox, m->subject, m->body, m->money, m->COD, item)) { player->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_ERR_INTERNAL_ERROR); return; } } } - else if (!sScriptMgr->CanSendMail(player, ObjectGuid(HighGuid::Player, m->sender), mailbox, m->subject, m->body, m->money, m->COD, nullptr)) + else if (!sScriptMgr->OnPlayerCanSendMail(player, ObjectGuid(HighGuid::Player, m->sender), mailbox, m->subject, m->body, m->money, m->COD, nullptr)) { player->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_ERR_INTERNAL_ERROR); return; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 6fe94f321..62a97ab03 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -181,7 +181,7 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recv_data) } else { - sScriptMgr->OnGossipSelectCode(_player, menuId, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str()); + sScriptMgr->OnPlayerGossipSelectCode(_player, menuId, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId), code.c_str()); } } else @@ -204,7 +204,7 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recv_data) } else { - sScriptMgr->OnGossipSelect(_player, menuId, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId)); + sScriptMgr->OnPlayerGossipSelect(_player, menuId, _player->PlayerTalkClass->GetGossipOptionSender(gossipListId), _player->PlayerTalkClass->GetGossipOptionAction(gossipListId)); } } } @@ -742,7 +742,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) { player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - sScriptMgr->OnFfaPvpStateUpdate(player, false); + sScriptMgr->OnPlayerFfaPvpStateUpdate(player, false); } } diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index 7efb33e06..b969e8105 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -904,7 +904,7 @@ void WorldSession::HandleRepairItemOpcode(WorldPacket& recvData) // reputation discount float discountMod = _player->GetReputationPriceDiscount(unit); - sScriptMgr->OnBeforePlayerDurabilityRepair(_player, npcGUID, itemGUID, discountMod, guildBank); + sScriptMgr->OnPlayerBeforeDurabilityRepair(_player, npcGUID, itemGUID, discountMod, guildBank); if (itemGUID) { diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index 302382234..796144a13 100644 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -126,7 +126,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) } } - sScriptMgr->PetitionBuy(_player, creature, charterid, cost, type); + sScriptMgr->OnPlayerPetitionBuy(_player, creature, charterid, cost, type); if (type == GUILD_CHARTER_TYPE) { @@ -840,7 +840,7 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid) if (creature->IsTabardDesigner()) { - sScriptMgr->PetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost); + sScriptMgr->OnPlayerPetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost); data << uint8(1); // count data << uint32(1); // index @@ -859,7 +859,7 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid) // 2v2 data << uint8(3); // count - sScriptMgr->PetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost); + sScriptMgr->OnPlayerPetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost); data << uint32(1); // index data << CharterEntry; // charter entry data << CharterDispayID; // charter display id @@ -873,7 +873,7 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid) CharterCost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_3v3); // 3v3 - sScriptMgr->PetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost); + sScriptMgr->OnPlayerPetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost); data << uint32(2); // index data << CharterEntry; // charter entry data << CharterDispayID; // charter display id @@ -887,7 +887,7 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid) CharterCost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_5v5); // 5v5 - sScriptMgr->PetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost); + sScriptMgr->OnPlayerPetitionShowList(_player, creature, CharterEntry, CharterDispayID, CharterCost); data << uint32(3); // index data << CharterEntry; // charter entry data << CharterDispayID; // charter display id diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 0ba046d39..80063d638 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -424,7 +424,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recvData) _player->RemoveActiveQuest(questId); _player->RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, questId); - sScriptMgr->OnQuestAbandon(_player, questId); + sScriptMgr->OnPlayerQuestAbandon(_player, questId); LOG_DEBUG("network.opcode", "Player {} abandoned quest {}", _player->GetGUID().ToString(), questId); // check if Quest Tracker is enabled diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index e200aaf3d..01a81b097 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -268,7 +268,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) } } - if (sScriptMgr->OnBeforeOpenItem(pUser, item)) + if (sScriptMgr->OnPlayerBeforeOpenItem(pUser, item)) { if (item->IsWrapped())// wrapped? { diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index 3197e0982..ce316965e 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -636,7 +636,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) return; } - if (!sScriptMgr->CanInitTrade(_player, pOther)) + if (!sScriptMgr->OnPlayerCanInitTrade(_player, pOther)) return; // OK start trade @@ -702,7 +702,7 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket) } // PlayerScript Hook for checking traded items if we want to filter them in a custom module - if (!sScriptMgr->CanSetTradeItem(_player, item, tradeSlot)) + if (!sScriptMgr->OnPlayerCanSetTradeItem(_player, item, tradeSlot)) { // Do not send TRADE_STATUS_TRADE_CANCELED because it will cause double display of "Transaction canceled" notification // On the trade initiator screen diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index c00332dd0..8997be846 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -696,7 +696,7 @@ QuestItemList* Loot::FillQuestLoot(Player* player) { LootItem& item = quest_items[i]; - sScriptMgr->OnBeforeFillQuestLootItem(player, item); + sScriptMgr->OnPlayerBeforeFillQuestLootItem(player, item); // Quest item is not free for all and is already assigned to another player // or player doesn't need it diff --git a/src/server/game/Maps/MapMgr.cpp b/src/server/game/Maps/MapMgr.cpp index 2b1fe2b3b..d4cf5493c 100644 --- a/src/server/game/Maps/MapMgr.cpp +++ b/src/server/game/Maps/MapMgr.cpp @@ -161,7 +161,7 @@ Map::EnterState MapMgr::PlayerCannotEnter(uint32 mapid, Player* player, bool log char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; - if (!sScriptMgr->CanEnterMap(player, entry, instance, mapDiff, loginCheck)) + if (!sScriptMgr->OnPlayerCanEnterMap(player, entry, instance, mapDiff, loginCheck)) return Map::CANNOT_ENTER_UNSPECIFIED_REASON; Group* group = player->GetGroup(); diff --git a/src/server/game/Misc/GameGraveyard.cpp b/src/server/game/Misc/GameGraveyard.cpp index 38269a3fc..108c2fb64 100644 --- a/src/server/game/Misc/GameGraveyard.cpp +++ b/src/server/game/Misc/GameGraveyard.cpp @@ -97,7 +97,7 @@ GraveyardStruct const* Graveyard::GetDefaultGraveyard(TeamId teamId) GraveyardStruct const* Graveyard::GetClosestGraveyard(Player* player, TeamId teamId, bool nearCorpse) { uint32 graveyardOverride = 0; - sScriptMgr->OnBeforeChooseGraveyard(player, teamId, nearCorpse, graveyardOverride); + sScriptMgr->OnPlayerBeforeChooseGraveyard(player, teamId, nearCorpse, graveyardOverride); if (graveyardOverride) { return sGraveyard->GetGraveyard(graveyardOverride); diff --git a/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp b/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp index 1f8402644..a02ae745c 100644 --- a/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp @@ -190,7 +190,7 @@ void ScriptMgr::OnPlayerEnterMap(Map* map, Player* player) ExecuteScript([=](PlayerScript* script) { - script->OnMapChanged(player); + script->OnPlayerMapChanged(player); }); ForeachMaps(map, diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 78bea7872..99ef82868 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -19,19 +19,19 @@ #include "ScriptMgr.h" #include "ScriptMgrMacros.h" -void ScriptMgr::OnBeforePlayerDurabilityRepair(Player* player, ObjectGuid npcGUID, ObjectGuid itemGUID, float& discountMod, uint8 guildBank) +void ScriptMgr::OnPlayerBeforeDurabilityRepair(Player* player, ObjectGuid npcGUID, ObjectGuid itemGUID, float& discountMod, uint8 guildBank) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_DURABILITY_REPAIR, script->OnBeforeDurabilityRepair(player, npcGUID, itemGUID, discountMod, guildBank)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_DURABILITY_REPAIR, script->OnPlayerBeforeDurabilityRepair(player, npcGUID, itemGUID, discountMod, guildBank)); } -void ScriptMgr::OnGossipSelect(Player* player, uint32 menu_id, uint32 sender, uint32 action) +void ScriptMgr::OnPlayerGossipSelect(Player* player, uint32 menu_id, uint32 sender, uint32 action) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GOSSIP_SELECT, script->OnGossipSelect(player, menu_id, sender, action)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GOSSIP_SELECT, script->OnPlayerGossipSelect(player, menu_id, sender, action)); } -void ScriptMgr::OnGossipSelectCode(Player* player, uint32 menu_id, uint32 sender, uint32 action, const char* code) +void ScriptMgr::OnPlayerGossipSelectCode(Player* player, uint32 menu_id, uint32 sender, uint32 action, const char* code) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GOSSIP_SELECT_CODE, script->OnGossipSelectCode(player, menu_id, sender, action, code)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GOSSIP_SELECT_CODE, script->OnPlayerGossipSelectCode(player, menu_id, sender, action, code)); } void ScriptMgr::OnPlayerCompleteQuest(Player* player, Quest const* quest) @@ -39,14 +39,14 @@ void ScriptMgr::OnPlayerCompleteQuest(Player* player, Quest const* quest) CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PLAYER_COMPLETE_QUEST, script->OnPlayerCompleteQuest(player, quest)); } -void ScriptMgr::OnSendInitialPacketsBeforeAddToMap(Player* player, WorldPacket& data) +void ScriptMgr::OnPlayerSendInitialPacketsBeforeAddToMap(Player* player, WorldPacket& data) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SEND_INITIAL_PACKETS_BEFORE_ADD_TO_MAP, script->OnSendInitialPacketsBeforeAddToMap(player, data)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SEND_INITIAL_PACKETS_BEFORE_ADD_TO_MAP, script->OnPlayerSendInitialPacketsBeforeAddToMap(player, data)); } -void ScriptMgr::OnBattlegroundDesertion(Player* player, BattlegroundDesertionType const desertionType) +void ScriptMgr::OnPlayerBattlegroundDesertion(Player* player, BattlegroundDesertionType const desertionType) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BATTLEGROUND_DESERTION, script->OnBattlegroundDesertion(player, desertionType)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BATTLEGROUND_DESERTION, script->OnPlayerBattlegroundDesertion(player, desertionType)); } void ScriptMgr::OnPlayerJustDied(Player* player) @@ -54,9 +54,9 @@ void ScriptMgr::OnPlayerJustDied(Player* player) CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PLAYER_JUST_DIED, script->OnPlayerJustDied(player)); } -void ScriptMgr::OnCalculateTalentsPoints(Player const* player, uint32& talentPointsForLevel) +void ScriptMgr::OnPlayerCalculateTalentsPoints(Player const* player, uint32& talentPointsForLevel) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CALCULATE_TALENTS_POINTS, script->OnCalculateTalentsPoints(player, talentPointsForLevel)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CALCULATE_TALENTS_POINTS, script->OnPlayerCalculateTalentsPoints(player, talentPointsForLevel)); } void ScriptMgr::OnPlayerReleasedGhost(Player* player) @@ -64,14 +64,14 @@ void ScriptMgr::OnPlayerReleasedGhost(Player* player) CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PLAYER_RELEASED_GHOST, script->OnPlayerReleasedGhost(player)); } -bool ScriptMgr::OnCanPlayerFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell) +bool ScriptMgr::OnPlayerCanFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_CAN_PLAYER_FLY_IN_ZONE, !script->OnCanPlayerFlyInZone(player, mapId, zoneId, bySpell)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_CAN_PLAYER_FLY_IN_ZONE, !script->OnPlayerCanFlyInZone(player, mapId, zoneId, bySpell)); } -void ScriptMgr::OnPVPKill(Player* killer, Player* killed) +void ScriptMgr::OnPlayerPVPKill(Player* killer, Player* killed) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PVP_KILL, script->OnPVPKill(killer, killed)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PVP_KILL, script->OnPlayerPVPKill(killer, killed)); } void ScriptMgr::OnPlayerPVPFlagChange(Player* player, bool state) @@ -79,14 +79,14 @@ void ScriptMgr::OnPlayerPVPFlagChange(Player* player, bool state) CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PLAYER_PVP_FLAG_CHANGE, script->OnPlayerPVPFlagChange(player, state)); } -void ScriptMgr::OnCreatureKill(Player* killer, Creature* killed) +void ScriptMgr::OnPlayerCreatureKill(Player* killer, Creature* killed) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CREATURE_KILL, script->OnCreatureKill(killer, killed)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CREATURE_KILL, script->OnPlayerCreatureKill(killer, killed)); } -void ScriptMgr::OnCreatureKilledByPet(Player* petOwner, Creature* killed) +void ScriptMgr::OnPlayerCreatureKilledByPet(Player* petOwner, Creature* killed) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CREATURE_KILLED_BY_PET, script->OnCreatureKilledByPet(petOwner, killed)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CREATURE_KILLED_BY_PET, script->OnPlayerCreatureKilledByPet(petOwner, killed)); } void ScriptMgr::OnPlayerKilledByCreature(Creature* killer, Player* killed) @@ -96,257 +96,257 @@ void ScriptMgr::OnPlayerKilledByCreature(Creature* killer, Player* killed) void ScriptMgr::OnPlayerLevelChanged(Player* player, uint8 oldLevel) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LEVEL_CHANGED, script->OnLevelChanged(player, oldLevel)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LEVEL_CHANGED, script->OnPlayerLevelChanged(player, oldLevel)); } void ScriptMgr::OnPlayerFreeTalentPointsChanged(Player* player, uint32 points) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FREE_TALENT_POINTS_CHANGED, script->OnFreeTalentPointsChanged(player, points)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FREE_TALENT_POINTS_CHANGED, script->OnPlayerFreeTalentPointsChanged(player, points)); } void ScriptMgr::OnPlayerTalentsReset(Player* player, bool noCost) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_TALENTS_RESET, script->OnTalentsReset(player, noCost)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_TALENTS_RESET, script->OnPlayerTalentsReset(player, noCost)); } -void ScriptMgr::OnAfterSpecSlotChanged(Player* player, uint8 newSlot) +void ScriptMgr::OnPlayerAfterSpecSlotChanged(Player* player, uint8 newSlot) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_SPEC_SLOT_CHANGED, script->OnAfterSpecSlotChanged(player, newSlot)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_SPEC_SLOT_CHANGED, script->OnPlayerAfterSpecSlotChanged(player, newSlot)); } void ScriptMgr::OnPlayerMoneyChanged(Player* player, int32& amount) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_MONEY_CHANGED, script->OnMoneyChanged(player, amount)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_MONEY_CHANGED, script->OnPlayerMoneyChanged(player, amount)); } -void ScriptMgr::OnBeforeLootMoney(Player* player, Loot* loot) +void ScriptMgr::OnPlayerBeforeLootMoney(Player* player, Loot* loot) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_LOOT_MONEY, script->OnBeforeLootMoney(player, loot)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_LOOT_MONEY, script->OnPlayerBeforeLootMoney(player, loot)); } -void ScriptMgr::OnGivePlayerXP(Player* player, uint32& amount, Unit* victim, uint8 xpSource) +void ScriptMgr::OnPlayerGiveXP(Player* player, uint32& amount, Unit* victim, uint8 xpSource) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GIVE_EXP, script->OnGiveXP(player, amount, victim, xpSource)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GIVE_EXP, script->OnPlayerGiveXP(player, amount, victim, xpSource)); } bool ScriptMgr::OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_REPUTATION_CHANGE, !script->OnReputationChange(player, factionID, standing, incremental)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_REPUTATION_CHANGE, !script->OnPlayerReputationChange(player, factionID, standing, incremental)); } void ScriptMgr::OnPlayerReputationRankChange(Player* player, uint32 factionID, ReputationRank newRank, ReputationRank oldRank, bool increased) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_REPUTATION_RANK_CHANGE, script->OnReputationRankChange(player, factionID, newRank, oldRank, increased)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_REPUTATION_RANK_CHANGE, script->OnPlayerReputationRankChange(player, factionID, newRank, oldRank, increased)); } void ScriptMgr::OnPlayerLearnSpell(Player* player, uint32 spellID) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LEARN_SPELL, script->OnLearnSpell(player, spellID)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LEARN_SPELL, script->OnPlayerLearnSpell(player, spellID)); } void ScriptMgr::OnPlayerForgotSpell(Player* player, uint32 spellID) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FORGOT_SPELL, script->OnForgotSpell(player, spellID)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FORGOT_SPELL, script->OnPlayerForgotSpell(player, spellID)); } void ScriptMgr::OnPlayerDuelRequest(Player* target, Player* challenger) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DUEL_REQUEST, script->OnDuelRequest(target, challenger)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DUEL_REQUEST, script->OnPlayerDuelRequest(target, challenger)); } void ScriptMgr::OnPlayerDuelStart(Player* player1, Player* player2) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DUEL_START, script->OnDuelStart(player1, player2)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DUEL_START, script->OnPlayerDuelStart(player1, player2)); } void ScriptMgr::OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DUEL_END, script->OnDuelEnd(winner, loser, type)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DUEL_END, script->OnPlayerDuelEnd(winner, loser, type)); } void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT, script->OnChat(player, type, lang, msg)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT, script->OnPlayerChat(player, type, lang, msg)); } -void ScriptMgr::OnBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& msg) +void ScriptMgr::OnPlayerBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& msg) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_SEND_CHAT_MESSAGE, script->OnBeforeSendChatMessage(player, type, lang, msg)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_SEND_CHAT_MESSAGE, script->OnPlayerBeforeSendChatMessage(player, type, lang, msg)); } void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Player* receiver) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_RECEIVER, script->OnChat(player, type, lang, msg, receiver)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_RECEIVER, script->OnPlayerChat(player, type, lang, msg, receiver)); } void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_GROUP, script->OnChat(player, type, lang, msg, group)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_GROUP, script->OnPlayerChat(player, type, lang, msg, group)); } void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_GUILD, script->OnChat(player, type, lang, msg, guild)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_GUILD, script->OnPlayerChat(player, type, lang, msg, guild)); } void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Channel* channel) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_CHANNEL, script->OnChat(player, type, lang, msg, channel)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_CHANNEL, script->OnPlayerChat(player, type, lang, msg, channel)); } void ScriptMgr::OnPlayerEmote(Player* player, uint32 emote) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_EMOTE, script->OnEmote(player, emote)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_EMOTE, script->OnPlayerEmote(player, emote)); } void ScriptMgr::OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_TEXT_EMOTE, script->OnTextEmote(player, textEmote, emoteNum, guid)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_TEXT_EMOTE, script->OnPlayerTextEmote(player, textEmote, emoteNum, guid)); } void ScriptMgr::OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SPELL_CAST, script->OnSpellCast(player, spell, skipCheck)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SPELL_CAST, script->OnPlayerSpellCast(player, spell, skipCheck)); } -void ScriptMgr::OnBeforePlayerUpdate(Player* player, uint32 p_time) +void ScriptMgr::OnPlayerBeforeUpdate(Player* player, uint32 p_time) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_UPDATE, script->OnBeforeUpdate(player, p_time)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_UPDATE, script->OnPlayerBeforeUpdate(player, p_time)); } void ScriptMgr::OnPlayerUpdate(Player* player, uint32 p_time) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE, script->OnUpdate(player, p_time)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE, script->OnPlayerUpdate(player, p_time)); } void ScriptMgr::OnPlayerLogin(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LOGIN, script->OnLogin(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LOGIN, script->OnPlayerLogin(player)); } void ScriptMgr::OnPlayerLoadFromDB(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LOAD_FROM_DB, script->OnLoadFromDB(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LOAD_FROM_DB, script->OnPlayerLoadFromDB(player)); } -void ScriptMgr::OnBeforePlayerLogout(Player* player) +void ScriptMgr::OnPlayerBeforeLogout(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_LOGOUT, script->OnBeforeLogout(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_LOGOUT, script->OnPlayerBeforeLogout(player)); } void ScriptMgr::OnPlayerLogout(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LOGOUT, script->OnLogout(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LOGOUT, script->OnPlayerLogout(player)); } void ScriptMgr::OnPlayerCreate(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CREATE, script->OnCreate(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CREATE, script->OnPlayerCreate(player)); } void ScriptMgr::OnPlayerSave(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SAVE, script->OnSave(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SAVE, script->OnPlayerSave(player)); } void ScriptMgr::OnPlayerDelete(ObjectGuid guid, uint32 accountId) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DELETE, script->OnDelete(guid, accountId)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DELETE, script->OnPlayerDelete(guid, accountId)); } void ScriptMgr::OnPlayerFailedDelete(ObjectGuid guid, uint32 accountId) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FAILED_DELETE, script->OnFailedDelete(guid, accountId)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FAILED_DELETE, script->OnPlayerFailedDelete(guid, accountId)); } void ScriptMgr::OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BIND_TO_INSTANCE, script->OnBindToInstance(player, difficulty, mapid, permanent)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BIND_TO_INSTANCE, script->OnPlayerBindToInstance(player, difficulty, mapid, permanent)); } void ScriptMgr::OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_ZONE, script->OnUpdateZone(player, newZone, newArea)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_ZONE, script->OnPlayerUpdateZone(player, newZone, newArea)); } void ScriptMgr::OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_AREA, script->OnUpdateArea(player, oldArea, newArea)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_AREA, script->OnPlayerUpdateArea(player, oldArea, newArea)); } -bool ScriptMgr::OnBeforePlayerTeleport(Player* player, uint32 mapid, float x, float y, float z, float orientation, uint32 options, Unit* target) +bool ScriptMgr::OnPlayerBeforeTeleport(Player* player, uint32 mapid, float x, float y, float z, float orientation, uint32 options, Unit* target) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_TELEPORT, !script->OnBeforeTeleport(player, mapid, x, y, z, orientation, options, target)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_TELEPORT, !script->OnPlayerBeforeTeleport(player, mapid, x, y, z, orientation, options, target)); } void ScriptMgr::OnPlayerUpdateFaction(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_FACTION, script->OnUpdateFaction(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_FACTION, script->OnPlayerUpdateFaction(player)); } void ScriptMgr::OnPlayerAddToBattleground(Player* player, Battleground* bg) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_ADD_TO_BATTLEGROUND, script->OnAddToBattleground(player, bg)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_ADD_TO_BATTLEGROUND, script->OnPlayerAddToBattleground(player, bg)); } void ScriptMgr::OnPlayerQueueRandomDungeon(Player* player, uint32 & rDungeonId) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_QUEUE_RANDOM_DUNGEON, script->OnQueueRandomDungeon(player, rDungeonId)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_QUEUE_RANDOM_DUNGEON, script->OnPlayerQueueRandomDungeon(player, rDungeonId)); } void ScriptMgr::OnPlayerRemoveFromBattleground(Player* player, Battleground* bg) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_REMOVE_FROM_BATTLEGROUND, script->OnRemoveFromBattleground(player, bg)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_REMOVE_FROM_BATTLEGROUND, script->OnPlayerRemoveFromBattleground(player, bg)); } -bool ScriptMgr::OnBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) +bool ScriptMgr::OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_ACHI_COMPLETE, !script->OnBeforeAchiComplete(player, achievement)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_ACHI_COMPLETE, !script->OnPlayerBeforeAchievementComplete(player, achievement)); } -void ScriptMgr::OnAchievementComplete(Player* player, AchievementEntry const* achievement) +void ScriptMgr::OnPlayerAchievementComplete(Player* player, AchievementEntry const* achievement) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_ACHI_COMPLETE, script->OnAchiComplete(player, achievement)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_ACHI_COMPLETE, script->OnPlayerAchievementComplete(player, achievement)); } -bool ScriptMgr::OnBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* criteria) +bool ScriptMgr::OnPlayerBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* criteria) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_CRITERIA_PROGRESS, !script->OnBeforeCriteriaProgress(player, criteria)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_CRITERIA_PROGRESS, !script->OnPlayerBeforeCriteriaProgress(player, criteria)); } -void ScriptMgr::OnCriteriaProgress(Player* player, AchievementCriteriaEntry const* criteria) +void ScriptMgr::OnPlayerCriteriaProgress(Player* player, AchievementCriteriaEntry const* criteria) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CRITERIA_PROGRESS, script->OnCriteriaProgress(player, criteria)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CRITERIA_PROGRESS, script->OnPlayerCriteriaProgress(player, criteria)); } -void ScriptMgr::OnAchievementSave(CharacterDatabaseTransaction trans, Player* player, uint16 achiId, CompletedAchievementData achiData) +void ScriptMgr::OnPlayerAchievementSave(CharacterDatabaseTransaction trans, Player* player, uint16 achiId, CompletedAchievementData achiData) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_ACHI_SAVE, script->OnAchiSave(trans, player, achiId, achiData)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_ACHI_SAVE, script->OnPlayerAchievementSave(trans, player, achiId, achiData)); } -void ScriptMgr::OnCriteriaSave(CharacterDatabaseTransaction trans, Player* player, uint16 critId, CriteriaProgress criteriaData) +void ScriptMgr::OnPlayerCriteriaSave(CharacterDatabaseTransaction trans, Player* player, uint16 critId, CriteriaProgress criteriaData) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CRITERIA_SAVE, script->OnCriteriaSave(trans, player, critId, criteriaData)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CRITERIA_SAVE, script->OnPlayerCriteriaSave(trans, player, critId, criteriaData)); } void ScriptMgr::OnPlayerBeingCharmed(Player* player, Unit* charmer, uint32 oldFactionId, uint32 newFactionId) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEING_CHARMED, script->OnBeingCharmed(player, charmer, oldFactionId, newFactionId)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEING_CHARMED, script->OnPlayerBeingCharmed(player, charmer, oldFactionId, newFactionId)); } -void ScriptMgr::OnAfterPlayerSetVisibleItemSlot(Player* player, uint8 slot, Item* item) +void ScriptMgr::OnPlayerAfterSetVisibleItemSlot(Player* player, uint8 slot, Item* item) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_SET_VISIBLE_ITEM_SLOT, script->OnAfterSetVisibleItemSlot(player, slot, item)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_SET_VISIBLE_ITEM_SLOT, script->OnPlayerAfterSetVisibleItemSlot(player, slot, item)); } -void ScriptMgr::OnAfterPlayerMoveItemFromInventory(Player* player, Item* it, uint8 bag, uint8 slot, bool update) +void ScriptMgr::OnPlayerAfterMoveItemFromInventory(Player* player, Item* it, uint8 bag, uint8 slot, bool update) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_MOVE_ITEM_FROM_INVENTORY, script->OnAfterMoveItemFromInventory(player, it, bag, slot, update)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_MOVE_ITEM_FROM_INVENTORY, script->OnPlayerAfterMoveItemFromInventory(player, it, bag, slot, update)); } -void ScriptMgr::OnEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool update) +void ScriptMgr::OnPlayerEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool update) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_EQUIP, script->OnEquip(player, it, bag, slot, update)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_EQUIP, script->OnPlayerEquip(player, it, bag, slot, update)); } void ScriptMgr::OnPlayerJoinBG(Player* player) @@ -359,214 +359,214 @@ void ScriptMgr::OnPlayerJoinArena(Player* player) CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PLAYER_JOIN_ARENA, script->OnPlayerJoinArena(player)); } -void ScriptMgr::OnGetMaxPersonalArenaRatingRequirement(Player const* player, uint32 minSlot, uint32& maxArenaRating) const +void ScriptMgr::OnPlayerGetMaxPersonalArenaRatingRequirement(Player const* player, uint32 minSlot, uint32& maxArenaRating) const { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_MAX_PERSONAL_ARENA_RATING_REQUIREMENT, script->OnGetMaxPersonalArenaRatingRequirement(player, minSlot, maxArenaRating)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_MAX_PERSONAL_ARENA_RATING_REQUIREMENT, script->OnPlayerGetMaxPersonalArenaRatingRequirement(player, minSlot, maxArenaRating)); } -void ScriptMgr::OnLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid) +void ScriptMgr::OnPlayerLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LOOT_ITEM, script->OnLootItem(player, item, count, lootguid)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LOOT_ITEM, script->OnPlayerLootItem(player, item, count, lootguid)); } -void ScriptMgr::OnBeforeFillQuestLootItem(Player* player, LootItem& item) +void ScriptMgr::OnPlayerBeforeFillQuestLootItem(Player* player, LootItem& item) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_FILL_QUEST_LOOT_ITEM, script->OnBeforeFillQuestLootItem(player, item)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_FILL_QUEST_LOOT_ITEM, script->OnPlayerBeforeFillQuestLootItem(player, item)); } -void ScriptMgr::OnStoreNewItem(Player* player, Item* item, uint32 count) +void ScriptMgr::OnPlayerStoreNewItem(Player* player, Item* item, uint32 count) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_STORE_NEW_ITEM, script->OnStoreNewItem(player, item, count)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_STORE_NEW_ITEM, script->OnPlayerStoreNewItem(player, item, count)); } -void ScriptMgr::OnCreateItem(Player* player, Item* item, uint32 count) +void ScriptMgr::OnPlayerCreateItem(Player* player, Item* item, uint32 count) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CREATE_ITEM, script->OnCreateItem(player, item, count)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CREATE_ITEM, script->OnPlayerCreateItem(player, item, count)); } -void ScriptMgr::OnQuestRewardItem(Player* player, Item* item, uint32 count) +void ScriptMgr::OnPlayerQuestRewardItem(Player* player, Item* item, uint32 count) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_QUEST_REWARD_ITEM, script->OnQuestRewardItem(player, item, count)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_QUEST_REWARD_ITEM, script->OnPlayerQuestRewardItem(player, item, count)); } -bool ScriptMgr::CanPlaceAuctionBid(Player* player, AuctionEntry* auction) +bool ScriptMgr::OnPlayerCanPlaceAuctionBid(Player* player, AuctionEntry* auction) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLACE_AUCTION_BID, !script->CanPlaceAuctionBid(player, auction)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLACE_AUCTION_BID, !script->OnPlayerCanPlaceAuctionBid(player, auction)); } -void ScriptMgr::OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll) +void ScriptMgr::OnPlayerGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GROUP_ROLL_REWARD_ITEM, script->OnGroupRollRewardItem(player, item, count, voteType, roll)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GROUP_ROLL_REWARD_ITEM, script->OnPlayerGroupRollRewardItem(player, item, count, voteType, roll)); } -bool ScriptMgr::OnBeforeOpenItem(Player* player, Item* item) +bool ScriptMgr::OnPlayerBeforeOpenItem(Player* player, Item* item) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_OPEN_ITEM, !script->OnBeforeOpenItem(player, item)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_OPEN_ITEM, !script->OnPlayerBeforeOpenItem(player, item)); } -void ScriptMgr::OnFirstLogin(Player* player) +void ScriptMgr::OnPlayerFirstLogin(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FIRST_LOGIN, script->OnFirstLogin(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FIRST_LOGIN, script->OnPlayerFirstLogin(player)); } -void ScriptMgr::OnSetMaxLevel(Player* player, uint32& maxPlayerLevel) +void ScriptMgr::OnPlayerSetMaxLevel(Player* player, uint32& maxPlayerLevel) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SET_MAX_LEVEL, script->OnSetMaxLevel(player, maxPlayerLevel)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SET_MAX_LEVEL, script->OnPlayerSetMaxLevel(player, maxPlayerLevel)); } -bool ScriptMgr::CanJoinInBattlegroundQueue(Player* player, ObjectGuid BattlemasterGuid, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, GroupJoinBattlegroundResult& err) +bool ScriptMgr::OnPlayerCanJoinInBattlegroundQueue(Player* player, ObjectGuid BattlemasterGuid, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, GroupJoinBattlegroundResult& err) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_JOIN_IN_BATTLEGROUND_QUEUE, !script->CanJoinInBattlegroundQueue(player, BattlemasterGuid, BGTypeID, joinAsGroup, err)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_JOIN_IN_BATTLEGROUND_QUEUE, !script->OnPlayerCanJoinInBattlegroundQueue(player, BattlemasterGuid, BGTypeID, joinAsGroup, err)); } -bool ScriptMgr::ShouldBeRewardedWithMoneyInsteadOfExp(Player* player) +bool ScriptMgr::OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(Player* player) { - CALL_ENABLED_BOOLEAN_HOOKS_WITH_DEFAULT_FALSE(PlayerScript, PLAYERHOOK_SHOULD_BE_REWARDED_WITH_MONEY_INSTEAD_OF_EXP, script->ShouldBeRewardedWithMoneyInsteadOfExp(player)); + CALL_ENABLED_BOOLEAN_HOOKS_WITH_DEFAULT_FALSE(PlayerScript, PLAYERHOOK_SHOULD_BE_REWARDED_WITH_MONEY_INSTEAD_OF_EXP, script->OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(player)); } -void ScriptMgr::OnBeforeTempSummonInitStats(Player* player, TempSummon* tempSummon, uint32& duration) +void ScriptMgr::OnPlayerBeforeTempSummonInitStats(Player* player, TempSummon* tempSummon, uint32& duration) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_TEMP_SUMMON_INIT_STATS, script->OnBeforeTempSummonInitStats(player, tempSummon, duration)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_TEMP_SUMMON_INIT_STATS, script->OnPlayerBeforeTempSummonInitStats(player, tempSummon, duration)); } -void ScriptMgr::OnBeforeGuardianInitStatsForLevel(Player* player, Guardian* guardian, CreatureTemplate const* cinfo, PetType& petType) +void ScriptMgr::OnPlayerBeforeGuardianInitStatsForLevel(Player* player, Guardian* guardian, CreatureTemplate const* cinfo, PetType& petType) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_GUARDIAN_INIT_STATS_FOR_LEVEL, script->OnBeforeGuardianInitStatsForLevel(player, guardian, cinfo, petType)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_GUARDIAN_INIT_STATS_FOR_LEVEL, script->OnPlayerBeforeGuardianInitStatsForLevel(player, guardian, cinfo, petType)); } -void ScriptMgr::OnAfterGuardianInitStatsForLevel(Player* player, Guardian* guardian) +void ScriptMgr::OnPlayerAfterGuardianInitStatsForLevel(Player* player, Guardian* guardian) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_GUARDIAN_INIT_STATS_FOR_LEVEL, script->OnAfterGuardianInitStatsForLevel(player, guardian)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_GUARDIAN_INIT_STATS_FOR_LEVEL, script->OnPlayerAfterGuardianInitStatsForLevel(player, guardian)); } -void ScriptMgr::OnBeforeLoadPetFromDB(Player* player, uint32& petentry, uint32& petnumber, bool& current, bool& forceLoadFromDB) +void ScriptMgr::OnPlayerBeforeLoadPetFromDB(Player* player, uint32& petentry, uint32& petnumber, bool& current, bool& forceLoadFromDB) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_LOAD_PET_FROM_DB, script->OnBeforeLoadPetFromDB(player, petentry, petnumber, current, forceLoadFromDB)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_LOAD_PET_FROM_DB, script->OnPlayerBeforeLoadPetFromDB(player, petentry, petnumber, current, forceLoadFromDB)); } -void ScriptMgr::OnBeforeBuyItemFromVendor(Player* player, ObjectGuid vendorguid, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot) +void ScriptMgr::OnPlayerBeforeBuyItemFromVendor(Player* player, ObjectGuid vendorguid, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_BUY_ITEM_FROM_VENDOR, script->OnBeforeBuyItemFromVendor(player, vendorguid, vendorslot, item, count, bag, slot)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_BUY_ITEM_FROM_VENDOR, script->OnPlayerBeforeBuyItemFromVendor(player, vendorguid, vendorslot, item, count, bag, slot)); } -void ScriptMgr::OnAfterStoreOrEquipNewItem(Player* player, uint32 vendorslot, Item* item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore) +void ScriptMgr::OnPlayerAfterStoreOrEquipNewItem(Player* player, uint32 vendorslot, Item* item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_STORE_OR_EQUIP_NEW_ITEM, script->OnAfterStoreOrEquipNewItem(player, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_STORE_OR_EQUIP_NEW_ITEM, script->OnPlayerAfterStoreOrEquipNewItem(player, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore)); } -void ScriptMgr::OnAfterUpdateMaxPower(Player* player, Powers& power, float& value) +void ScriptMgr::OnPlayerAfterUpdateMaxPower(Player* player, Powers& power, float& value) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_UPDATE_MAX_POWER, script->OnAfterUpdateMaxPower(player, power, value)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_UPDATE_MAX_POWER, script->OnPlayerAfterUpdateMaxPower(player, power, value)); } -void ScriptMgr::OnAfterUpdateMaxHealth(Player* player, float& value) +void ScriptMgr::OnPlayerAfterUpdateMaxHealth(Player* player, float& value) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_UPDATE_MAX_HEALTH, script->OnAfterUpdateMaxHealth(player, value)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_UPDATE_MAX_HEALTH, script->OnPlayerAfterUpdateMaxHealth(player, value)); } -void ScriptMgr::OnBeforeUpdateAttackPowerAndDamage(Player* player, float& level, float& val2, bool ranged) +void ScriptMgr::OnPlayerBeforeUpdateAttackPowerAndDamage(Player* player, float& level, float& val2, bool ranged) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_UPDATE_ATTACK_POWER_AND_DAMAGE, script->OnBeforeUpdateAttackPowerAndDamage(player, level, val2, ranged)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_UPDATE_ATTACK_POWER_AND_DAMAGE, script->OnPlayerBeforeUpdateAttackPowerAndDamage(player, level, val2, ranged)); } -void ScriptMgr::OnAfterUpdateAttackPowerAndDamage(Player* player, float& level, float& base_attPower, float& attPowerMod, float& attPowerMultiplier, bool ranged) +void ScriptMgr::OnPlayerAfterUpdateAttackPowerAndDamage(Player* player, float& level, float& base_attPower, float& attPowerMod, float& attPowerMultiplier, bool ranged) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_UPDATE_ATTACK_POWER_AND_DAMAGE, script->OnAfterUpdateAttackPowerAndDamage(player, level, base_attPower, attPowerMod, attPowerMultiplier, ranged)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_UPDATE_ATTACK_POWER_AND_DAMAGE, script->OnPlayerAfterUpdateAttackPowerAndDamage(player, level, base_attPower, attPowerMod, attPowerMultiplier, ranged)); } -void ScriptMgr::OnBeforeInitTalentForLevel(Player* player, uint8& level, uint32& talentPointsForLevel) +void ScriptMgr::OnPlayerBeforeInitTalentForLevel(Player* player, uint8& level, uint32& talentPointsForLevel) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_INIT_TALENT_FOR_LEVEL, script->OnBeforeInitTalentForLevel(player, level, talentPointsForLevel)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_INIT_TALENT_FOR_LEVEL, script->OnPlayerBeforeInitTalentForLevel(player, level, talentPointsForLevel)); } -bool ScriptMgr::OnBeforePlayerQuestComplete(Player* player, uint32 quest_id) +bool ScriptMgr::OnPlayerBeforeQuestComplete(Player* player, uint32 quest_id) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_QUEST_COMPLETE, !script->OnBeforeQuestComplete(player, quest_id)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_QUEST_COMPLETE, !script->OnPlayerBeforeQuestComplete(player, quest_id)); } -void ScriptMgr::OnQuestComputeXP(Player* player, Quest const* quest, uint32& xpValue) +void ScriptMgr::OnPlayerQuestComputeXP(Player* player, Quest const* quest, uint32& xpValue) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_QUEST_COMPUTE_EXP, script->OnQuestComputeXP(player, quest, xpValue)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_QUEST_COMPUTE_EXP, script->OnPlayerQuestComputeXP(player, quest, xpValue)); } -void ScriptMgr::OnBeforeStoreOrEquipNewItem(Player* player, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore) +void ScriptMgr::OnPlayerBeforeStoreOrEquipNewItem(Player* player, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_STORE_OR_EQUIP_NEW_ITEM, script->OnBeforeStoreOrEquipNewItem(player, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_STORE_OR_EQUIP_NEW_ITEM, script->OnPlayerBeforeStoreOrEquipNewItem(player, vendorslot, item, count, bag, slot, pProto, pVendor, crItem, bStore)); } -bool ScriptMgr::CanJoinInArenaQueue(Player* player, ObjectGuid BattlemasterGuid, uint8 arenaslot, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, uint8 IsRated, GroupJoinBattlegroundResult& err) +bool ScriptMgr::OnPlayerCanJoinInArenaQueue(Player* player, ObjectGuid BattlemasterGuid, uint8 arenaslot, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, uint8 IsRated, GroupJoinBattlegroundResult& err) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_JOIN_IN_ARENA_QUEUE, !script->CanJoinInArenaQueue(player, BattlemasterGuid, arenaslot, BGTypeID, joinAsGroup, IsRated, err)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_JOIN_IN_ARENA_QUEUE, !script->OnPlayerCanJoinInArenaQueue(player, BattlemasterGuid, arenaslot, BGTypeID, joinAsGroup, IsRated, err)); } -bool ScriptMgr::CanBattleFieldPort(Player* player, uint8 arenaType, BattlegroundTypeId BGTypeID, uint8 action) +bool ScriptMgr::OnPlayerCanBattleFieldPort(Player* player, uint8 arenaType, BattlegroundTypeId BGTypeID, uint8 action) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_BATTLEFIELD_PORT, !script->CanBattleFieldPort(player, arenaType, BGTypeID, action)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_BATTLEFIELD_PORT, !script->OnPlayerCanBattleFieldPort(player, arenaType, BGTypeID, action)); } -bool ScriptMgr::CanGroupInvite(Player* player, std::string& membername) +bool ScriptMgr::OnPlayerCanGroupInvite(Player* player, std::string& membername) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_GROUP_INVITE, !script->CanGroupInvite(player, membername)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_GROUP_INVITE, !script->OnPlayerCanGroupInvite(player, membername)); } -bool ScriptMgr::CanGroupAccept(Player* player, Group* group) +bool ScriptMgr::OnPlayerCanGroupAccept(Player* player, Group* group) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_GROUP_ACCEPT, !script->CanGroupAccept(player, group)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_GROUP_ACCEPT, !script->OnPlayerCanGroupAccept(player, group)); } -bool ScriptMgr::CanSellItem(Player* player, Item* item, Creature* creature) +bool ScriptMgr::OnPlayerCanSellItem(Player* player, Item* item, Creature* creature) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SELL_ITEM, !script->CanSellItem(player, item, creature)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SELL_ITEM, !script->OnPlayerCanSellItem(player, item, creature)); } -bool ScriptMgr::CanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item) +bool ScriptMgr::OnPlayerCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SEND_MAIL, !script->CanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, item)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SEND_MAIL, !script->OnPlayerCanSendMail(player, receiverGuid, mailbox, subject, body, money, COD, item)); } -bool ScriptMgr::CanSendErrorAlreadyLooted(Player* player) +bool ScriptMgr::OnPlayerCanSendErrorAlreadyLooted(Player* player) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SEND_ERROR_ALREADY_LOOTED, !script->CanSendErrorAlreadyLooted(player)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SEND_ERROR_ALREADY_LOOTED, !script->OnPlayerCanSendErrorAlreadyLooted(player)); } -void ScriptMgr::OnAfterCreatureLoot(Player* player) +void ScriptMgr::OnPlayerAfterCreatureLoot(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_CREATURE_LOOT, script->OnAfterCreatureLoot(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_CREATURE_LOOT, script->OnPlayerAfterCreatureLoot(player)); } -void ScriptMgr::OnAfterCreatureLootMoney(Player* player) +void ScriptMgr::OnPlayerAfterCreatureLootMoney(Player* player) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_CREATURE_LOOT_MONEY, script->OnAfterCreatureLootMoney(player)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_AFTER_CREATURE_LOOT_MONEY, script->OnPlayerAfterCreatureLootMoney(player)); } -void ScriptMgr::PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type) +void ScriptMgr::OnPlayerPetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_PETITION_BUY, script->PetitionBuy(player, creature, charterid, cost, type)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_PETITION_BUY, script->OnPlayerPetitionBuy(player, creature, charterid, cost, type)); } -void ScriptMgr::PetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost) +void ScriptMgr::OnPlayerPetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_PETITION_SHOW_LIST, script->PetitionShowList(player, creature, CharterEntry, CharterDispayID, CharterCost)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_PETITION_SHOW_LIST, script->OnPlayerPetitionShowList(player, creature, CharterEntry, CharterDispayID, CharterCost)); } -void ScriptMgr::OnRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate) +void ScriptMgr::OnPlayerRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_REWARD_KILL_REWARDER, script->OnRewardKillRewarder(player, rewarder, isDungeon, rate)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_REWARD_KILL_REWARDER, script->OnPlayerRewardKillRewarder(player, rewarder, isDungeon, rate)); } -bool ScriptMgr::CanGiveMailRewardAtGiveLevel(Player* player, uint8 level) +bool ScriptMgr::OnPlayerCanGiveMailRewardAtGiveLevel(Player* player, uint8 level) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_GIVE_MAIL_REWARD_AT_GIVE_LEVEL, !script->CanGiveMailRewardAtGiveLevel(player, level)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_GIVE_MAIL_REWARD_AT_GIVE_LEVEL, !script->OnPlayerCanGiveMailRewardAtGiveLevel(player, level)); } -void ScriptMgr::OnDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid) +void ScriptMgr::OnPlayerDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DELETE_FROM_DB, script->OnDeleteFromDB(trans, guid)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DELETE_FROM_DB, script->OnPlayerDeleteFromDB(trans, guid)); } -bool ScriptMgr::CanRepopAtGraveyard(Player* player) +bool ScriptMgr::OnPlayerCanRepopAtGraveyard(Player* player) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_REPOP_AT_GRAVEYARD, !script->CanRepopAtGraveyard(player)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_REPOP_AT_GRAVEYARD, !script->OnPlayerCanRepopAtGraveyard(player)); } Optional ScriptMgr::OnPlayerIsClass(Player const* player, Classes unitClass, ClassContext context) @@ -584,9 +584,9 @@ Optional ScriptMgr::OnPlayerIsClass(Player const* player, Classes unitClas return {}; } -void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure) +void ScriptMgr::OnPlayerGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_MAX_SKILL_VALUE, script->OnGetMaxSkillValue(player, skill, result, IsPure)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_MAX_SKILL_VALUE, script->OnPlayerGetMaxSkillValue(player, skill, result, IsPure)); } bool ScriptMgr::OnPlayerHasActivePowerType(Player const* player, Powers power) @@ -594,214 +594,214 @@ bool ScriptMgr::OnPlayerHasActivePowerType(Player const* player, Powers power) CALL_ENABLED_BOOLEAN_HOOKS_WITH_DEFAULT_FALSE(PlayerScript, PLAYERHOOK_ON_PLAYER_HAS_ACTIVE_POWER_TYPE, script->OnPlayerHasActivePowerType(player, power)); } -void ScriptMgr::OnUpdateGatheringSkill(Player *player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32 &gain) +void ScriptMgr::OnPlayerUpdateGatheringSkill(Player *player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32 &gain) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_GATHERING_SKILL, script->OnUpdateGatheringSkill(player, skillId, currentLevel, gray, green, yellow, gain)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_GATHERING_SKILL, script->OnPlayerUpdateGatheringSkill(player, skillId, currentLevel, gray, green, yellow, gain)); } -void ScriptMgr::OnUpdateCraftingSkill(Player *player, SkillLineAbilityEntry const* skill, uint32 currentLevel, uint32& gain) +void ScriptMgr::OnPlayerUpdateCraftingSkill(Player *player, SkillLineAbilityEntry const* skill, uint32 currentLevel, uint32& gain) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_CRAFTING_SKILL, script->OnUpdateCraftingSkill(player, skill, currentLevel, gain)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_CRAFTING_SKILL, script->OnPlayerUpdateCraftingSkill(player, skill, currentLevel, gain)); } -bool ScriptMgr::OnUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll) +bool ScriptMgr::OnPlayerUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_FISHING_SKILL, !script->OnUpdateFishingSkill(player, skill, zone_skill, chance, roll)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_FISHING_SKILL, !script->OnPlayerUpdateFishingSkill(player, skill, zone_skill, chance, roll)); } -bool ScriptMgr::CanAreaExploreAndOutdoor(Player* player) +bool ScriptMgr::OnPlayerCanAreaExploreAndOutdoor(Player* player) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_AREA_EXPLORE_AND_OUTDOOR, !script->CanAreaExploreAndOutdoor(player)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_AREA_EXPLORE_AND_OUTDOOR, !script->OnPlayerCanAreaExploreAndOutdoor(player)); } -void ScriptMgr::OnVictimRewardBefore(Player* player, Player* victim, uint32& killer_title, uint32& victim_title) +void ScriptMgr::OnPlayerVictimRewardBefore(Player* player, Player* victim, uint32& killer_title, uint32& victim_title) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_VICTIM_REWARD_BEFORE, script->OnVictimRewardBefore(player, victim, killer_title, victim_title)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_VICTIM_REWARD_BEFORE, script->OnPlayerVictimRewardBefore(player, victim, killer_title, victim_title)); } -void ScriptMgr::OnVictimRewardAfter(Player* player, Player* victim, uint32& killer_title, uint32& victim_rank, float& honor_f) +void ScriptMgr::OnPlayerVictimRewardAfter(Player* player, Player* victim, uint32& killer_title, uint32& victim_rank, float& honor_f) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_VICTIM_REWARD_AFTER, script->OnVictimRewardAfter(player, victim, killer_title, victim_rank, honor_f)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_VICTIM_REWARD_AFTER, script->OnPlayerVictimRewardAfter(player, victim, killer_title, victim_rank, honor_f)); } -void ScriptMgr::OnCustomScalingStatValueBefore(Player* player, ItemTemplate const* proto, uint8 slot, bool apply, uint32& CustomScalingStatValue) +void ScriptMgr::OnPlayerCustomScalingStatValueBefore(Player* player, ItemTemplate const* proto, uint8 slot, bool apply, uint32& CustomScalingStatValue) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CUSTOM_SCALING_STAT_VALUE_BEFORE, script->OnCustomScalingStatValueBefore(player, proto, slot, apply, CustomScalingStatValue)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CUSTOM_SCALING_STAT_VALUE_BEFORE, script->OnPlayerCustomScalingStatValueBefore(player, proto, slot, apply, CustomScalingStatValue)); } -void ScriptMgr::OnCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv) +void ScriptMgr::OnPlayerCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CUSTOM_SCALING_STAT_VALUE, script->OnCustomScalingStatValue(player, proto, statType, val, itemProtoStatNumber, ScalingStatValue, ssv)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CUSTOM_SCALING_STAT_VALUE, script->OnPlayerCustomScalingStatValue(player, proto, statType, val, itemProtoStatNumber, ScalingStatValue, ssv)); } -void ScriptMgr::OnApplyItemModsBefore(Player* player, uint8 slot, bool apply, uint8 itemProtoStatNumber, uint32 statType, int32& val) +void ScriptMgr::OnPlayerApplyItemModsBefore(Player* player, uint8 slot, bool apply, uint8 itemProtoStatNumber, uint32 statType, int32& val) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_ITEM_MODS_BEFORE, script->OnApplyItemModsBefore(player, slot, apply, itemProtoStatNumber, statType, val)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_ITEM_MODS_BEFORE, script->OnPlayerApplyItemModsBefore(player, slot, apply, itemProtoStatNumber, statType, val)); } -void ScriptMgr::OnApplyEnchantmentItemModsBefore(Player* player, Item* item, EnchantmentSlot slot, bool apply, uint32 enchant_spell_id, uint32& enchant_amount) +void ScriptMgr::OnPlayerApplyEnchantmentItemModsBefore(Player* player, Item* item, EnchantmentSlot slot, bool apply, uint32 enchant_spell_id, uint32& enchant_amount) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_ENCHANTMENT_ITEM_MODS_BEFORE, script->OnApplyEnchantmentItemModsBefore(player, item, slot, apply, enchant_spell_id, enchant_amount)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_ENCHANTMENT_ITEM_MODS_BEFORE, script->OnPlayerApplyEnchantmentItemModsBefore(player, item, slot, apply, enchant_spell_id, enchant_amount)); } -void ScriptMgr::OnApplyWeaponDamage(Player* player, uint8 slot, ItemTemplate const* proto, float& minDamage, float& maxDamage, uint8 damageIndex) +void ScriptMgr::OnPlayerApplyWeaponDamage(Player* player, uint8 slot, ItemTemplate const* proto, float& minDamage, float& maxDamage, uint8 damageIndex) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_WEAPON_DAMAGE, script->OnApplyWeaponDamage(player, slot, proto, minDamage, maxDamage, damageIndex)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_WEAPON_DAMAGE, script->OnPlayerApplyWeaponDamage(player, slot, proto, minDamage, maxDamage, damageIndex)); } -bool ScriptMgr::CanArmorDamageModifier(Player* player) +bool ScriptMgr::OnPlayerCanArmorDamageModifier(Player* player) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_ARMOR_DAMAGE_MODIFIER, !script->CanArmorDamageModifier(player)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_ARMOR_DAMAGE_MODIFIER, !script->OnPlayerCanArmorDamageModifier(player)); } -void ScriptMgr::OnGetFeralApBonus(Player* player, int32& feral_bonus, int32 dpsMod, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv) +void ScriptMgr::OnPlayerGetFeralApBonus(Player* player, int32& feral_bonus, int32 dpsMod, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_FERAL_AP_BONUS, script->OnGetFeralApBonus(player, feral_bonus, dpsMod, proto, ssv)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_FERAL_AP_BONUS, script->OnPlayerGetFeralApBonus(player, feral_bonus, dpsMod, proto, ssv)); } -bool ScriptMgr::CanApplyWeaponDependentAuraDamageMod(Player* player, Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply) +bool ScriptMgr::OnPlayerCanApplyWeaponDependentAuraDamageMod(Player* player, Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_APPLY_WEAPON_DEPENDENT_AURA_DAMAGE_MOD, !script->CanApplyWeaponDependentAuraDamageMod(player, item, attackType, aura, apply)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_APPLY_WEAPON_DEPENDENT_AURA_DAMAGE_MOD, !script->OnPlayerCanApplyWeaponDependentAuraDamageMod(player, item, attackType, aura, apply)); } -bool ScriptMgr::CanApplyEquipSpell(Player* player, SpellInfo const* spellInfo, Item* item, bool apply, bool form_change) +bool ScriptMgr::OnPlayerCanApplyEquipSpell(Player* player, SpellInfo const* spellInfo, Item* item, bool apply, bool form_change) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_APPLY_EQUIP_SPELL, !script->CanApplyEquipSpell(player, spellInfo, item, apply, form_change)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_APPLY_EQUIP_SPELL, !script->OnPlayerCanApplyEquipSpell(player, spellInfo, item, apply, form_change)); } -bool ScriptMgr::CanApplyEquipSpellsItemSet(Player* player, ItemSetEffect* eff) +bool ScriptMgr::OnPlayerCanApplyEquipSpellsItemSet(Player* player, ItemSetEffect* eff) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_APPLY_EQUIP_SPELLS_ITEM_SET, !script->CanApplyEquipSpellsItemSet(player, eff)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_APPLY_EQUIP_SPELLS_ITEM_SET, !script->OnPlayerCanApplyEquipSpellsItemSet(player, eff)); } -bool ScriptMgr::CanCastItemCombatSpell(Player* player, Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto) +bool ScriptMgr::OnPlayerCanCastItemCombatSpell(Player* player, Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_CAST_ITEM_COMBAT_SPELL, !script->CanCastItemCombatSpell(player, target, attType, procVictim, procEx, item, proto)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_CAST_ITEM_COMBAT_SPELL, !script->OnPlayerCanCastItemCombatSpell(player, target, attType, procVictim, procEx, item, proto)); } -bool ScriptMgr::CanCastItemUseSpell(Player* player, Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex) +bool ScriptMgr::OnPlayerCanCastItemUseSpell(Player* player, Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_CAST_ITEM_USE_SPELL, !script->CanCastItemUseSpell(player, item, targets, cast_count, glyphIndex)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_CAST_ITEM_USE_SPELL, !script->OnPlayerCanCastItemUseSpell(player, item, targets, cast_count, glyphIndex)); } -void ScriptMgr::OnApplyAmmoBonuses(Player* player, ItemTemplate const* proto, float& currentAmmoDPS) +void ScriptMgr::OnPlayerApplyAmmoBonuses(Player* player, ItemTemplate const* proto, float& currentAmmoDPS) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_AMMO_BONUSES, script->OnApplyAmmoBonuses(player, proto, currentAmmoDPS)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_APPLY_AMMO_BONUSES, script->OnPlayerApplyAmmoBonuses(player, proto, currentAmmoDPS)); } -bool ScriptMgr::CanEquipItem(Player* player, uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading) +bool ScriptMgr::OnPlayerCanEquipItem(Player* player, uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_EQUIP_ITEM, !script->CanEquipItem(player, slot, dest, pItem, swap, not_loading)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_EQUIP_ITEM, !script->OnPlayerCanEquipItem(player, slot, dest, pItem, swap, not_loading)); } -bool ScriptMgr::CanUnequipItem(Player* player, uint16 pos, bool swap) +bool ScriptMgr::OnPlayerCanUnequipItem(Player* player, uint16 pos, bool swap) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_UNEQUIP_ITEM, !script->CanUnequipItem(player, pos, swap)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_UNEQUIP_ITEM, !script->OnPlayerCanUnequipItem(player, pos, swap)); } -bool ScriptMgr::CanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result) +bool ScriptMgr::OnPlayerCanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_USE_ITEM, !script->CanUseItem(player, proto, result)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_USE_ITEM, !script->OnPlayerCanUseItem(player, proto, result)); } -bool ScriptMgr::CanSaveEquipNewItem(Player* player, Item* item, uint16 pos, bool update) +bool ScriptMgr::OnPlayerCanSaveEquipNewItem(Player* player, Item* item, uint16 pos, bool update) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SAVE_EQUIP_NEW_ITEM, !script->CanSaveEquipNewItem(player, item, pos, update)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SAVE_EQUIP_NEW_ITEM, !script->OnPlayerCanSaveEquipNewItem(player, item, pos, update)); } -bool ScriptMgr::CanApplyEnchantment(Player* player, Item* item, EnchantmentSlot slot, bool apply, bool apply_dur, bool ignore_condition) +bool ScriptMgr::OnPlayerCanApplyEnchantment(Player* player, Item* item, EnchantmentSlot slot, bool apply, bool apply_dur, bool ignore_condition) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_APPLY_ENCHANTMENT, !script->CanApplyEnchantment(player, item, slot, apply, apply_dur, ignore_condition)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_APPLY_ENCHANTMENT, !script->OnPlayerCanApplyEnchantment(player, item, slot, apply, apply_dur, ignore_condition)); } -void ScriptMgr::OnGetQuestRate(Player* player, float& result) +void ScriptMgr::OnPlayerGetQuestRate(Player* player, float& result) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_QUEST_RATE, script->OnGetQuestRate(player, result)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_QUEST_RATE, script->OnPlayerGetQuestRate(player, result)); } -bool ScriptMgr::PassedQuestKilledMonsterCredit(Player* player, Quest const* qinfo, uint32 entry, uint32 real_entry, ObjectGuid guid) +bool ScriptMgr::OnPlayerPassedQuestKilledMonsterCredit(Player* player, Quest const* qinfo, uint32 entry, uint32 real_entry, ObjectGuid guid) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_PASSED_QUEST_KILLED_MONSTER_CREDIT, !script->PassedQuestKilledMonsterCredit(player, qinfo, entry, real_entry, guid)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_PASSED_QUEST_KILLED_MONSTER_CREDIT, !script->OnPlayerPassedQuestKilledMonsterCredit(player, qinfo, entry, real_entry, guid)); } -bool ScriptMgr::CheckItemInSlotAtLoadInventory(Player* player, Item* item, uint8 slot, uint8& err, uint16& dest) +bool ScriptMgr::OnPlayerCheckItemInSlotAtLoadInventory(Player* player, Item* item, uint8 slot, uint8& err, uint16& dest) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CHECK_ITEM_IN_SLOT_AT_LOAD_INVENTORY, !script->CheckItemInSlotAtLoadInventory(player, item, slot, err, dest)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CHECK_ITEM_IN_SLOT_AT_LOAD_INVENTORY, !script->OnPlayerCheckItemInSlotAtLoadInventory(player, item, slot, err, dest)); } -bool ScriptMgr::NotAvoidSatisfy(Player* player, DungeonProgressionRequirements const* ar, uint32 target_map, bool report) +bool ScriptMgr::OnPlayerNotAvoidSatisfy(Player* player, DungeonProgressionRequirements const* ar, uint32 target_map, bool report) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_NOT_AVOID_SATISFY, !script->NotAvoidSatisfy(player, ar, target_map, report)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_NOT_AVOID_SATISFY, !script->OnPlayerNotAvoidSatisfy(player, ar, target_map, report)); } -bool ScriptMgr::NotVisibleGloballyFor(Player* player, Player const* u) +bool ScriptMgr::OnPlayerNotVisibleGloballyFor(Player* player, Player const* u) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_NOT_VISIBLE_GLOBALLY_FOR, !script->NotVisibleGloballyFor(player, u)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_NOT_VISIBLE_GLOBALLY_FOR, !script->OnPlayerNotVisibleGloballyFor(player, u)); } -void ScriptMgr::OnGetArenaPersonalRating(Player* player, uint8 slot, uint32& result) +void ScriptMgr::OnPlayerGetArenaPersonalRating(Player* player, uint8 slot, uint32& result) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_ARENA_PERSONAL_RATING, script->OnGetArenaPersonalRating(player, slot, result)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_ARENA_PERSONAL_RATING, script->OnPlayerGetArenaPersonalRating(player, slot, result)); } -void ScriptMgr::OnGetArenaTeamId(Player* player, uint8 slot, uint32& result) +void ScriptMgr::OnPlayerGetArenaTeamId(Player* player, uint8 slot, uint32& result) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_ARENA_TEAM_ID, script->OnGetArenaTeamId(player, slot, result)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_ARENA_TEAM_ID, script->OnPlayerGetArenaTeamId(player, slot, result)); } -void ScriptMgr::OnIsFFAPvP(Player* player, bool& result) +void ScriptMgr::OnPlayerIsFFAPvP(Player* player, bool& result) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_IS_FFA_PVP, script->OnIsFFAPvP(player, result)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_IS_FFA_PVP, script->OnPlayerIsFFAPvP(player, result)); } -void ScriptMgr::OnFfaPvpStateUpdate(Player* player, bool result) +void ScriptMgr::OnPlayerFfaPvpStateUpdate(Player* player, bool result) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FFA_PVP_STATE_UPDATE, script->OnFfaPvpStateUpdate(player, result)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_FFA_PVP_STATE_UPDATE, script->OnPlayerFfaPvpStateUpdate(player, result)); } -void ScriptMgr::OnIsPvP(Player* player, bool& result) +void ScriptMgr::OnPlayerIsPvP(Player* player, bool& result) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_IS_PVP, script->OnIsPvP(player, result)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_IS_PVP, script->OnPlayerIsPvP(player, result)); } -void ScriptMgr::OnGetMaxSkillValueForLevel(Player* player, uint16& result) +void ScriptMgr::OnPlayerGetMaxSkillValueForLevel(Player* player, uint16& result) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_MAX_SKILL_VALUE_FOR_LEVEL, script->OnGetMaxSkillValueForLevel(player, result)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_MAX_SKILL_VALUE_FOR_LEVEL, script->OnPlayerGetMaxSkillValueForLevel(player, result)); } -bool ScriptMgr::NotSetArenaTeamInfoField(Player* player, uint8 slot, ArenaTeamInfoType type, uint32 value) +bool ScriptMgr::OnPlayerNotSetArenaTeamInfoField(Player* player, uint8 slot, ArenaTeamInfoType type, uint32 value) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_NOT_SET_ARENA_TEAM_INFO_FIELD, !script->NotSetArenaTeamInfoField(player, slot, type, value)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_NOT_SET_ARENA_TEAM_INFO_FIELD, !script->OnPlayerNotSetArenaTeamInfoField(player, slot, type, value)); } -bool ScriptMgr::CanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment) +bool ScriptMgr::OnPlayerCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_JOIN_LFG, !script->CanJoinLfg(player, roles, dungeons, comment)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_JOIN_LFG, !script->OnPlayerCanJoinLfg(player, roles, dungeons, comment)); } -bool ScriptMgr::CanEnterMap(Player* player, MapEntry const* entry, InstanceTemplate const* instance, MapDifficulty const* mapDiff, bool loginCheck) +bool ScriptMgr::OnPlayerCanEnterMap(Player* player, MapEntry const* entry, InstanceTemplate const* instance, MapDifficulty const* mapDiff, bool loginCheck) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_ENTER_MAP, !script->CanEnterMap(player, entry, instance, mapDiff, loginCheck)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_ENTER_MAP, !script->OnPlayerCanEnterMap(player, entry, instance, mapDiff, loginCheck)); } -bool ScriptMgr::CanInitTrade(Player* player, Player* target) +bool ScriptMgr::OnPlayerCanInitTrade(Player* player, Player* target) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_INIT_TRADE, !script->CanInitTrade(player, target)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_INIT_TRADE, !script->OnPlayerCanInitTrade(player, target)); } -bool ScriptMgr::CanSetTradeItem(Player* player, Item* tradedItem, uint8 tradeSlot) +bool ScriptMgr::OnPlayerCanSetTradeItem(Player* player, Item* tradedItem, uint8 tradeSlot) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SET_TRADE_ITEM, !script->CanSetTradeItem(player, tradedItem, tradeSlot)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_SET_TRADE_ITEM, !script->OnPlayerCanSetTradeItem(player, tradedItem, tradeSlot)); } -void ScriptMgr::OnSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec) +void ScriptMgr::OnPlayerSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SET_SERVER_SIDE_VISIBILITY, script->OnSetServerSideVisibility(player, type, sec)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SET_SERVER_SIDE_VISIBILITY, script->OnPlayerSetServerSideVisibility(player, type, sec)); } -void ScriptMgr::OnSetServerSideVisibilityDetect(Player* player, ServerSideVisibilityType& type, AccountTypes& sec) +void ScriptMgr::OnPlayerSetServerSideVisibilityDetect(Player* player, ServerSideVisibilityType& type, AccountTypes& sec) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SET_SERVER_SIDE_VISIBILITY_DETECT, script->OnSetServerSideVisibilityDetect(player, type, sec)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_SET_SERVER_SIDE_VISIBILITY_DETECT, script->OnPlayerSetServerSideVisibilityDetect(player, type, sec)); } void ScriptMgr::OnPlayerResurrect(Player* player, float restore_percent, bool applySickness) @@ -809,34 +809,34 @@ void ScriptMgr::OnPlayerResurrect(Player* player, float restore_percent, bool ap CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PLAYER_RESURRECT, script->OnPlayerResurrect(player, restore_percent, applySickness)); } -void ScriptMgr::OnBeforeChooseGraveyard(Player* player, TeamId teamId, bool nearCorpse, uint32& graveyardOverride) +void ScriptMgr::OnPlayerBeforeChooseGraveyard(Player* player, TeamId teamId, bool nearCorpse, uint32& graveyardOverride) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_CHOOSE_GRAVEYARD, script->OnBeforeChooseGraveyard(player, teamId, nearCorpse, graveyardOverride)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_CHOOSE_GRAVEYARD, script->OnPlayerBeforeChooseGraveyard(player, teamId, nearCorpse, graveyardOverride)); } -bool ScriptMgr::CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg) +bool ScriptMgr::OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_CHAT, !script->CanPlayerUseChat(player, type, language, msg)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_CHAT, !script->OnPlayerCanUseChat(player, type, language, msg)); } -bool ScriptMgr::CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Player* receiver) +bool ScriptMgr::OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Player* receiver) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_PRIVATE_CHAT, !script->CanPlayerUseChat(player, type, language, msg, receiver)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_PRIVATE_CHAT, !script->OnPlayerCanUseChat(player, type, language, msg, receiver)); } -bool ScriptMgr::CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Group* group) +bool ScriptMgr::OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Group* group) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_GROUP_CHAT, !script->CanPlayerUseChat(player, type, language, msg, group)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_GROUP_CHAT, !script->OnPlayerCanUseChat(player, type, language, msg, group)); } -bool ScriptMgr::CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Guild* guild) +bool ScriptMgr::OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Guild* guild) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_GUILD_CHAT, !script->CanPlayerUseChat(player, type, language, msg, guild)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_GUILD_CHAT, !script->OnPlayerCanUseChat(player, type, language, msg, guild)); } -bool ScriptMgr::CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Channel* channel) +bool ScriptMgr::OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Channel* channel) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_CHANNEL_CHAT, !script->CanPlayerUseChat(player, type, language, msg, channel)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_PLAYER_USE_CHANNEL_CHAT, !script->OnPlayerCanUseChat(player, type, language, msg, channel)); } void ScriptMgr::OnPlayerLearnTalents(Player* player, uint32 talentId, uint32 talentRank, uint32 spellid) @@ -854,9 +854,9 @@ void ScriptMgr::OnPlayerLeaveCombat(Player* player) CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_PLAYER_LEAVE_COMBAT, script->OnPlayerLeaveCombat(player)); } -void ScriptMgr::OnQuestAbandon(Player* player, uint32 questId) +void ScriptMgr::OnPlayerQuestAbandon(Player* player, uint32 questId) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_QUEST_ABANDON, script->OnQuestAbandon(player, questId)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_QUEST_ABANDON, script->OnPlayerQuestAbandon(player, questId)); } // Player anti cheat @@ -895,14 +895,14 @@ 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::CanPlayerUpdateSkill(Player* player, uint32 skillId) +bool ScriptMgr::OnPlayerCanUpdateSkill(Player* player, uint32 skillId) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_CAN_UPDATE_SKILL, !script->CanPlayerUpdateSkill(player, skillId)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_CAN_UPDATE_SKILL, !script->OnPlayerCanUpdateSkill(player, skillId)); } -void ScriptMgr::OnBeforePlayerUpdateSkill(Player* player, uint32 skillId, uint32& value, uint32 max, uint32 step) +void ScriptMgr::OnPlayerBeforeUpdateSkill(Player* player, uint32 skillId, uint32& value, uint32 max, uint32 step) { - CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_UPDATE_SKILL, script->OnBeforePlayerUpdateSkill(player, skillId, value, max, step)); + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_UPDATE_SKILL, script->OnPlayerBeforeUpdateSkill(player, skillId, value, max, step)); } void ScriptMgr::OnPlayerUpdateSkill(Player* player, uint32 skillId, uint32 value, uint32 max, uint32 step, uint32 newValue) @@ -910,9 +910,9 @@ void ScriptMgr::OnPlayerUpdateSkill(Player* player, uint32 skillId, uint32 value CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_SKILL, script->OnPlayerUpdateSkill(player, skillId, value, max, step, newValue)); } -bool ScriptMgr::CanPlayerResurrect(Player* player) +bool ScriptMgr::OnPlayerCanResurrect(Player* player) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_RESURRECT, !script->CanPlayerResurrect(player)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_RESURRECT, !script->OnPlayerCanResurrect(player)); } PlayerScript::PlayerScript(const char* name, std::vector enabledHooks) diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.h b/src/server/game/Scripting/ScriptDefines/PlayerScript.h index 1fee803df..cf2242d5f 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.h +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.h @@ -221,188 +221,188 @@ public: virtual void OnPlayerJustDied(Player* /*player*/) { } // Called player talent points are calculated - virtual void OnCalculateTalentsPoints(Player const* /*player*/, uint32& /*talentPointsForLevel*/) { } + virtual void OnPlayerCalculateTalentsPoints(Player const* /*player*/, uint32& /*talentPointsForLevel*/) { } // Called when clicking the release button virtual void OnPlayerReleasedGhost(Player* /*player*/) { } // Called on Send Initial Packets Before Add To Map - virtual void OnSendInitialPacketsBeforeAddToMap(Player* /*player*/, WorldPacket& /*data*/) {} + virtual void OnPlayerSendInitialPacketsBeforeAddToMap(Player* /*player*/, WorldPacket& /*data*/) {} // Called when a player does a desertion action (see BattlegroundDesertionType) - virtual void OnBattlegroundDesertion(Player* /*player*/, BattlegroundDesertionType const /*desertionType*/) { } + virtual void OnPlayerBattlegroundDesertion(Player* /*player*/, BattlegroundDesertionType const /*desertionType*/) { } // Called when a player completes a quest virtual void OnPlayerCompleteQuest(Player* /*player*/, Quest const* /*quest_id*/) { } // Called when a player kills another player - virtual void OnPVPKill(Player* /*killer*/, Player* /*killed*/) { } + virtual void OnPlayerPVPKill(Player* /*killer*/, Player* /*killed*/) { } // Called when a player toggles pvp virtual void OnPlayerPVPFlagChange(Player* /*player*/, bool /*state*/) { } // Called when a player kills a creature - virtual void OnCreatureKill(Player* /*killer*/, Creature* /*killed*/) { } + virtual void OnPlayerCreatureKill(Player* /*killer*/, Creature* /*killed*/) { } // Called when a player's pet kills a creature - virtual void OnCreatureKilledByPet(Player* /*PetOwner*/, Creature* /*killed*/) { } + virtual void OnPlayerCreatureKilledByPet(Player* /*PetOwner*/, Creature* /*killed*/) { } // Called when a player is killed by a creature virtual void OnPlayerKilledByCreature(Creature* /*killer*/, Player* /*killed*/) { } // Called when a player's level changes (right after the level is applied) - virtual void OnLevelChanged(Player* /*player*/, uint8 /*oldlevel*/) { } + virtual void OnPlayerLevelChanged(Player* /*player*/, uint8 /*oldlevel*/) { } // Called when a player's free talent points change (right before the change is applied) - virtual void OnFreeTalentPointsChanged(Player* /*player*/, uint32 /*points*/) { } + virtual void OnPlayerFreeTalentPointsChanged(Player* /*player*/, uint32 /*points*/) { } // Called when a player's talent points are reset (right before the reset is done) - virtual void OnTalentsReset(Player* /*player*/, bool /*noCost*/) { } + virtual void OnPlayerTalentsReset(Player* /*player*/, bool /*noCost*/) { } // Called after a player switches specs using the dual spec system - virtual void OnAfterSpecSlotChanged(Player* /*player*/, uint8 /*newSlot*/) { } + virtual void OnPlayerAfterSpecSlotChanged(Player* /*player*/, uint8 /*newSlot*/) { } // Called for player::update - virtual void OnBeforeUpdate(Player* /*player*/, uint32 /*p_time*/) { } - virtual void OnUpdate(Player* /*player*/, uint32 /*p_time*/) { } + virtual void OnPlayerBeforeUpdate(Player* /*player*/, uint32 /*p_time*/) { } + virtual void OnPlayerUpdate(Player* /*player*/, uint32 /*p_time*/) { } // Called when a player's money is modified (before the modification is done) - virtual void OnMoneyChanged(Player* /*player*/, int32& /*amount*/) { } + virtual void OnPlayerMoneyChanged(Player* /*player*/, int32& /*amount*/) { } // Called before looted money is added to a player - virtual void OnBeforeLootMoney(Player* /*player*/, Loot* /*loot*/) {} + virtual void OnPlayerBeforeLootMoney(Player* /*player*/, Loot* /*loot*/) {} // Called when a player gains XP (before anything is given) - virtual void OnGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/, uint8 /*xpSource*/) { } + virtual void OnPlayerGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/, uint8 /*xpSource*/) { } // Called when a player's reputation changes (before it is actually changed) - virtual bool OnReputationChange(Player* /*player*/, uint32 /*factionID*/, int32& /*standing*/, bool /*incremental*/) { return true; } + virtual bool OnPlayerReputationChange(Player* /*player*/, uint32 /*factionID*/, int32& /*standing*/, bool /*incremental*/) { return true; } // Called when a player's reputation rank changes (before it is actually changed) - virtual void OnReputationRankChange(Player* /*player*/, uint32 /*factionID*/, ReputationRank /*newRank*/, ReputationRank /*olRank*/, bool /*increased*/) { } + virtual void OnPlayerReputationRankChange(Player* /*player*/, uint32 /*factionID*/, ReputationRank /*newRank*/, ReputationRank /*olRank*/, bool /*increased*/) { } // Called when a player learned new spell - virtual void OnLearnSpell(Player* /*player*/, uint32 /*spellID*/) {} + virtual void OnPlayerLearnSpell(Player* /*player*/, uint32 /*spellID*/) {} // Called when a player forgot spell - virtual void OnForgotSpell(Player* /*player*/, uint32 /*spellID*/) {} + virtual void OnPlayerForgotSpell(Player* /*player*/, uint32 /*spellID*/) {} // Called when a duel is requested - virtual void OnDuelRequest(Player* /*target*/, Player* /*challenger*/) { } + virtual void OnPlayerDuelRequest(Player* /*target*/, Player* /*challenger*/) { } // Called when a duel starts (after 3s countdown) - virtual void OnDuelStart(Player* /*player1*/, Player* /*player2*/) { } + virtual void OnPlayerDuelStart(Player* /*player1*/, Player* /*player2*/) { } // Called when a duel ends - virtual void OnDuelEnd(Player* /*winner*/, Player* /*loser*/, DuelCompleteType /*type*/) { } + virtual void OnPlayerDuelEnd(Player* /*winner*/, Player* /*loser*/, DuelCompleteType /*type*/) { } // The following methods are called when a player sends a chat message. - virtual void OnChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/) { } + virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/) { } - virtual void OnBeforeSendChatMessage(Player* /*player*/, uint32& /*type*/, uint32& /*lang*/, std::string& /*msg*/) { } + virtual void OnPlayerBeforeSendChatMessage(Player* /*player*/, uint32& /*type*/, uint32& /*lang*/, std::string& /*msg*/) { } - virtual void OnChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Player* /*receiver*/) { } + virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Player* /*receiver*/) { } - virtual void OnChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Group* /*group*/) { } + virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Group* /*group*/) { } - virtual void OnChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Guild* /*guild*/) { } + virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Guild* /*guild*/) { } - virtual void OnChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Channel* /*channel*/) { } + virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Channel* /*channel*/) { } // Both of the below are called on emote opcodes. - virtual void OnEmote(Player* /*player*/, uint32 /*emote*/) { } + virtual void OnPlayerEmote(Player* /*player*/, uint32 /*emote*/) { } - virtual void OnTextEmote(Player* /*player*/, uint32 /*textEmote*/, uint32 /*emoteNum*/, ObjectGuid /*guid*/) { } + virtual void OnPlayerTextEmote(Player* /*player*/, uint32 /*textEmote*/, uint32 /*emoteNum*/, ObjectGuid /*guid*/) { } // Called in Spell::Cast. - virtual void OnSpellCast(Player* /*player*/, Spell* /*spell*/, bool /*skipCheck*/) { } + virtual void OnPlayerSpellCast(Player* /*player*/, Spell* /*spell*/, bool /*skipCheck*/) { } // Called during data loading - virtual void OnLoadFromDB(Player* /*player*/) { }; + virtual void OnPlayerLoadFromDB(Player* /*player*/) { }; // Called when a player logs in. - virtual void OnLogin(Player* /*player*/) { } + virtual void OnPlayerLogin(Player* /*player*/) { } // Called before the player is logged out - virtual void OnBeforeLogout(Player* /*player*/) { } + virtual void OnPlayerBeforeLogout(Player* /*player*/) { } // Called when a player logs out. - virtual void OnLogout(Player* /*player*/) { } + virtual void OnPlayerLogout(Player* /*player*/) { } // Called when a player is created. - virtual void OnCreate(Player* /*player*/) { } + virtual void OnPlayerCreate(Player* /*player*/) { } // Called when a player is deleted. - virtual void OnDelete(ObjectGuid /*guid*/, uint32 /*accountId*/) { } + virtual void OnPlayerDelete(ObjectGuid /*guid*/, uint32 /*accountId*/) { } // Called when a player delete failed. - virtual void OnFailedDelete(ObjectGuid /*guid*/, uint32 /*accountId*/) { } + virtual void OnPlayerFailedDelete(ObjectGuid /*guid*/, uint32 /*accountId*/) { } // Called when a player is about to be saved. - virtual void OnSave(Player* /*player*/) { } + virtual void OnPlayerSave(Player* /*player*/) { } // Called when a player is bound to an instance - virtual void OnBindToInstance(Player* /*player*/, Difficulty /*difficulty*/, uint32 /*mapId*/, bool /*permanent*/) { } + virtual void OnPlayerBindToInstance(Player* /*player*/, Difficulty /*difficulty*/, uint32 /*mapId*/, bool /*permanent*/) { } // Called when a player switches to a new zone - virtual void OnUpdateZone(Player* /*player*/, uint32 /*newZone*/, uint32 /*newArea*/) { } + virtual void OnPlayerUpdateZone(Player* /*player*/, uint32 /*newZone*/, uint32 /*newArea*/) { } // Called when a player switches to a new area (more accurate than UpdateZone) - virtual void OnUpdateArea(Player* /*player*/, uint32 /*oldArea*/, uint32 /*newArea*/) { } + virtual void OnPlayerUpdateArea(Player* /*player*/, uint32 /*oldArea*/, uint32 /*newArea*/) { } // Called when a player changes to a new map (after moving to new map) - virtual void OnMapChanged(Player* /*player*/) { } + virtual void OnPlayerMapChanged(Player* /*player*/) { } // Called before a player is being teleported to new coords - [[nodiscard]] virtual bool OnBeforeTeleport(Player* /*player*/, uint32 /*mapid*/, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) { return true; } + [[nodiscard]] virtual bool OnPlayerBeforeTeleport(Player* /*player*/, uint32 /*mapid*/, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) { return true; } // Called when team/faction is set on player - virtual void OnUpdateFaction(Player* /*player*/) { } + virtual void OnPlayerUpdateFaction(Player* /*player*/) { } // Called when a player is added to battleground - virtual void OnAddToBattleground(Player* /*player*/, Battleground* /*bg*/) { } + virtual void OnPlayerAddToBattleground(Player* /*player*/, Battleground* /*bg*/) { } // Called when a player queues a Random Dungeon using the RDF (Random Dungeon Finder) - virtual void OnQueueRandomDungeon(Player* /*player*/, uint32 & /*rDungeonId*/) { } + virtual void OnPlayerQueueRandomDungeon(Player* /*player*/, uint32 & /*rDungeonId*/) { } // Called when a player is removed from battleground - virtual void OnRemoveFromBattleground(Player* /*player*/, Battleground* /*bg*/) { } + virtual void OnPlayerRemoveFromBattleground(Player* /*player*/, Battleground* /*bg*/) { } // Called when a player complete an achievement - virtual void OnAchiComplete(Player* /*player*/, AchievementEntry const* /*achievement*/) { } + virtual void OnPlayerAchievementComplete(Player* /*player*/, AchievementEntry const* /*achievement*/) { } // Called before player complete an achievement, can be used to disable achievements in certain conditions - virtual bool OnBeforeAchiComplete(Player* /*player*/, AchievementEntry const* /*achievement*/) { return true; } + virtual bool OnPlayerBeforeAchievementComplete(Player* /*player*/, AchievementEntry const* /*achievement*/) { return true; } // Called when a player complete an achievement criteria - virtual void OnCriteriaProgress(Player* /*player*/, AchievementCriteriaEntry const* /*criteria*/) { } + virtual void OnPlayerCriteriaProgress(Player* /*player*/, AchievementCriteriaEntry const* /*criteria*/) { } // Called before player complete an achievement criteria, can be used to disable achievement criteria in certain conditions - virtual bool OnBeforeCriteriaProgress(Player* /*player*/, AchievementCriteriaEntry const* /*criteria*/) { return true; } + virtual bool OnPlayerBeforeCriteriaProgress(Player* /*player*/, AchievementCriteriaEntry const* /*criteria*/) { return true; } // Called when an Achievement is saved to DB - virtual void OnAchiSave(CharacterDatabaseTransaction /*trans*/, Player* /*player*/, uint16 /*achId*/, CompletedAchievementData /*achiData*/) { } + virtual void OnPlayerAchievementSave(CharacterDatabaseTransaction /*trans*/, Player* /*player*/, uint16 /*achId*/, CompletedAchievementData /*achiData*/) { } // Called when an Criteria is saved to DB - virtual void OnCriteriaSave(CharacterDatabaseTransaction /*trans*/, Player* /*player*/, uint16 /*achId*/, CriteriaProgress /*criteriaData*/) { } + virtual void OnPlayerCriteriaSave(CharacterDatabaseTransaction /*trans*/, Player* /*player*/, uint16 /*achId*/, CriteriaProgress /*criteriaData*/) { } // Called when a player selects an option in a player gossip window - virtual void OnGossipSelect(Player* /*player*/, uint32 /*menu_id*/, uint32 /*sender*/, uint32 /*action*/) { } + virtual void OnPlayerGossipSelect(Player* /*player*/, uint32 /*menu_id*/, uint32 /*sender*/, uint32 /*action*/) { } // Called when a player selects an option in a player gossip window - virtual void OnGossipSelectCode(Player* /*player*/, uint32 /*menu_id*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { } + virtual void OnPlayerGossipSelectCode(Player* /*player*/, uint32 /*menu_id*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) { } // On player getting charmed - virtual void OnBeingCharmed(Player* /*player*/, Unit* /*charmer*/, uint32 /*oldFactionId*/, uint32 /*newFactionId*/) { } + virtual void OnPlayerBeingCharmed(Player* /*player*/, Unit* /*charmer*/, uint32 /*oldFactionId*/, uint32 /*newFactionId*/) { } // To change behaviour of set visible item slot - virtual void OnAfterSetVisibleItemSlot(Player* /*player*/, uint8 /*slot*/, Item* /*item*/) { } + virtual void OnPlayerAfterSetVisibleItemSlot(Player* /*player*/, uint8 /*slot*/, Item* /*item*/) { } // After an item has been moved from inventory - virtual void OnAfterMoveItemFromInventory(Player* /*player*/, Item* /*it*/, uint8 /*bag*/, uint8 /*slot*/, bool /*update*/) { } + virtual void OnPlayerAfterMoveItemFromInventory(Player* /*player*/, Item* /*it*/, uint8 /*bag*/, uint8 /*slot*/, bool /*update*/) { } // After an item has been equipped - virtual void OnEquip(Player* /*player*/, Item* /*it*/, uint8 /*bag*/, uint8 /*slot*/, bool /*update*/) { } + virtual void OnPlayerEquip(Player* /*player*/, Item* /*it*/, uint8 /*bag*/, uint8 /*slot*/, bool /*update*/) { } // After player enters queue for BG virtual void OnPlayerJoinBG(Player* /*player*/) { } @@ -411,105 +411,105 @@ public: virtual void OnPlayerJoinArena(Player* /*player*/) { } //Called after the normal slots (0..2) for arena have been evaluated so that custom arena teams could modify it if nececasry - virtual void OnGetMaxPersonalArenaRatingRequirement(Player const* /*player*/, uint32 /*minSlot*/, uint32& /*maxArenaRating*/) const {} + virtual void OnPlayerGetMaxPersonalArenaRatingRequirement(Player const* /*player*/, uint32 /*minSlot*/, uint32& /*maxArenaRating*/) const {} //After looting item - virtual void OnLootItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/, ObjectGuid /*lootguid*/) { } + virtual void OnPlayerLootItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/, ObjectGuid /*lootguid*/) { } //Before looting item - virtual void OnBeforeFillQuestLootItem(Player* /*player*/, LootItem& /*item*/) { } + virtual void OnPlayerBeforeFillQuestLootItem(Player* /*player*/, LootItem& /*item*/) { } //After looting item (includes master loot). - virtual void OnStoreNewItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { } + virtual void OnPlayerStoreNewItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { } //After creating item (eg profession item creation) - virtual void OnCreateItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { } + virtual void OnPlayerCreateItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { } // After receiving item as a quest reward - virtual void OnQuestRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { } + virtual void OnPlayerQuestRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/) { } // When placing a bid or buying out an auction - [[nodiscard]] virtual bool CanPlaceAuctionBid(Player* /*player*/, AuctionEntry* /*auction*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanPlaceAuctionBid(Player* /*player*/, AuctionEntry* /*auction*/) { return true; } // After receiving item as a group roll reward - virtual void OnGroupRollRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/, RollVote /*voteType*/, Roll* /*roll*/) { } + virtual void OnPlayerGroupRollRewardItem(Player* /*player*/, Item* /*item*/, uint32 /*count*/, RollVote /*voteType*/, Roll* /*roll*/) { } //Before opening an item - [[nodiscard]] virtual bool OnBeforeOpenItem(Player* /*player*/, Item* /*item*/) { return true; } + [[nodiscard]] virtual bool OnPlayerBeforeOpenItem(Player* /*player*/, Item* /*item*/) { return true; } // After completed a quest - [[nodiscard]] virtual bool OnBeforeQuestComplete(Player* /*player*/, uint32 /*quest_id*/) { return true; } + [[nodiscard]] virtual bool OnPlayerBeforeQuestComplete(Player* /*player*/, uint32 /*quest_id*/) { return true; } // Called after computing the XP reward value for a quest - virtual void OnQuestComputeXP(Player* /*player*/, Quest const* /*quest*/, uint32& /*xpValue*/) { } + virtual void OnPlayerQuestComputeXP(Player* /*player*/, Quest const* /*quest*/, uint32& /*xpValue*/) { } // Before durability repair action, you can even modify the discount value - virtual void OnBeforeDurabilityRepair(Player* /*player*/, ObjectGuid /*npcGUID*/, ObjectGuid /*itemGUID*/, float&/*discountMod*/, uint8 /*guildBank*/) { } + virtual void OnPlayerBeforeDurabilityRepair(Player* /*player*/, ObjectGuid /*npcGUID*/, ObjectGuid /*itemGUID*/, float&/*discountMod*/, uint8 /*guildBank*/) { } //Before buying something from any vendor - virtual void OnBeforeBuyItemFromVendor(Player* /*player*/, ObjectGuid /*vendorguid*/, uint32 /*vendorslot*/, uint32& /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/) { }; + virtual void OnPlayerBeforeBuyItemFromVendor(Player* /*player*/, ObjectGuid /*vendorguid*/, uint32 /*vendorslot*/, uint32& /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/) { }; //Before buying something from any vendor - virtual void OnBeforeStoreOrEquipNewItem(Player* /*player*/, uint32 /*vendorslot*/, uint32& /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/, ItemTemplate const* /*pProto*/, Creature* /*pVendor*/, VendorItem const* /*crItem*/, bool /*bStore*/) { }; + virtual void OnPlayerBeforeStoreOrEquipNewItem(Player* /*player*/, uint32 /*vendorslot*/, uint32& /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/, ItemTemplate const* /*pProto*/, Creature* /*pVendor*/, VendorItem const* /*crItem*/, bool /*bStore*/) { }; //After buying something from any vendor - virtual void OnAfterStoreOrEquipNewItem(Player* /*player*/, uint32 /*vendorslot*/, Item* /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/, ItemTemplate const* /*pProto*/, Creature* /*pVendor*/, VendorItem const* /*crItem*/, bool /*bStore*/) { }; + virtual void OnPlayerAfterStoreOrEquipNewItem(Player* /*player*/, uint32 /*vendorslot*/, Item* /*item*/, uint8 /*count*/, uint8 /*bag*/, uint8 /*slot*/, ItemTemplate const* /*pProto*/, Creature* /*pVendor*/, VendorItem const* /*crItem*/, bool /*bStore*/) { }; - virtual void OnAfterUpdateMaxPower(Player* /*player*/, Powers& /*power*/, float& /*value*/) { } + virtual void OnPlayerAfterUpdateMaxPower(Player* /*player*/, Powers& /*power*/, float& /*value*/) { } - virtual void OnAfterUpdateMaxHealth(Player* /*player*/, float& /*value*/) { } + virtual void OnPlayerAfterUpdateMaxHealth(Player* /*player*/, float& /*value*/) { } - virtual void OnBeforeUpdateAttackPowerAndDamage(Player* /*player*/, float& /*level*/, float& /*val2*/, bool /*ranged*/) { } - virtual void OnAfterUpdateAttackPowerAndDamage(Player* /*player*/, float& /*level*/, float& /*base_attPower*/, float& /*attPowerMod*/, float& /*attPowerMultiplier*/, bool /*ranged*/) { } + virtual void OnPlayerBeforeUpdateAttackPowerAndDamage(Player* /*player*/, float& /*level*/, float& /*val2*/, bool /*ranged*/) { } + virtual void OnPlayerAfterUpdateAttackPowerAndDamage(Player* /*player*/, float& /*level*/, float& /*base_attPower*/, float& /*attPowerMod*/, float& /*attPowerMultiplier*/, bool /*ranged*/) { } - virtual void OnBeforeInitTalentForLevel(Player* /*player*/, uint8& /*level*/, uint32& /*talentPointsForLevel*/) { } + virtual void OnPlayerBeforeInitTalentForLevel(Player* /*player*/, uint8& /*level*/, uint32& /*talentPointsForLevel*/) { } - virtual void OnFirstLogin(Player* /*player*/) { } + virtual void OnPlayerFirstLogin(Player* /*player*/) { } - virtual void OnSetMaxLevel(Player* /*player*/, uint32& /*maxPlayerLevel*/) { } + virtual void OnPlayerSetMaxLevel(Player* /*player*/, uint32& /*maxPlayerLevel*/) { } - [[nodiscard]] virtual bool CanJoinInBattlegroundQueue(Player* /*player*/, ObjectGuid /*BattlemasterGuid*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*joinAsGroup*/, GroupJoinBattlegroundResult& /*err*/) { return true; } - virtual bool ShouldBeRewardedWithMoneyInsteadOfExp(Player* /*player*/) { return false; } + [[nodiscard]] virtual bool OnPlayerCanJoinInBattlegroundQueue(Player* /*player*/, ObjectGuid /*BattlemasterGuid*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*joinAsGroup*/, GroupJoinBattlegroundResult& /*err*/) { return true; } + virtual bool OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(Player* /*player*/) { return false; } // Called before the player's temporary summoned creature has initialized it's stats - virtual void OnBeforeTempSummonInitStats(Player* /*player*/, TempSummon* /*tempSummon*/, uint32& /*duration*/) { } + virtual void OnPlayerBeforeTempSummonInitStats(Player* /*player*/, TempSummon* /*tempSummon*/, uint32& /*duration*/) { } // Called before the player's guardian / pet has initialized it's stats for the player's level - virtual void OnBeforeGuardianInitStatsForLevel(Player* /*player*/, Guardian* /*guardian*/, CreatureTemplate const* /*cinfo*/, PetType& /*petType*/) { } + virtual void OnPlayerBeforeGuardianInitStatsForLevel(Player* /*player*/, Guardian* /*guardian*/, CreatureTemplate const* /*cinfo*/, PetType& /*petType*/) { } // Called after the player's guardian / pet has initialized it's stats for the player's level - virtual void OnAfterGuardianInitStatsForLevel(Player* /*player*/, Guardian* /*guardian*/) { } + virtual void OnPlayerAfterGuardianInitStatsForLevel(Player* /*player*/, Guardian* /*guardian*/) { } // Called before loading a player's pet from the DB - virtual void OnBeforeLoadPetFromDB(Player* /*player*/, uint32& /*petentry*/, uint32& /*petnumber*/, bool& /*current*/, bool& /*forceLoadFromDB*/) { } + virtual void OnPlayerBeforeLoadPetFromDB(Player* /*player*/, uint32& /*petentry*/, uint32& /*petnumber*/, bool& /*current*/, bool& /*forceLoadFromDB*/) { } - [[nodiscard]] virtual bool CanJoinInArenaQueue(Player* /*player*/, ObjectGuid /*BattlemasterGuid*/, uint8 /*arenaslot*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*joinAsGroup*/, uint8 /*IsRated*/, GroupJoinBattlegroundResult& /*err*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanJoinInArenaQueue(Player* /*player*/, ObjectGuid /*BattlemasterGuid*/, uint8 /*arenaslot*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*joinAsGroup*/, uint8 /*IsRated*/, GroupJoinBattlegroundResult& /*err*/) { return true; } - [[nodiscard]] virtual bool CanBattleFieldPort(Player* /*player*/, uint8 /*arenaType*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*action*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanBattleFieldPort(Player* /*player*/, uint8 /*arenaType*/, BattlegroundTypeId /*BGTypeID*/, uint8 /*action*/) { return true; } - [[nodiscard]] virtual bool CanGroupInvite(Player* /*player*/, std::string& /*membername*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanGroupInvite(Player* /*player*/, std::string& /*membername*/) { return true; } - [[nodiscard]] virtual bool CanGroupAccept(Player* /*player*/, Group* /*group*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanGroupAccept(Player* /*player*/, Group* /*group*/) { return true; } - [[nodiscard]] virtual bool CanSellItem(Player* /*player*/, Item* /*item*/, Creature* /*creature*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanSellItem(Player* /*player*/, Item* /*item*/, Creature* /*creature*/) { return true; } - [[nodiscard]] virtual bool CanSendMail(Player* /*player*/, ObjectGuid /*receiverGuid*/, ObjectGuid /*mailbox*/, std::string& /*subject*/, std::string& /*body*/, uint32 /*money*/, uint32 /*COD*/, Item* /*item*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanSendMail(Player* /*player*/, ObjectGuid /*receiverGuid*/, ObjectGuid /*mailbox*/, std::string& /*subject*/, std::string& /*body*/, uint32 /*money*/, uint32 /*COD*/, Item* /*item*/) { return true; } - virtual void PetitionBuy(Player* /*player*/, Creature* /*creature*/, uint32& /*charterid*/, uint32& /*cost*/, uint32& /*type*/) { } + virtual void OnPlayerPetitionBuy(Player* /*player*/, Creature* /*creature*/, uint32& /*charterid*/, uint32& /*cost*/, uint32& /*type*/) { } - virtual void PetitionShowList(Player* /*player*/, Creature* /*creature*/, uint32& /*CharterEntry*/, uint32& /*CharterDispayID*/, uint32& /*CharterCost*/) { } + virtual void OnPlayerPetitionShowList(Player* /*player*/, Creature* /*creature*/, uint32& /*CharterEntry*/, uint32& /*CharterDispayID*/, uint32& /*CharterCost*/) { } - virtual void OnRewardKillRewarder(Player* /*player*/, KillRewarder* /*rewarder*/, bool /*isDungeon*/, float& /*rate*/) { } + virtual void OnPlayerRewardKillRewarder(Player* /*player*/, KillRewarder* /*rewarder*/, bool /*isDungeon*/, float& /*rate*/) { } - [[nodiscard]] virtual bool CanGiveMailRewardAtGiveLevel(Player* /*player*/, uint8 /*level*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanGiveMailRewardAtGiveLevel(Player* /*player*/, uint8 /*level*/) { return true; } - virtual void OnDeleteFromDB(CharacterDatabaseTransaction /*trans*/, uint32 /*guid*/) { } + virtual void OnPlayerDeleteFromDB(CharacterDatabaseTransaction /*trans*/, uint32 /*guid*/) { } - [[nodiscard]] virtual bool CanRepopAtGraveyard(Player* /*player*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanRepopAtGraveyard(Player* /*player*/) { return true; } [[nodiscard]] virtual Optional OnPlayerIsClass(Player const* /*player*/, Classes /*playerClass*/, ClassContext /*context*/) { return std::nullopt; } - virtual void OnGetMaxSkillValue(Player* /*player*/, uint32 /*skill*/, int32& /*result*/, bool /*IsPure*/) { } + virtual void OnPlayerGetMaxSkillValue(Player* /*player*/, uint32 /*skill*/, int32& /*result*/, bool /*IsPure*/) { } [[nodiscard]] virtual bool OnPlayerHasActivePowerType(Player const* /*player*/, Powers /*power*/) { return false; } @@ -524,7 +524,7 @@ public: * @param yellow Contains the yellow skill level for current application * @param gain Contains the amount of points that should be added to the Player */ - virtual void OnUpdateGatheringSkill(Player* /*player*/, uint32 /*skill_id*/, uint32 /*current*/, uint32 /*gray*/, uint32 /*green*/, uint32 /*yellow*/, uint32& /*gain*/) { } + virtual void OnPlayerUpdateGatheringSkill(Player* /*player*/, uint32 /*skill_id*/, uint32 /*current*/, uint32 /*gray*/, uint32 /*green*/, uint32 /*yellow*/, uint32& /*gain*/) { } /** * @brief This hook is called before crafting skill gain is applied to the character. @@ -534,82 +534,82 @@ public: * @param current_level Contains the current skill level for skill * @param gain Contains the amount of points that should be added to the Player */ - virtual void OnUpdateCraftingSkill(Player* /*player*/, SkillLineAbilityEntry const* /*skill*/, uint32 /*current_level*/, uint32& /*gain*/) { } + virtual void OnPlayerUpdateCraftingSkill(Player* /*player*/, SkillLineAbilityEntry const* /*skill*/, uint32 /*current_level*/, uint32& /*gain*/) { } - [[nodiscard]] virtual bool OnUpdateFishingSkill(Player* /*player*/, int32 /*skill*/, int32 /*zone_skill*/, int32 /*chance*/, int32 /*roll*/) { return true; } + [[nodiscard]] virtual bool OnPlayerUpdateFishingSkill(Player* /*player*/, int32 /*skill*/, int32 /*zone_skill*/, int32 /*chance*/, int32 /*roll*/) { return true; } - [[nodiscard]] virtual bool CanAreaExploreAndOutdoor(Player* /*player*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanAreaExploreAndOutdoor(Player* /*player*/) { return true; } - virtual void OnVictimRewardBefore(Player* /*player*/, Player* /*victim*/, uint32& /*killer_title*/, uint32& /*victim_title*/) { } + virtual void OnPlayerVictimRewardBefore(Player* /*player*/, Player* /*victim*/, uint32& /*killer_title*/, uint32& /*victim_title*/) { } - virtual void OnVictimRewardAfter(Player* /*player*/, Player* /*victim*/, uint32& /*killer_title*/, uint32& /*victim_rank*/, float& /*honor_f*/) { } + virtual void OnPlayerVictimRewardAfter(Player* /*player*/, Player* /*victim*/, uint32& /*killer_title*/, uint32& /*victim_rank*/, float& /*honor_f*/) { } - virtual void OnCustomScalingStatValueBefore(Player* /*player*/, ItemTemplate const* /*proto*/, uint8 /*slot*/, bool /*apply*/, uint32& /*CustomScalingStatValue*/) { } + virtual void OnPlayerCustomScalingStatValueBefore(Player* /*player*/, ItemTemplate const* /*proto*/, uint8 /*slot*/, bool /*apply*/, uint32& /*CustomScalingStatValue*/) { } - virtual void OnCustomScalingStatValue(Player* /*player*/, ItemTemplate const* /*proto*/, uint32& /*statType*/, int32& /*val*/, uint8 /*itemProtoStatNumber*/, uint32 /*ScalingStatValue*/, ScalingStatValuesEntry const* /*ssv*/) { } + virtual void OnPlayerCustomScalingStatValue(Player* /*player*/, ItemTemplate const* /*proto*/, uint32& /*statType*/, int32& /*val*/, uint8 /*itemProtoStatNumber*/, uint32 /*ScalingStatValue*/, ScalingStatValuesEntry const* /*ssv*/) { } - virtual void OnApplyItemModsBefore(Player* /*player*/, uint8 /*slot*/, bool /*apply*/, uint8 /*itemProtoStatNumber*/, uint32 /*statType*/, int32& /*val*/) { } + virtual void OnPlayerApplyItemModsBefore(Player* /*player*/, uint8 /*slot*/, bool /*apply*/, uint8 /*itemProtoStatNumber*/, uint32 /*statType*/, int32& /*val*/) { } - virtual void OnApplyEnchantmentItemModsBefore(Player* /*player*/, Item* /*item*/, EnchantmentSlot /*slot*/, bool /*apply*/, uint32 /*enchant_spell_id*/, uint32& /*enchant_amount*/) { } + virtual void OnPlayerApplyEnchantmentItemModsBefore(Player* /*player*/, Item* /*item*/, EnchantmentSlot /*slot*/, bool /*apply*/, uint32 /*enchant_spell_id*/, uint32& /*enchant_amount*/) { } - virtual void OnApplyWeaponDamage(Player* /*player*/, uint8 /*slot*/, ItemTemplate const* /*proto*/, float& /*minDamage*/, float& /*maxDamage*/, uint8 /*damageIndex*/) { } + virtual void OnPlayerApplyWeaponDamage(Player* /*player*/, uint8 /*slot*/, ItemTemplate const* /*proto*/, float& /*minDamage*/, float& /*maxDamage*/, uint8 /*damageIndex*/) { } - [[nodiscard]] virtual bool CanArmorDamageModifier(Player* /*player*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanArmorDamageModifier(Player* /*player*/) { return true; } - virtual void OnGetFeralApBonus(Player* /*player*/, int32& /*feral_bonus*/, int32 /*dpsMod*/, ItemTemplate const* /*proto*/, ScalingStatValuesEntry const* /*ssv*/) { } + virtual void OnPlayerGetFeralApBonus(Player* /*player*/, int32& /*feral_bonus*/, int32 /*dpsMod*/, ItemTemplate const* /*proto*/, ScalingStatValuesEntry const* /*ssv*/) { } - [[nodiscard]] virtual bool CanApplyWeaponDependentAuraDamageMod(Player* /*player*/, Item* /*item*/, WeaponAttackType /*attackType*/, AuraEffect const* /*aura*/, bool /*apply*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanApplyWeaponDependentAuraDamageMod(Player* /*player*/, Item* /*item*/, WeaponAttackType /*attackType*/, AuraEffect const* /*aura*/, bool /*apply*/) { return true; } - [[nodiscard]] virtual bool CanApplyEquipSpell(Player* /*player*/, SpellInfo const* /*spellInfo*/, Item* /*item*/, bool /*apply*/, bool /*form_change*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanApplyEquipSpell(Player* /*player*/, SpellInfo const* /*spellInfo*/, Item* /*item*/, bool /*apply*/, bool /*form_change*/) { return true; } - [[nodiscard]] virtual bool CanApplyEquipSpellsItemSet(Player* /*player*/, ItemSetEffect* /*eff*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanApplyEquipSpellsItemSet(Player* /*player*/, ItemSetEffect* /*eff*/) { return true; } - [[nodiscard]] virtual bool CanCastItemCombatSpell(Player* /*player*/, Unit* /*target*/, WeaponAttackType /*attType*/, uint32 /*procVictim*/, uint32 /*procEx*/, Item* /*item*/, ItemTemplate const* /*proto*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanCastItemCombatSpell(Player* /*player*/, Unit* /*target*/, WeaponAttackType /*attType*/, uint32 /*procVictim*/, uint32 /*procEx*/, Item* /*item*/, ItemTemplate const* /*proto*/) { return true; } - [[nodiscard]] virtual bool CanCastItemUseSpell(Player* /*player*/, Item* /*item*/, SpellCastTargets const& /*targets*/, uint8 /*cast_count*/, uint32 /*glyphIndex*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanCastItemUseSpell(Player* /*player*/, Item* /*item*/, SpellCastTargets const& /*targets*/, uint8 /*cast_count*/, uint32 /*glyphIndex*/) { return true; } - virtual void OnApplyAmmoBonuses(Player* /*player*/, ItemTemplate const* /*proto*/, float& /*currentAmmoDPS*/) { } + virtual void OnPlayerApplyAmmoBonuses(Player* /*player*/, ItemTemplate const* /*proto*/, float& /*currentAmmoDPS*/) { } - [[nodiscard]] virtual bool CanEquipItem(Player* /*player*/, uint8 /*slot*/, uint16& /*dest*/, Item* /*pItem*/, bool /*swap*/, bool /*not_loading*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanEquipItem(Player* /*player*/, uint8 /*slot*/, uint16& /*dest*/, Item* /*pItem*/, bool /*swap*/, bool /*not_loading*/) { return true; } - [[nodiscard]] virtual bool CanUnequipItem(Player* /*player*/, uint16 /*pos*/, bool /*swap*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanUnequipItem(Player* /*player*/, uint16 /*pos*/, bool /*swap*/) { return true; } - [[nodiscard]] virtual bool CanUseItem(Player* /*player*/, ItemTemplate const* /*proto*/, InventoryResult& /*result*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanUseItem(Player* /*player*/, ItemTemplate const* /*proto*/, InventoryResult& /*result*/) { return true; } - [[nodiscard]] virtual bool CanSaveEquipNewItem(Player* /*player*/, Item* /*item*/, uint16 /*pos*/, bool /*update*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanSaveEquipNewItem(Player* /*player*/, Item* /*item*/, uint16 /*pos*/, bool /*update*/) { return true; } - [[nodiscard]] virtual bool CanApplyEnchantment(Player* /*player*/, Item* /*item*/, EnchantmentSlot /*slot*/, bool /*apply*/, bool /*apply_dur*/, bool /*ignore_condition*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanApplyEnchantment(Player* /*player*/, Item* /*item*/, EnchantmentSlot /*slot*/, bool /*apply*/, bool /*apply_dur*/, bool /*ignore_condition*/) { return true; } - virtual void OnGetQuestRate(Player* /*player*/, float& /*result*/) { } + virtual void OnPlayerGetQuestRate(Player* /*player*/, float& /*result*/) { } - [[nodiscard]] virtual bool PassedQuestKilledMonsterCredit(Player* /*player*/, Quest const* /*qinfo*/, uint32 /*entry*/, uint32 /*real_entry*/, ObjectGuid /*guid*/) { return true; } + [[nodiscard]] virtual bool OnPlayerPassedQuestKilledMonsterCredit(Player* /*player*/, Quest const* /*qinfo*/, uint32 /*entry*/, uint32 /*real_entry*/, ObjectGuid /*guid*/) { return true; } - [[nodiscard]] virtual bool CheckItemInSlotAtLoadInventory(Player* /*player*/, Item* /*item*/, uint8 /*slot*/, uint8& /*err*/, uint16& /*dest*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCheckItemInSlotAtLoadInventory(Player* /*player*/, Item* /*item*/, uint8 /*slot*/, uint8& /*err*/, uint16& /*dest*/) { return true; } - [[nodiscard]] virtual bool NotAvoidSatisfy(Player* /*player*/, DungeonProgressionRequirements const* /*ar*/, uint32 /*target_map*/, bool /*report*/) { return true; } + [[nodiscard]] virtual bool OnPlayerNotAvoidSatisfy(Player* /*player*/, DungeonProgressionRequirements const* /*ar*/, uint32 /*target_map*/, bool /*report*/) { return true; } - [[nodiscard]] virtual bool NotVisibleGloballyFor(Player* /*player*/, Player const* /*u*/) { return true; } + [[nodiscard]] virtual bool OnPlayerNotVisibleGloballyFor(Player* /*player*/, Player const* /*u*/) { return true; } // Whats that? - virtual void OnGetArenaPersonalRating(Player* /*player*/, uint8 /*slot*/, uint32& /*result*/) { } + virtual void OnPlayerGetArenaPersonalRating(Player* /*player*/, uint8 /*slot*/, uint32& /*result*/) { } - virtual void OnGetArenaTeamId(Player* /*player*/, uint8 /*slot*/, uint32& /*result*/) { } + virtual void OnPlayerGetArenaTeamId(Player* /*player*/, uint8 /*slot*/, uint32& /*result*/) { } - virtual void OnIsFFAPvP(Player* /*player*/, bool& /*result*/) { } + virtual void OnPlayerIsFFAPvP(Player* /*player*/, bool& /*result*/) { } //Fires whenever the UNIT_BYTE2_FLAG_FFA_PVP bit is Changed on the player - virtual void OnFfaPvpStateUpdate(Player* /*player*/, bool /*result*/) { } + virtual void OnPlayerFfaPvpStateUpdate(Player* /*player*/, bool /*result*/) { } - virtual void OnIsPvP(Player* /*player*/, bool& /*result*/) { } + virtual void OnPlayerIsPvP(Player* /*player*/, bool& /*result*/) { } - virtual void OnGetMaxSkillValueForLevel(Player* /*player*/, uint16& /*result*/) { } + virtual void OnPlayerGetMaxSkillValueForLevel(Player* /*player*/, uint16& /*result*/) { } - [[nodiscard]] virtual bool NotSetArenaTeamInfoField(Player* /*player*/, uint8 /*slot*/, ArenaTeamInfoType /*type*/, uint32 /*value*/) { return true; } + [[nodiscard]] virtual bool OnPlayerNotSetArenaTeamInfoField(Player* /*player*/, uint8 /*slot*/, ArenaTeamInfoType /*type*/, uint32 /*value*/) { return true; } // Whats that? - [[nodiscard]] virtual bool CanJoinLfg(Player* /*player*/, uint8 /*roles*/, std::set& /*dungeons*/, const std::string& /*comment*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanJoinLfg(Player* /*player*/, uint8 /*roles*/, std::set& /*dungeons*/, const std::string& /*comment*/) { return true; } - [[nodiscard]] virtual bool CanEnterMap(Player* /*player*/, MapEntry const* /*entry*/, InstanceTemplate const* /*instance*/, MapDifficulty const* /*mapDiff*/, bool /*loginCheck*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanEnterMap(Player* /*player*/, MapEntry const* /*entry*/, InstanceTemplate const* /*instance*/, MapDifficulty const* /*mapDiff*/, bool /*loginCheck*/) { return true; } - [[nodiscard]] virtual bool CanInitTrade(Player* /*player*/, Player* /*target*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanInitTrade(Player* /*player*/, Player* /*target*/) { return true; } /** * @brief This hook called just before finishing the handling of the action of a player setting an item in a trade slot @@ -619,16 +619,16 @@ public: * * @return True if you want to continue setting the item in the trade slot, false if you want to cancel the trade */ - [[nodiscard]] virtual bool CanSetTradeItem(Player* /*player*/, Item* /*tradedItem*/, uint8 /*tradeSlot*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanSetTradeItem(Player* /*player*/, Item* /*tradedItem*/, uint8 /*tradeSlot*/) { return true; } - virtual void OnSetServerSideVisibility(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { } + virtual void OnPlayerSetServerSideVisibility(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { } - virtual void OnSetServerSideVisibilityDetect(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { } + virtual void OnPlayerSetServerSideVisibilityDetect(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { } virtual void OnPlayerResurrect(Player* /*player*/, float /*restore_percent*/, bool /*applySickness*/) { } // Called before selecting the graveyard when releasing spirit - virtual void OnBeforeChooseGraveyard(Player* /*player*/, TeamId /*teamId*/, bool /*nearCorpse*/, uint32& /*graveyardOverride*/) { } + virtual void OnPlayerBeforeChooseGraveyard(Player* /*player*/, TeamId /*teamId*/, bool /*nearCorpse*/, uint32& /*graveyardOverride*/) { } /** * @brief This hook called before player sending message in default chat @@ -640,7 +640,7 @@ public: * * @return True if you want to continue sending the message, false if you want to disable sending the message */ - [[nodiscard]] virtual bool CanPlayerUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/) { return true; } /** * @brief This hook called before player sending message to other player via private @@ -653,7 +653,7 @@ public: * * @return True if you want to continue sending the message, false if you want to disable sending the message */ - [[nodiscard]] virtual bool CanPlayerUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/, Player* /*receiver*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/, Player* /*receiver*/) { return true; } /** * @brief This hook called before player sending message to group @@ -666,7 +666,7 @@ public: * * @return True if you want to continue sending the message, false if you want to disable sending the message */ - [[nodiscard]] virtual bool CanPlayerUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/, Group* /*group*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/, Group* /*group*/) { return true; } /** * @brief This hook called before player sending message to guild @@ -679,7 +679,7 @@ public: * * @return True if you want to continue sending the message, false if you want to disable sending the message */ - [[nodiscard]] virtual bool CanPlayerUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/, Guild* /*guild*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/, Guild* /*guild*/) { return true; } /** * @brief This hook called before player sending message to channel @@ -692,7 +692,7 @@ public: * * @return True if you want to continue sending the message, false if you want to disable sending the message */ - [[nodiscard]] virtual bool CanPlayerUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/, Channel* /*channel*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanUseChat(Player* /*player*/, uint32 /*type*/, uint32 /*language*/, std::string& /*msg*/, Channel* /*channel*/) { return true; } /** * @brief This hook called after player learning talents @@ -725,7 +725,7 @@ public: * @param player Contains information about the Player * @param questId Contains information about the quest id */ - virtual void OnQuestAbandon(Player* /*player*/, uint32 /*questId*/) { } + virtual void OnPlayerQuestAbandon(Player* /*player*/, uint32 /*questId*/) { } /** * @brief This hook called before other CanFlyChecks are applied @@ -735,7 +735,7 @@ public: * @param zoneId Contains information about the current zone * @param bySpell Contains information about the spell that invoked the check */ - [[nodiscard]] virtual bool OnCanPlayerFlyInZone(Player* /*player*/, uint32 /*mapId*/, uint32 /*zoneId*/, SpellInfo const* /*bySpell*/) { return true; } + [[nodiscard]] virtual bool OnPlayerCanFlyInZone(Player* /*player*/, uint32 /*mapId*/, uint32 /*zoneId*/, SpellInfo const* /*bySpell*/) { return true; } // Passive Anticheat System virtual void AnticheatSetCanFlybyServer(Player* /*player*/, bool /*apply*/) { } @@ -753,7 +753,7 @@ public: * * @return true Avoiding displaying the error message that the loot has already been taken. */ - virtual bool CanSendErrorAlreadyLooted(Player* /*player*/) { return true; } + virtual bool OnPlayerCanSendErrorAlreadyLooted(Player* /*player*/) { return true; } /** * @brief It is used when an item is taken from a creature. @@ -761,17 +761,17 @@ public: * @param player Contains information about the Player * */ - virtual void OnAfterCreatureLoot(Player* /*player*/) { } + virtual void OnPlayerAfterCreatureLoot(Player* /*player*/) { } /** * @brief After a creature's money is taken * * @param player Contains information about the Player */ - virtual void OnAfterCreatureLootMoney(Player* /*player*/) { } + virtual void OnPlayerAfterCreatureLootMoney(Player* /*player*/) { } - virtual bool CanPlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/) { return true; } - virtual void OnBeforePlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/, uint32& /*value*/, uint32 /*max*/, uint32 /*step*/) { } + virtual bool OnPlayerCanUpdateSkill(Player* /*player*/, uint32 /*skillId*/) { return true; } + virtual void OnPlayerBeforeUpdateSkill(Player* /*player*/, uint32 /*skillId*/, uint32& /*value*/, uint32 /*max*/, uint32 /*step*/) { } virtual void OnPlayerUpdateSkill(Player* /*player*/, uint32 /*skillId*/, uint32 /*value*/, uint32 /*max*/, uint32 /*step*/, uint32 /*newValue*/) { } /** @@ -781,7 +781,7 @@ public: * * @return true if player is authorized to resurect */ - virtual bool CanPlayerResurrect(Player* /*player*/) { return true; } + virtual bool OnPlayerCanResurrect(Player* /*player*/) { return true; } }; #endif diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index b05d146f0..a0db4d2ea 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -293,24 +293,24 @@ public: /* AchievementCriteriaScript */ bool OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target, uint32 criteria_id); public: /* PlayerScript */ - void OnBeforePlayerUpdate(Player* player, uint32 p_time); - void OnPlayerUpdate(Player* player, uint32 p_time); - void OnSendInitialPacketsBeforeAddToMap(Player* player, WorldPacket& data); void OnPlayerJustDied(Player* player); - void OnCalculateTalentsPoints(Player const* player, uint32& talentPointsForLevel); + void OnPlayerCalculateTalentsPoints(Player const* player, uint32& talentPointsForLevel); void OnPlayerReleasedGhost(Player* player); - void OnPVPKill(Player* killer, Player* killed); + void OnPlayerSendInitialPacketsBeforeAddToMap(Player* player, WorldPacket& data); + void OnPlayerBeforeUpdate(Player* player, uint32 p_time); + void OnPlayerUpdate(Player* player, uint32 p_time); + void OnPlayerPVPKill(Player* killer, Player* killed); void OnPlayerPVPFlagChange(Player* player, bool state); - void OnCreatureKill(Player* killer, Creature* killed); - void OnCreatureKilledByPet(Player* petOwner, Creature* killed); + void OnPlayerCreatureKill(Player* killer, Creature* killed); + void OnPlayerCreatureKilledByPet(Player* petOwner, Creature* killed); void OnPlayerKilledByCreature(Creature* killer, Player* killed); void OnPlayerLevelChanged(Player* player, uint8 oldLevel); void OnPlayerFreeTalentPointsChanged(Player* player, uint32 newPoints); void OnPlayerTalentsReset(Player* player, bool noCost); - void OnAfterSpecSlotChanged(Player* player, uint8 newSlot); + void OnPlayerAfterSpecSlotChanged(Player* player, uint8 newSlot); void OnPlayerMoneyChanged(Player* player, int32& amount); - void OnBeforeLootMoney(Player* player, Loot* loot); - void OnGivePlayerXP(Player* player, uint32& amount, Unit* victim, uint8 xpSource); + void OnPlayerBeforeLootMoney(Player* player, Loot* loot); + void OnPlayerGiveXP(Player* player, uint32& amount, Unit* victim, uint8 xpSource); bool OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental); void OnPlayerReputationRankChange(Player* player, uint32 factionID, ReputationRank newRank, ReputationRank oldRank, bool increased); void OnPlayerLearnSpell(Player* player, uint32 spellID); @@ -319,7 +319,7 @@ public: /* PlayerScript */ void OnPlayerDuelStart(Player* player1, Player* player2); void OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type); void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg); - void OnBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& msg); + void OnPlayerBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& msg); void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Player* receiver); void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group); void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild); @@ -329,7 +329,7 @@ public: /* PlayerScript */ void OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck); void OnPlayerLogin(Player* player); void OnPlayerLoadFromDB(Player* player); - void OnBeforePlayerLogout(Player* player); + void OnPlayerBeforeLogout(Player* player); void OnPlayerLogout(Player* player); void OnPlayerCreate(Player* player); void OnPlayerSave(Player* player); @@ -338,131 +338,131 @@ public: /* PlayerScript */ void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent); void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea); void OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea); - bool OnBeforePlayerTeleport(Player* player, uint32 mapid, float x, float y, float z, float orientation, uint32 options, Unit* target); + bool OnPlayerBeforeTeleport(Player* player, uint32 mapid, float x, float y, float z, float orientation, uint32 options, Unit* target); void OnPlayerUpdateFaction(Player* player); void OnPlayerAddToBattleground(Player* player, Battleground* bg); void OnPlayerQueueRandomDungeon(Player* player, uint32 & rDungeonId); void OnPlayerRemoveFromBattleground(Player* player, Battleground* bg); - void OnAchievementComplete(Player* player, AchievementEntry const* achievement); - bool OnBeforeAchievementComplete(Player* player, AchievementEntry const* achievement); - void OnCriteriaProgress(Player* player, AchievementCriteriaEntry const* criteria); - bool OnBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* criteria); - void OnAchievementSave(CharacterDatabaseTransaction trans, Player* player, uint16 achiId, CompletedAchievementData achiData); - void OnCriteriaSave(CharacterDatabaseTransaction trans, Player* player, uint16 critId, CriteriaProgress criteriaData); - void OnGossipSelect(Player* player, uint32 menu_id, uint32 sender, uint32 action); - void OnGossipSelectCode(Player* player, uint32 menu_id, uint32 sender, uint32 action, const char* code); + void OnPlayerAchievementComplete(Player* player, AchievementEntry const* achievement); + bool OnPlayerBeforeAchievementComplete(Player* player, AchievementEntry const* achievement); + void OnPlayerCriteriaProgress(Player* player, AchievementCriteriaEntry const* criteria); + bool OnPlayerBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* criteria); + void OnPlayerAchievementSave(CharacterDatabaseTransaction trans, Player* player, uint16 achiId, CompletedAchievementData achiData); + void OnPlayerCriteriaSave(CharacterDatabaseTransaction trans, Player* player, uint16 critId, CriteriaProgress criteriaData); + void OnPlayerGossipSelect(Player* player, uint32 menu_id, uint32 sender, uint32 action); + void OnPlayerGossipSelectCode(Player* player, uint32 menu_id, uint32 sender, uint32 action, const char* code); void OnPlayerBeingCharmed(Player* player, Unit* charmer, uint32 oldFactionId, uint32 newFactionId); - void OnAfterPlayerSetVisibleItemSlot(Player* player, uint8 slot, Item* item); - void OnAfterPlayerMoveItemFromInventory(Player* player, Item* it, uint8 bag, uint8 slot, bool update); - void OnEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool update); + void OnPlayerAfterSetVisibleItemSlot(Player* player, uint8 slot, Item* item); + void OnPlayerAfterMoveItemFromInventory(Player* player, Item* it, uint8 bag, uint8 slot, bool update); + void OnPlayerEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool update); void OnPlayerJoinBG(Player* player); void OnPlayerJoinArena(Player* player); - void OnGetMaxPersonalArenaRatingRequirement(Player const* player, uint32 minSlot, uint32& maxArenaRating) const; - void OnLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid); - void OnBeforeFillQuestLootItem(Player* player, LootItem& item); - void OnStoreNewItem(Player* player, Item* item, uint32 count); - void OnCreateItem(Player* player, Item* item, uint32 count); - void OnQuestRewardItem(Player* player, Item* item, uint32 count); - bool CanPlaceAuctionBid(Player* player, AuctionEntry* auction); - void OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll); - bool OnBeforeOpenItem(Player* player, Item* item); - bool OnBeforePlayerQuestComplete(Player* player, uint32 quest_id); - void OnQuestComputeXP(Player* player, Quest const* quest, uint32& xpValue); - void OnBeforePlayerDurabilityRepair(Player* player, ObjectGuid npcGUID, ObjectGuid itemGUID, float& discountMod, uint8 guildBank); - void OnBeforeBuyItemFromVendor(Player* player, ObjectGuid vendorguid, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot); - void OnBeforeStoreOrEquipNewItem(Player* player, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore); - void OnAfterStoreOrEquipNewItem(Player* player, uint32 vendorslot, Item* item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore); - void OnAfterUpdateMaxPower(Player* player, Powers& power, float& value); - void OnAfterUpdateMaxHealth(Player* player, float& value); - void OnBeforeUpdateAttackPowerAndDamage(Player* player, float& level, float& val2, bool ranged); - void OnAfterUpdateAttackPowerAndDamage(Player* player, float& level, float& base_attPower, float& attPowerMod, float& attPowerMultiplier, bool ranged); - void OnBeforeInitTalentForLevel(Player* player, uint8& level, uint32& talentPointsForLevel); - void OnFirstLogin(Player* player); - void OnSetMaxLevel(Player* player, uint32& maxPlayerLevel); + void OnPlayerGetMaxPersonalArenaRatingRequirement(Player const* player, uint32 minSlot, uint32& maxArenaRating) const; + void OnPlayerLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid); + void OnPlayerBeforeFillQuestLootItem(Player* player, LootItem& item); + void OnPlayerStoreNewItem(Player* player, Item* item, uint32 count); + void OnPlayerCreateItem(Player* player, Item* item, uint32 count); + void OnPlayerQuestRewardItem(Player* player, Item* item, uint32 count); + bool OnPlayerCanPlaceAuctionBid(Player* player, AuctionEntry* auction); + void OnPlayerGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll); + bool OnPlayerBeforeOpenItem(Player* player, Item* item); + bool OnPlayerBeforeQuestComplete(Player* player, uint32 quest_id); + void OnPlayerQuestComputeXP(Player* player, Quest const* quest, uint32& xpValue); + void OnPlayerBeforeDurabilityRepair(Player* player, ObjectGuid npcGUID, ObjectGuid itemGUID, float& discountMod, uint8 guildBank); + void OnPlayerBeforeBuyItemFromVendor(Player* player, ObjectGuid vendorguid, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot); + void OnPlayerBeforeStoreOrEquipNewItem(Player* player, uint32 vendorslot, uint32& item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore); + void OnPlayerAfterStoreOrEquipNewItem(Player* player, uint32 vendorslot, Item* item, uint8 count, uint8 bag, uint8 slot, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore); + void OnPlayerAfterUpdateMaxPower(Player* player, Powers& power, float& value); + void OnPlayerAfterUpdateMaxHealth(Player* player, float& value); + void OnPlayerBeforeUpdateAttackPowerAndDamage(Player* player, float& level, float& val2, bool ranged); + void OnPlayerAfterUpdateAttackPowerAndDamage(Player* player, float& level, float& base_attPower, float& attPowerMod, float& attPowerMultiplier, bool ranged); + void OnPlayerBeforeInitTalentForLevel(Player* player, uint8& level, uint32& talentPointsForLevel); + void OnPlayerFirstLogin(Player* player); + void OnPlayerSetMaxLevel(Player* player, uint32& maxPlayerLevel); void OnPlayerCompleteQuest(Player* player, Quest const* quest); - void OnBattlegroundDesertion(Player* player, BattlegroundDesertionType const desertionType); - bool CanJoinInBattlegroundQueue(Player* player, ObjectGuid BattlemasterGuid, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, GroupJoinBattlegroundResult& err); - bool ShouldBeRewardedWithMoneyInsteadOfExp(Player* player); - void OnBeforeTempSummonInitStats(Player* player, TempSummon* tempSummon, uint32& duration); - void OnBeforeGuardianInitStatsForLevel(Player* player, Guardian* guardian, CreatureTemplate const* cinfo, PetType& petType); - void OnAfterGuardianInitStatsForLevel(Player* player, Guardian* guardian); - void OnBeforeLoadPetFromDB(Player* player, uint32& petentry, uint32& petnumber, bool& current, bool& forceLoadFromDB); - bool CanJoinInArenaQueue(Player* player, ObjectGuid BattlemasterGuid, uint8 arenaslot, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, uint8 IsRated, GroupJoinBattlegroundResult& err); - bool CanBattleFieldPort(Player* player, uint8 arenaType, BattlegroundTypeId BGTypeID, uint8 action); - bool CanGroupInvite(Player* player, std::string& membername); - bool CanGroupAccept(Player* player, Group* group); - bool CanSellItem(Player* player, Item* item, Creature* creature); - bool CanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item); - void PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type); - void PetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost); - void OnRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate); - bool CanGiveMailRewardAtGiveLevel(Player* player, uint8 level); - void OnDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid); - bool CanRepopAtGraveyard(Player* player); + void OnPlayerBattlegroundDesertion(Player* player, BattlegroundDesertionType const desertionType); + bool OnPlayerCanJoinInBattlegroundQueue(Player* player, ObjectGuid BattlemasterGuid, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, GroupJoinBattlegroundResult& err); + bool OnPlayerShouldBeRewardedWithMoneyInsteadOfExp(Player* player); + void OnPlayerBeforeTempSummonInitStats(Player* player, TempSummon* tempSummon, uint32& duration); + void OnPlayerBeforeGuardianInitStatsForLevel(Player* player, Guardian* guardian, CreatureTemplate const* cinfo, PetType& petType); + void OnPlayerAfterGuardianInitStatsForLevel(Player* player, Guardian* guardian); + void OnPlayerBeforeLoadPetFromDB(Player* player, uint32& petentry, uint32& petnumber, bool& current, bool& forceLoadFromDB); + bool OnPlayerCanJoinInArenaQueue(Player* player, ObjectGuid BattlemasterGuid, uint8 arenaslot, BattlegroundTypeId BGTypeID, uint8 joinAsGroup, uint8 IsRated, GroupJoinBattlegroundResult& err); + bool OnPlayerCanBattleFieldPort(Player* player, uint8 arenaType, BattlegroundTypeId BGTypeID, uint8 action); + bool OnPlayerCanGroupInvite(Player* player, std::string& membername); + bool OnPlayerCanGroupAccept(Player* player, Group* group); + bool OnPlayerCanSellItem(Player* player, Item* item, Creature* creature); + bool OnPlayerCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item); + void OnPlayerPetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type); + void OnPlayerPetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost); + void OnPlayerRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate); + bool OnPlayerCanGiveMailRewardAtGiveLevel(Player* player, uint8 level); + void OnPlayerDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid); + bool OnPlayerCanRepopAtGraveyard(Player* player); std::optional OnPlayerIsClass(Player const* player, Classes playerClass, ClassContext context); - void OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure); + void OnPlayerGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure); bool OnPlayerHasActivePowerType(Player const* player, Powers power); - void OnUpdateGatheringSkill(Player* player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32& gain); - void OnUpdateCraftingSkill(Player* player, SkillLineAbilityEntry const* skill, uint32 currentLevel, uint32& gain); - bool OnUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll); - bool CanAreaExploreAndOutdoor(Player* player); - void OnVictimRewardBefore(Player* player, Player* victim, uint32& killer_title, uint32& victim_title); - void OnVictimRewardAfter(Player* player, Player* victim, uint32& killer_title, uint32& victim_rank, float& honor_f); - void OnCustomScalingStatValueBefore(Player* player, ItemTemplate const* proto, uint8 slot, bool apply, uint32& CustomScalingStatValue); - void OnCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv); - void OnApplyItemModsBefore(Player* player, uint8 slot, bool apply, uint8 itemProtoStatNumber, uint32 statType, int32& val); - void OnApplyEnchantmentItemModsBefore(Player* player, Item* item, EnchantmentSlot slot, bool apply, uint32 enchant_spell_id, uint32& enchant_amount); - void OnApplyWeaponDamage(Player* player, uint8 slot, ItemTemplate const* proto, float& minDamage, float& maxDamage, uint8 damageIndex); - bool CanArmorDamageModifier(Player* player); - void OnGetFeralApBonus(Player* player, int32& feral_bonus, int32 dpsMod, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv); - bool CanApplyWeaponDependentAuraDamageMod(Player* player, Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply); - bool CanApplyEquipSpell(Player* player, SpellInfo const* spellInfo, Item* item, bool apply, bool form_change); - bool CanApplyEquipSpellsItemSet(Player* player, ItemSetEffect* eff); - bool CanCastItemCombatSpell(Player* player, Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto); - bool CanCastItemUseSpell(Player* player, Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex); - void OnApplyAmmoBonuses(Player* player, ItemTemplate const* proto, float& currentAmmoDPS); - bool CanEquipItem(Player* player, uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading); - bool CanUnequipItem(Player* player, uint16 pos, bool swap); - bool CanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result); - bool CanSaveEquipNewItem(Player* player, Item* item, uint16 pos, bool update); - bool CanApplyEnchantment(Player* player, Item* item, EnchantmentSlot slot, bool apply, bool apply_dur, bool ignore_condition); - void OnGetQuestRate(Player* player, float& result); - bool PassedQuestKilledMonsterCredit(Player* player, Quest const* qinfo, uint32 entry, uint32 real_entry, ObjectGuid guid); - bool CheckItemInSlotAtLoadInventory(Player* player, Item* item, uint8 slot, uint8& err, uint16& dest); - bool NotAvoidSatisfy(Player* player, DungeonProgressionRequirements const* ar, uint32 target_map, bool report); - bool NotVisibleGloballyFor(Player* player, Player const* u); - void OnGetArenaPersonalRating(Player* player, uint8 slot, uint32& result); - void OnFfaPvpStateUpdate(Player* player, bool result); - void OnGetArenaTeamId(Player* player, uint8 slot, uint32& result); - void OnIsFFAPvP(Player* player, bool& result); - void OnIsPvP(Player* player, bool& result); - void OnGetMaxSkillValueForLevel(Player* player, uint16& result); - bool NotSetArenaTeamInfoField(Player* player, uint8 slot, ArenaTeamInfoType type, uint32 value); - bool CanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment); - bool CanEnterMap(Player* player, MapEntry const* entry, InstanceTemplate const* instance, MapDifficulty const* mapDiff, bool loginCheck); - bool CanInitTrade(Player* player, Player* target); - bool CanSetTradeItem(Player* player, Item* tradedItem, uint8 tradeSlot); - void OnSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec); - void OnSetServerSideVisibilityDetect(Player* player, ServerSideVisibilityType& type, AccountTypes& sec); + void OnPlayerUpdateGatheringSkill(Player* player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32& gain); + void OnPlayerUpdateCraftingSkill(Player* player, SkillLineAbilityEntry const* skill, uint32 currentLevel, uint32& gain); + bool OnPlayerUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll); + bool OnPlayerCanAreaExploreAndOutdoor(Player* player); + void OnPlayerVictimRewardBefore(Player* player, Player* victim, uint32& killer_title, uint32& victim_title); + void OnPlayerVictimRewardAfter(Player* player, Player* victim, uint32& killer_title, uint32& victim_rank, float& honor_f); + void OnPlayerCustomScalingStatValueBefore(Player* player, ItemTemplate const* proto, uint8 slot, bool apply, uint32& CustomScalingStatValue); + void OnPlayerCustomScalingStatValue(Player* player, ItemTemplate const* proto, uint32& statType, int32& val, uint8 itemProtoStatNumber, uint32 ScalingStatValue, ScalingStatValuesEntry const* ssv); + void OnPlayerApplyItemModsBefore(Player* player, uint8 slot, bool apply, uint8 itemProtoStatNumber, uint32 statType, int32& val); + void OnPlayerApplyEnchantmentItemModsBefore(Player* player, Item* item, EnchantmentSlot slot, bool apply, uint32 enchant_spell_id, uint32& enchant_amount); + void OnPlayerApplyWeaponDamage(Player* player, uint8 slot, ItemTemplate const* proto, float& minDamage, float& maxDamage, uint8 damageIndex); + bool OnPlayerCanArmorDamageModifier(Player* player); + void OnPlayerGetFeralApBonus(Player* player, int32& feral_bonus, int32 dpsMod, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv); + bool OnPlayerCanApplyWeaponDependentAuraDamageMod(Player* player, Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply); + bool OnPlayerCanApplyEquipSpell(Player* player, SpellInfo const* spellInfo, Item* item, bool apply, bool form_change); + bool OnPlayerCanApplyEquipSpellsItemSet(Player* player, ItemSetEffect* eff); + bool OnPlayerCanCastItemCombatSpell(Player* player, Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto); + bool OnPlayerCanCastItemUseSpell(Player* player, Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex); + void OnPlayerApplyAmmoBonuses(Player* player, ItemTemplate const* proto, float& currentAmmoDPS); + bool OnPlayerCanEquipItem(Player* player, uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading); + bool OnPlayerCanUnequipItem(Player* player, uint16 pos, bool swap); + bool OnPlayerCanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result); + bool OnPlayerCanSaveEquipNewItem(Player* player, Item* item, uint16 pos, bool update); + bool OnPlayerCanApplyEnchantment(Player* player, Item* item, EnchantmentSlot slot, bool apply, bool apply_dur, bool ignore_condition); + void OnPlayerGetQuestRate(Player* player, float& result); + bool OnPlayerPassedQuestKilledMonsterCredit(Player* player, Quest const* qinfo, uint32 entry, uint32 real_entry, ObjectGuid guid); + bool OnPlayerCheckItemInSlotAtLoadInventory(Player* player, Item* item, uint8 slot, uint8& err, uint16& dest); + bool OnPlayerNotAvoidSatisfy(Player* player, DungeonProgressionRequirements const* ar, uint32 target_map, bool report); // Wahts that? + bool OnPlayerNotVisibleGloballyFor(Player* player, Player const* u); + void OnPlayerGetArenaPersonalRating(Player* player, uint8 slot, uint32& result); + void OnPlayerFfaPvpStateUpdate(Player* player, bool result); + void OnPlayerGetArenaTeamId(Player* player, uint8 slot, uint32& result); + void OnPlayerIsFFAPvP(Player* player, bool& result); + void OnPlayerIsPvP(Player* player, bool& result); + void OnPlayerGetMaxSkillValueForLevel(Player* player, uint16& result); + bool OnPlayerNotSetArenaTeamInfoField(Player* player, uint8 slot, ArenaTeamInfoType type, uint32 value); + bool OnPlayerCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment); + bool OnPlayerCanEnterMap(Player* player, MapEntry const* entry, InstanceTemplate const* instance, MapDifficulty const* mapDiff, bool loginCheck); + bool OnPlayerCanInitTrade(Player* player, Player* target); + bool OnPlayerCanSetTradeItem(Player* player, Item* tradedItem, uint8 tradeSlot); + void OnPlayerSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec); + void OnPlayerSetServerSideVisibilityDetect(Player* player, ServerSideVisibilityType& type, AccountTypes& sec); void OnPlayerResurrect(Player* player, float restore_percent, bool applySickness); - void OnBeforeChooseGraveyard(Player* player, TeamId teamId, bool nearCorpse, uint32& graveyardOverride); - bool CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg); - bool CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Player* receiver); - bool CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Group* group); - bool CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Guild* guild); - bool CanPlayerUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Channel* channel); + void OnPlayerBeforeChooseGraveyard(Player* player, TeamId teamId, bool nearCorpse, uint32& graveyardOverride); + bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg); + bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Player* receiver); + bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Group* group); + bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Guild* guild); + bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 language, std::string& msg, Channel* channel); void OnPlayerLearnTalents(Player* player, uint32 talentId, uint32 talentRank, uint32 spellid); void OnPlayerEnterCombat(Player* player, Unit* enemy); void OnPlayerLeaveCombat(Player* player); - void OnQuestAbandon(Player* player, uint32 questId); - bool CanSendErrorAlreadyLooted(Player* player); - void OnAfterCreatureLoot(Player* player); - void OnAfterCreatureLootMoney(Player* player); - bool OnCanPlayerFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell); - bool CanPlayerUpdateSkill(Player* player, uint32 skillId); - void OnBeforePlayerUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step); + void OnPlayerQuestAbandon(Player* player, uint32 questId); + bool OnPlayerCanSendErrorAlreadyLooted(Player* player); + void OnPlayerAfterCreatureLoot(Player* player); + void OnPlayerAfterCreatureLootMoney(Player* player); + bool OnPlayerCanFlyInZone(Player* player, uint32 mapId, uint32 zoneId, SpellInfo const* bySpell); + bool OnPlayerCanUpdateSkill(Player* player, uint32 skillId); + void OnPlayerBeforeUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step); void OnPlayerUpdateSkill(Player* player, uint32 skillId, uint32 value, uint32 max, uint32 step, uint32 newValue); - bool CanPlayerResurrect(Player* player); + bool OnPlayerCanResurrect(Player* player); // Anti cheat void AnticheatSetCanFlybyServer(Player* player, bool apply); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index c12b773a6..4af00a0ed 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -593,7 +593,7 @@ void WorldSession::LogoutPlayer(bool save) if (_player) { //! Call script hook before other logout events - sScriptMgr->OnBeforePlayerLogout(_player); + sScriptMgr->OnPlayerBeforeLogout(_player); if (ObjectGuid lguid = _player->GetLootGUID()) DoLootRelease(lguid); @@ -646,11 +646,11 @@ void WorldSession::LogoutPlayer(bool save) CharacterDatabase.Execute(stmt); } - sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_INVITE_LOGOUT); + sScriptMgr->OnPlayerBattlegroundDesertion(_player, BG_DESERTION_TYPE_INVITE_LOGOUT); } if (bgQueueTypeId >= BATTLEGROUND_QUEUE_2v2 && bgQueueTypeId < MAX_BATTLEGROUND_QUEUE_TYPES && _player->IsInvitedForBattlegroundQueueType(bgQueueTypeId)) - sScriptMgr->OnBattlegroundDesertion(_player, ARENA_DESERTION_TYPE_INVITE_LOGOUT); + sScriptMgr->OnPlayerBattlegroundDesertion(_player, ARENA_DESERTION_TYPE_INVITE_LOGOUT); _player->RemoveBattlegroundQueueId(bgQueueTypeId); sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).RemovePlayer(_player->GetGUID(), true); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index c10a2cb2c..75121d79c 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1765,7 +1765,7 @@ void Spell::DoCreateItem(uint8 /*effIndex*/, uint32 itemId) // send info to the client player->SendNewItem(pItem, addNumber, true, SelfCast); - sScriptMgr->OnCreateItem(player, pItem, addNumber); + sScriptMgr->OnPlayerCreateItem(player, pItem, addNumber); // we succeeded in creating at least one item, so a levelup is possible if (SelfCast) diff --git a/src/server/scripts/Events/midsummer.cpp b/src/server/scripts/Events/midsummer.cpp index 314235ab1..42aa2bc10 100644 --- a/src/server/scripts/Events/midsummer.cpp +++ b/src/server/scripts/Events/midsummer.cpp @@ -157,7 +157,7 @@ public: { } - void OnUpdateZone(Player* player, uint32 newZone, uint32 /*newArea*/) override + void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 /*newArea*/) override { if (!IsHolidayActive(HOLIDAY_FIRE_FESTIVAL)) return; diff --git a/src/server/scripts/World/action_ip_logger.cpp b/src/server/scripts/World/action_ip_logger.cpp index 1036e6f40..17a2808bd 100644 --- a/src/server/scripts/World/action_ip_logger.cpp +++ b/src/server/scripts/World/action_ip_logger.cpp @@ -179,19 +179,19 @@ public: } // CHARACTER_CREATE = 7 - void OnCreate(Player* player) override + void OnPlayerCreate(Player* player) override { CharacterIPLogAction(player, CHARACTER_CREATE); } // CHARACTER_LOGIN = 8 - void OnLogin(Player* player) override + void OnPlayerLogin(Player* player) override { CharacterIPLogAction(player, CHARACTER_LOGIN); } // CHARACTER_LOGOUT = 9 - void OnLogout(Player* player) override + void OnPlayerLogout(Player* player) override { CharacterIPLogAction(player, CHARACTER_LOGOUT); } @@ -273,13 +273,13 @@ public: } // CHARACTER_DELETE = 10 - void OnDelete(ObjectGuid guid, uint32 accountId) override + void OnPlayerDelete(ObjectGuid guid, uint32 accountId) override { DeleteIPLogAction(guid, accountId, CHARACTER_DELETE); } // CHARACTER_FAILED_DELETE = 11 - void OnFailedDelete(ObjectGuid guid, uint32 accountId) override + void OnPlayerFailedDelete(ObjectGuid guid, uint32 accountId) override { DeleteIPLogAction(guid, accountId, CHARACTER_FAILED_DELETE); } diff --git a/src/server/scripts/World/chat_log.cpp b/src/server/scripts/World/chat_log.cpp index 47863dbcd..4dac65212 100644 --- a/src/server/scripts/World/chat_log.cpp +++ b/src/server/scripts/World/chat_log.cpp @@ -36,7 +36,7 @@ public: { } - void OnChat(Player* player, uint32 type, uint32 lang, std::string& msg) override + void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg) override { std::string logType = ""; std::string chatType = ""; @@ -63,7 +63,7 @@ public: player->GetName(), chatType, lang, msg); } - void OnChat(Player* player, uint32 /*type*/, uint32 lang, std::string& msg, Player* receiver) override + void OnPlayerChat(Player* player, uint32 /*type*/, uint32 lang, std::string& msg, Player* receiver) override { //! NOTE: //! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER" @@ -74,7 +74,7 @@ public: player->GetName(), msgType, receiver ? receiver->GetName() : "", msg); } - void OnChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group) override + void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group) override { //! NOTE: //! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER" @@ -108,7 +108,7 @@ public: role, player->GetName(), action, msgType, targetGroup, msg); } - void OnChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild) override + void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild) override { //! NOTE: //! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER" @@ -131,7 +131,7 @@ public: player->GetName(), msgType, guild ? guild->GetName() : "", msg); } - void OnChat(Player* player, uint32 /*type*/, uint32 /*lang*/, std::string& msg, Channel* channel) override + void OnPlayerChat(Player* player, uint32 /*type*/, uint32 /*lang*/, std::string& msg, Channel* channel) override { bool isSystem = channel && (channel->HasFlag(CHANNEL_FLAG_TRADE) || diff --git a/src/server/scripts/World/server_mail.cpp b/src/server/scripts/World/server_mail.cpp index 16935a733..0e15f658b 100644 --- a/src/server/scripts/World/server_mail.cpp +++ b/src/server/scripts/World/server_mail.cpp @@ -27,7 +27,7 @@ public: ServerMailReward() : PlayerScript("ServerMailReward", {PLAYERHOOK_ON_LOGIN}) { } // CHARACTER_LOGIN = 8 - void OnLogin(Player* player) override + void OnPlayerLogin(Player* player) override { // Retrieve all server mail records and session only once auto const& serverMailStore = sObjectMgr->GetAllServerMailStore(); From 6c91d0f4a5af2bd17cd0b4e30b23fb966ba638fa Mon Sep 17 00:00:00 2001 From: Rocco Silipo <108557877+Rorschach91@users.noreply.github.com> Date: Sun, 16 Feb 2025 21:06:52 +0100 Subject: [PATCH 56/97] fix(DB/Creatures) Various Northrend NPCs now have a SmartAI. (#21471) --- .../Northrend_Multiple_SmartAI.sql | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 data/sql/updates/pending_db_world/Northrend_Multiple_SmartAI.sql diff --git a/data/sql/updates/pending_db_world/Northrend_Multiple_SmartAI.sql b/data/sql/updates/pending_db_world/Northrend_Multiple_SmartAI.sql new file mode 100644 index 000000000..f9746dfe5 --- /dev/null +++ b/data/sql/updates/pending_db_world/Northrend_Multiple_SmartAI.sql @@ -0,0 +1,76 @@ + +-- Chillmere Tidehunter +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24460; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24460); +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 +(24460, 0, 0, 0, 9, 0, 100, 0, 5000, 10000, 10000, 15000, 0, 5, 11, 6533, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Chillmere Tidehunter - Within 0-5 Range - Cast \'Net\''), +(24460, 0, 2, 0, 9, 0, 100, 0, 1000, 2000, 1000, 2000, 5, 30, 11, 38556, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Chillmere Tidehunter - Within 5-30 Range - Cast \'Throw\''); + +-- Chillmere Coastrunner +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24459; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24459); +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 +(24459, 0, 0, 0, 0, 0, 100, 0, 6000, 12000, 12000, 18000, 0, 0, 11, 14874, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Chillmere Coastrunner - In Combat - Cast \'Rupture\''), +(24459, 0, 1, 0, 0, 0, 100, 0, 12000, 18000, 8000, 16000, 0, 0, 11, 28428, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Chillmere Coastrunner - In Combat - Cast \'Instant Poison\''); + +-- Chillmere Oracle +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24461; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24461); +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 +(24461, 0, 0, 0, 9, 0, 100, 0, 1000, 2000, 8000, 45000, 0, 5, 11, 11831, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Chillmere Oracle - Within 0-5 Range - Cast \'Frost Nova\''), +(24461, 0, 1, 0, 0, 0, 100, 0, 4000, 8000, 12000, 18000, 0, 0, 11, 49935, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Chillmere Oracle - In Combat - Cast \'Hex of the Murloc\''), +(24461, 0, 2, 0, 0, 0, 100, 0, 8000, 12000, 8000, 12000, 0, 0, 11, 49906, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Chillmere Oracle - In Combat - Cast \'Ice Lance\''); + +-- Rotgill +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24546; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24546); +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 +(24546, 0, 0, 0, 0, 0, 100, 0, 2000, 4000, 2000, 12000, 0, 0, 11, 49956, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rotgill - In Combat - Cast \'Searing Wound\''), +(24546, 0, 1, 0, 2, 0, 100, 0, 0, 25, 0, 0, 0, 0, 11, 8599, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Rotgill - Between 0-25% Health - Cast \'Enrage\''); + +-- Reef Cow +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24797; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24797); +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 +(24797, 0, 0, 0, 0, 0, 100, 0, 4000, 6000, 6000, 16000, 0, 0, 11, 50169, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Reef Cow - In Combat - Cast \'Flipper Thwack\''); + +-- Blood Shade +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24872; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24872); +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 +(24872, 0, 0, 0, 0, 0, 100, 0, 4000, 12000, 4000, 12000, 0, 0, 11, 49843, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Blood Shade - In Combat - Cast \'Vexed Blood of the Ancestors\''); + +-- Risen Vrykul Ancestor +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24871; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24871); +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 +(24871, 0, 0, 0, 0, 0, 100, 0, 10000, 30000, 30000, 60000, 0, 0, 11, 49841, 32, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Risen Vrykul Ancestor - In Combat - Cast \'Perturbing Strike\''); + +-- Onslaught Infantry +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 27330; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 27330); +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 +(27330, 0, 0, 0, 0, 0, 100, 0, 2000, 4000, 2000, 4000, 0, 0, 11, 50713, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Onslaught Infantry - In Combat - Cast \'Unrelenting Onslaught\''); + +-- Forgotten Captain +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 27220; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 27220); +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 +(27220, 0, 0, 0, 0, 0, 100, 0, 6000, 9000, 8000, 12000, 0, 0, 11, 51591, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Forgotten Captain - In Combat - Cast \'Stormhammer\''); + +-- Old Crystalbark +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 32357; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 32357); +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 +(32357, 0, 0, 0, 0, 0, 100, 0, 3700, 16200, 19200, 28000, 0, 0, 11, 50506, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Old Crystalbark - In Combat - Cast \'Mark of Detonation\''), +(32357, 0, 1, 0, 0, 0, 100, 0, 1625, 8100, 9600, 14000, 0, 0, 11, 60903, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Old Crystalbark - In Combat - Cast \'Arcane Breath\''); From 8cfe71e27e90a9bfcd3ebb78a5dd3eec6b0dc8b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Feb 2025 20:07:56 +0000 Subject: [PATCH 57/97] chore(DB): import pending files Referenced commit(s): 6c91d0f4a5af2bd17cd0b4e30b23fb966ba638fa --- .../2025_02_16_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/Northrend_Multiple_SmartAI.sql => db_world/2025_02_16_00.sql} (99%) diff --git a/data/sql/updates/pending_db_world/Northrend_Multiple_SmartAI.sql b/data/sql/updates/db_world/2025_02_16_00.sql similarity index 99% rename from data/sql/updates/pending_db_world/Northrend_Multiple_SmartAI.sql rename to data/sql/updates/db_world/2025_02_16_00.sql index f9746dfe5..024d56356 100644 --- a/data/sql/updates/pending_db_world/Northrend_Multiple_SmartAI.sql +++ b/data/sql/updates/db_world/2025_02_16_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_15_02 -> 2025_02_16_00 -- Chillmere Tidehunter UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24460; From 3291c747c5345302456c6b8697375f2c3ff563a4 Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Sun, 16 Feb 2025 21:19:31 +0100 Subject: [PATCH 58/97] feat(Core/DBUpdater): include pending path (#21469) --- .../pending_db_auth/rev_1739664850515709200.sql | 10 ++++++++++ .../pending_db_characters/rev_1739664807403132000.sql | 10 ++++++++++ .../pending_db_world/rev_1739663978360122100.sql | 10 ++++++++++ src/server/apps/worldserver/worldserver.conf.dist | 2 +- src/server/database/Updater/UpdateFetcher.cpp | 10 +++------- src/server/database/Updater/UpdateFetcher.h | 5 +++++ 6 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 data/sql/updates/pending_db_auth/rev_1739664850515709200.sql create mode 100644 data/sql/updates/pending_db_characters/rev_1739664807403132000.sql create mode 100644 data/sql/updates/pending_db_world/rev_1739663978360122100.sql diff --git a/data/sql/updates/pending_db_auth/rev_1739664850515709200.sql b/data/sql/updates/pending_db_auth/rev_1739664850515709200.sql new file mode 100644 index 000000000..17f145d81 --- /dev/null +++ b/data/sql/updates/pending_db_auth/rev_1739664850515709200.sql @@ -0,0 +1,10 @@ +-- +ALTER TABLE `updates` + CHANGE COLUMN `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if an update is released or archived.' COLLATE 'utf8mb4_unicode_ci' AFTER `hash`; + +ALTER TABLE `updates_include` + CHANGE COLUMN `state` `state` ENUM('RELEASED','ARCHIVED','CUSTOM','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if the directory contains released or archived updates.' COLLATE 'utf8mb4_unicode_ci' AFTER `path`; + +DELETE FROM `updates_include` WHERE `path` = '$/data/sql/updates/pending_db_auth'; +INSERT INTO `updates_include` (`path`, `state`) VALUES +('$/data/sql/updates/pending_db_auth', 'PENDING'); diff --git a/data/sql/updates/pending_db_characters/rev_1739664807403132000.sql b/data/sql/updates/pending_db_characters/rev_1739664807403132000.sql new file mode 100644 index 000000000..249070e21 --- /dev/null +++ b/data/sql/updates/pending_db_characters/rev_1739664807403132000.sql @@ -0,0 +1,10 @@ +-- +ALTER TABLE `updates` + CHANGE COLUMN `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if an update is released or archived.' COLLATE 'utf8mb4_unicode_ci' AFTER `hash`; + +ALTER TABLE `updates_include` + CHANGE COLUMN `state` `state` ENUM('RELEASED','ARCHIVED','CUSTOM','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if the directory contains released or archived updates.' COLLATE 'utf8mb4_unicode_ci' AFTER `path`; + +DELETE FROM `updates_include` WHERE `path` = '$/data/sql/updates/pending_db_characters'; +INSERT INTO `updates_include` (`path`, `state`) VALUES +('$/data/sql/updates/pending_db_characters', 'PENDING'); diff --git a/data/sql/updates/pending_db_world/rev_1739663978360122100.sql b/data/sql/updates/pending_db_world/rev_1739663978360122100.sql new file mode 100644 index 000000000..5e2f9c5c8 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1739663978360122100.sql @@ -0,0 +1,10 @@ +-- +ALTER TABLE `updates` + CHANGE COLUMN `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if an update is released or archived.' COLLATE 'utf8mb4_unicode_ci' AFTER `hash`; + +ALTER TABLE `updates_include` + CHANGE COLUMN `state` `state` ENUM('RELEASED','ARCHIVED','CUSTOM','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if the directory contains released or archived updates.' COLLATE 'utf8mb4_unicode_ci' AFTER `path`; + +DELETE FROM `updates_include` WHERE `path` = '$/data/sql/updates/pending_db_world'; +INSERT INTO `updates_include` (`path`, `state`) VALUES +('$/data/sql/updates/pending_db_world', 'PENDING'); diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index 4e32c5807..d0597bfc2 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -291,7 +291,7 @@ FlashAtStart = 1 # DATABASE_CHARACTER = 2, // Character database # DATABASE_WORLD = 4, // World database # -# Default: 7 - (All enabled) +# Default: 7 - (All enabled) # 4 - (Enable world only) # 0 - (All disabled) diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index 79e288d1e..67d7e393e 100644 --- a/src/server/database/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp @@ -157,9 +157,7 @@ UpdateFetcher::DirectoryStorage UpdateFetcher::ReceiveIncludedDirectories() cons std::vector moduleList; for (auto const& itr : Acore::Tokenize(_modulesList, ',', true)) - { moduleList.emplace_back(itr); - } // data/sql for (auto const& itr : moduleList) @@ -168,9 +166,7 @@ UpdateFetcher::DirectoryStorage UpdateFetcher::ReceiveIncludedDirectories() cons Path const p(path); if (!is_directory(p)) - { continue; - } DirectoryEntry const entry = { p, AppliedFileEntry::StateConvert("MODULE") }; directories.push_back(entry); @@ -386,14 +382,14 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, // Apply default updates for (auto const& availableQuery : available) { - if (availableQuery.second != CUSTOM && availableQuery.second != MODULE) + if (availableQuery.second != PENDING && availableQuery.second != CUSTOM && availableQuery.second != MODULE) ApplyUpdateFile(availableQuery); } - // Apply only custom/module updates + // Apply only pending/custom/module updates for (auto const& availableQuery : available) { - if (availableQuery.second == CUSTOM || availableQuery.second == MODULE) + if (availableQuery.second == PENDING || availableQuery.second == CUSTOM || availableQuery.second == MODULE) ApplyUpdateFile(availableQuery); } diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h index ca7d8c2d8..2f9027bdb 100644 --- a/src/server/database/Updater/UpdateFetcher.h +++ b/src/server/database/Updater/UpdateFetcher.h @@ -72,6 +72,7 @@ private: { RELEASED, CUSTOM, + PENDING, MODULE, ARCHIVED }; @@ -92,6 +93,8 @@ private: return RELEASED; else if (state == "CUSTOM") return CUSTOM; + else if (state == "PENDING") + return PENDING; else if (state == "MODULE") return MODULE; @@ -106,6 +109,8 @@ private: return "RELEASED"; case CUSTOM: return "CUSTOM"; + case PENDING: + return "PENDING"; case MODULE: return "MODULE"; case ARCHIVED: From d0085feb951d735db240ab4169f77b31b37646f7 Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Sun, 16 Feb 2025 21:20:29 +0100 Subject: [PATCH 59/97] =?UTF-8?q?fix(DB/Auth):=20allow=20autobroadcast=5Fl?= =?UTF-8?q?ocale=20to=20have=20multiple=20locales=20for=E2=80=A6=20(#21467?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/sql/updates/pending_db_auth/rev_1739653958699584600.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 data/sql/updates/pending_db_auth/rev_1739653958699584600.sql diff --git a/data/sql/updates/pending_db_auth/rev_1739653958699584600.sql b/data/sql/updates/pending_db_auth/rev_1739653958699584600.sql new file mode 100644 index 000000000..195b69bb9 --- /dev/null +++ b/data/sql/updates/pending_db_auth/rev_1739653958699584600.sql @@ -0,0 +1,4 @@ +-- +ALTER TABLE `autobroadcast_locale` +DROP PRIMARY KEY, +ADD PRIMARY KEY (`realmid`, `id`, `locale`); From 5fb67bdd5c6fedf985863cfbc69fe3c60431e571 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Feb 2025 20:20:31 +0000 Subject: [PATCH 60/97] chore(DB): import pending files Referenced commit(s): 3291c747c5345302456c6b8697375f2c3ff563a4 --- .../rev_1739653958699584600.sql => db_auth/2025_02_16_00.sql} | 1 + .../rev_1739664850515709200.sql => db_auth/2025_02_16_01.sql} | 1 + .../2025_02_16_00.sql} | 1 + .../rev_1739663978360122100.sql => db_world/2025_02_16_01.sql} | 1 + 4 files changed, 4 insertions(+) rename data/sql/updates/{pending_db_auth/rev_1739653958699584600.sql => db_auth/2025_02_16_00.sql} (69%) rename data/sql/updates/{pending_db_auth/rev_1739664850515709200.sql => db_auth/2025_02_16_01.sql} (93%) rename data/sql/updates/{pending_db_characters/rev_1739664807403132000.sql => db_characters/2025_02_16_00.sql} (94%) rename data/sql/updates/{pending_db_world/rev_1739663978360122100.sql => db_world/2025_02_16_01.sql} (94%) diff --git a/data/sql/updates/pending_db_auth/rev_1739653958699584600.sql b/data/sql/updates/db_auth/2025_02_16_00.sql similarity index 69% rename from data/sql/updates/pending_db_auth/rev_1739653958699584600.sql rename to data/sql/updates/db_auth/2025_02_16_00.sql index 195b69bb9..8f68f2670 100644 --- a/data/sql/updates/pending_db_auth/rev_1739653958699584600.sql +++ b/data/sql/updates/db_auth/2025_02_16_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_01_26_00 -> 2025_02_16_00 -- ALTER TABLE `autobroadcast_locale` DROP PRIMARY KEY, diff --git a/data/sql/updates/pending_db_auth/rev_1739664850515709200.sql b/data/sql/updates/db_auth/2025_02_16_01.sql similarity index 93% rename from data/sql/updates/pending_db_auth/rev_1739664850515709200.sql rename to data/sql/updates/db_auth/2025_02_16_01.sql index 17f145d81..87911ccba 100644 --- a/data/sql/updates/pending_db_auth/rev_1739664850515709200.sql +++ b/data/sql/updates/db_auth/2025_02_16_01.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_16_00 -> 2025_02_16_01 -- ALTER TABLE `updates` CHANGE COLUMN `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if an update is released or archived.' COLLATE 'utf8mb4_unicode_ci' AFTER `hash`; diff --git a/data/sql/updates/pending_db_characters/rev_1739664807403132000.sql b/data/sql/updates/db_characters/2025_02_16_00.sql similarity index 94% rename from data/sql/updates/pending_db_characters/rev_1739664807403132000.sql rename to data/sql/updates/db_characters/2025_02_16_00.sql index 249070e21..0f4f14721 100644 --- a/data/sql/updates/pending_db_characters/rev_1739664807403132000.sql +++ b/data/sql/updates/db_characters/2025_02_16_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_12_00 -> 2025_02_16_00 -- ALTER TABLE `updates` CHANGE COLUMN `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if an update is released or archived.' COLLATE 'utf8mb4_unicode_ci' AFTER `hash`; diff --git a/data/sql/updates/pending_db_world/rev_1739663978360122100.sql b/data/sql/updates/db_world/2025_02_16_01.sql similarity index 94% rename from data/sql/updates/pending_db_world/rev_1739663978360122100.sql rename to data/sql/updates/db_world/2025_02_16_01.sql index 5e2f9c5c8..75a41744f 100644 --- a/data/sql/updates/pending_db_world/rev_1739663978360122100.sql +++ b/data/sql/updates/db_world/2025_02_16_01.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_16_00 -> 2025_02_16_01 -- ALTER TABLE `updates` CHANGE COLUMN `state` `state` ENUM('RELEASED','CUSTOM','MODULE','ARCHIVED','PENDING') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if an update is released or archived.' COLLATE 'utf8mb4_unicode_ci' AFTER `hash`; From 4c66c589e44fd7ac28a77fdae16bcc83f56cb5cc Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Sun, 16 Feb 2025 23:07:37 +0100 Subject: [PATCH 61/97] fix(Core/Spells): Implement SPELL_ATTR2_ALLOW_LOW_LEVEL_BUFF (#21470) Co-authored-by: Shauren --- src/server/game/Spells/Spell.cpp | 31 +++++++++++++++++++++------- src/server/game/Spells/SpellInfo.cpp | 4 ++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1b9ff3a15..e20def2cb 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -7461,9 +7461,19 @@ SpellCastResult Spell::CheckItems() if (!targetItem) return SPELL_FAILED_ITEM_NOT_FOUND; - // xinef: required level has to be checked also! Exploit fix - if (targetItem->GetTemplate()->ItemLevel < m_spellInfo->BaseLevel || (targetItem->GetTemplate()->RequiredLevel && targetItem->GetTemplate()->RequiredLevel < m_spellInfo->BaseLevel)) - return SPELL_FAILED_LOWLEVEL; + // Apply item level restriction + if (!m_spellInfo->HasAttribute(SPELL_ATTR2_ALLOW_LOW_LEVEL_BUFF)) + { + uint32 requiredLevel = targetItem->GetTemplate()->RequiredLevel; + if (!requiredLevel) + requiredLevel = targetItem->GetTemplate()->ItemLevel; + + if (requiredLevel < m_spellInfo->BaseLevel) + return SPELL_FAILED_LOWLEVEL; + } + + if (m_CastItem && m_spellInfo->MaxLevel > 0 && targetItem->GetTemplate()->ItemLevel > m_spellInfo->MaxLevel) + return SPELL_FAILED_HIGHLEVEL; bool isItemUsable = false; for (uint8 e = 0; e < MAX_ITEM_PROTO_SPELLS; ++e) @@ -7531,15 +7541,20 @@ SpellCastResult Spell::CheckItems() return SPELL_FAILED_NOT_TRADEABLE; } - // Xinef: Apply item level restriction if the enchanting spell has max level restrition set - if (m_CastItem && m_spellInfo->MaxLevel > 0) + // Apply item level restriction + if (!m_spellInfo->HasAttribute(SPELL_ATTR2_ALLOW_LOW_LEVEL_BUFF)) { - if (item->GetTemplate()->ItemLevel < m_CastItem->GetTemplate()->RequiredLevel) + uint32 requiredLevel = item->GetTemplate()->RequiredLevel; + if (!requiredLevel) + requiredLevel = item->GetTemplate()->ItemLevel; + + if (requiredLevel < m_spellInfo->BaseLevel) return SPELL_FAILED_LOWLEVEL; - if (item->GetTemplate()->ItemLevel > m_spellInfo->MaxLevel) - return SPELL_FAILED_HIGHLEVEL; } + if (m_CastItem && m_spellInfo->MaxLevel > 0 && item->GetTemplate()->ItemLevel > m_spellInfo->MaxLevel) + return SPELL_FAILED_HIGHLEVEL; + break; } case SPELL_EFFECT_ENCHANT_HELD_ITEM: diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 1126614ca..9785e6da9 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -2529,6 +2529,10 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const //if (IsPassive()) // return this; + // Client ignores spell with these attributes (sub_53D9D0) + if (HasAttribute(SPELL_ATTR0_COOLDOWN_ON_EVENT) || HasAttribute(SPELL_ATTR2_ALLOW_LOW_LEVEL_BUFF) || HasAttribute(SPELL_ATTR3_ONLY_PROC_ON_CASTER)) + return this; + bool needRankSelection = false; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { From f7028d5778d660e48f32451395d7e1dc00dafeb7 Mon Sep 17 00:00:00 2001 From: Fabrizio Contigiani Date: Sun, 16 Feb 2025 19:10:59 -0300 Subject: [PATCH 62/97] fix(DB/Quest): Allow both factions to get quest "The Multiphase Survey" [id: 11880] (#21433) --- data/sql/updates/pending_db_world/fix-quest-11880.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/sql/updates/pending_db_world/fix-quest-11880.sql diff --git a/data/sql/updates/pending_db_world/fix-quest-11880.sql b/data/sql/updates/pending_db_world/fix-quest-11880.sql new file mode 100644 index 000000000..3543029b4 --- /dev/null +++ b/data/sql/updates/pending_db_world/fix-quest-11880.sql @@ -0,0 +1 @@ +UPDATE `quest_template` SET `AllowableRaces` = 0 WHERE (`ID` = 11880); From 2c7cf4832e1bc6f1a787706af4c479c61372980d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Feb 2025 22:11:59 +0000 Subject: [PATCH 63/97] chore(DB): import pending files Referenced commit(s): f7028d5778d660e48f32451395d7e1dc00dafeb7 --- .../fix-quest-11880.sql => db_world/2025_02_16_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/fix-quest-11880.sql => db_world/2025_02_16_02.sql} (61%) diff --git a/data/sql/updates/pending_db_world/fix-quest-11880.sql b/data/sql/updates/db_world/2025_02_16_02.sql similarity index 61% rename from data/sql/updates/pending_db_world/fix-quest-11880.sql rename to data/sql/updates/db_world/2025_02_16_02.sql index 3543029b4..28f34728d 100644 --- a/data/sql/updates/pending_db_world/fix-quest-11880.sql +++ b/data/sql/updates/db_world/2025_02_16_02.sql @@ -1 +1,2 @@ +-- DB update 2025_02_16_01 -> 2025_02_16_02 UPDATE `quest_template` SET `AllowableRaces` = 0 WHERE (`ID` = 11880); From 30f273e593afefab1d8279edc048e4e67a0d49a0 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Sun, 16 Feb 2025 23:14:09 +0100 Subject: [PATCH 64/97] fix(Scripts/Naxxramas): Add post-Gothik Four Horsemen introduction (#20550) --- .../rev_1731527942376561860.sql | 13 +++++ .../Naxxramas/instance_naxxramas.cpp | 50 ++++++++++++++++++- .../scripts/Northrend/Naxxramas/naxxramas.h | 7 ++- 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1731527942376561860.sql diff --git a/data/sql/updates/pending_db_world/rev_1731527942376561860.sql b/data/sql/updates/pending_db_world/rev_1731527942376561860.sql new file mode 100644 index 000000000..87e5f8000 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1731527942376561860.sql @@ -0,0 +1,13 @@ +-- +SET @ZELIEK = 16063; +UPDATE `creature_text` SET `Comment` = 'zeliek SAY_ZELI_DIALOG1' WHERE (`CreatureID` = @ZELIEK) AND (`GroupID` = 5); +UPDATE `creature_text` SET `Comment` = 'zeliek SAY_ZELI_DIALOG2' WHERE (`CreatureID` = @ZELIEK) AND (`GroupID` = 6); +SET @KORTHAZZ = 16064; +UPDATE `creature_text` SET `Comment` = 'korthazz SAY_KORT_DIALOG1' WHERE (`CreatureID` = @KORTHAZZ) AND (`GroupID` = 5); +UPDATE `creature_text` SET `Comment` = 'korthazz SAY_KORT_DIALOG2' WHERE (`CreatureID` = @KORTHAZZ) AND (`GroupID` = 6); +SET @BLAUMEUX = 16065; +UPDATE `creature_text` SET `Comment` = 'blaumeux SAY_BLAU_DIALOG1' WHERE (`CreatureID` = @BLAUMEUX) AND (`GroupID` = 5); +UPDATE `creature_text` SET `Comment` = 'blaumeux SAY_BLAU_DIALOG2' WHERE (`CreatureID` = @BLAUMEUX) AND (`GroupID` = 6); +SET @RIVENDARE = 30549; +UPDATE `creature_text` SET `Comment` = 'rivendare SAY_RIVE_DIALOG1' WHERE (`CreatureID` = @RIVENDARE) AND (`GroupID` = 5); +UPDATE `creature_text` SET `Comment` = 'rivendare SAY_RIVE_DIALOG2' WHERE (`CreatureID` = @RIVENDARE) AND (`GroupID` = 6); diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 550a84743..a72a33e29 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -101,7 +101,7 @@ public: _screamTimer = 2 * MINUTE * IN_MILLISECONDS; _hadThaddiusGreet = false; _currentWingTaunt = SAY_FIRST_WING_TAUNT; - _horsemanLoaded = 0; + _currentHorsemenLine = 0; // Achievements abominationsKilled = 0; @@ -174,6 +174,7 @@ public: bool _hadThaddiusGreet; EventMap events; uint8 _currentWingTaunt; + uint8 _currentHorsemenLine; uint8 _horsemanLoaded; // Achievements @@ -943,6 +944,7 @@ public: { go->SetGoState(GO_STATE_ACTIVE); } + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 10s); break; case BOSS_SAPPHIRON: events.ScheduleEvent(EVENT_FROSTWYRM_WATERFALL_DOOR, 5s); @@ -1071,6 +1073,52 @@ public: go->SetGoState(GO_STATE_ACTIVE); } break; + case EVENT_HORSEMEN_INTRO: + switch (_currentHorsemenLine) + { + case 0: // To arms, ye roustabouts! We've got company! + if (Creature* korthazz = instance->GetCreature(_korthazzGUID)) + korthazz->AI()->Talk(SAY_HORSEMEN_DIALOG1); + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 4500ms); + break; + case 1: // Invaders, cease this foolish venture at once! Turn away while you still can! + if (Creature* zeliek = instance->GetCreature(_zeliekGUID)) + zeliek->AI()->Talk(SAY_HORSEMEN_DIALOG1); + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 6500ms); + break; + case 2: // Come, Zeliek, do not drive them out. Not before we've had our fun! + if (Creature* blaumeux = instance->GetCreature(_blaumeuxGUID)) + blaumeux->AI()->Talk(SAY_HORSEMEN_DIALOG1); + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 6500ms); + break; + case 3: // Enough prattling. Let them come. We shall grind their bones to dust. + if (Creature* rivendare = instance->GetCreature(_rivendareGUID)) + rivendare->AI()->Talk(SAY_HORSEMEN_DIALOG1); + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 6500ms); + break; + case 4: // I do hope they stay alive long enough for me to... introduce myself. + if (Creature* blaumeux = instance->GetCreature(_blaumeuxGUID)) + blaumeux->AI()->Talk(SAY_HORSEMEN_DIALOG2); + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 6500ms); + break; + case 5: // Perhaps they will come to their senses... and run away as fast as they can. + if (Creature* zeliek = instance->GetCreature(_zeliekGUID)) + zeliek->AI()->Talk(SAY_HORSEMEN_DIALOG2); + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 6500ms); + break; + case 6: // I've heard about enough a' yer snivelin'! Shut yer flytrap before I shut it for ye'! + if (Creature* korthazz = instance->GetCreature(_korthazzGUID)) + korthazz->AI()->Talk(SAY_HORSEMEN_DIALOG2); + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 6500ms); + break; + case 7: // Conserve your anger. Harness your rage. You will all have outlets for your frustrations soon enough. + if (Creature* rivendare = instance->GetCreature(_rivendareGUID)) + rivendare->AI()->Talk(SAY_HORSEMEN_DIALOG2); + events.ScheduleEvent(EVENT_HORSEMEN_INTRO, 6500ms); + break; + } + ++_currentHorsemenLine; + break; } } diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index 1b90d2b1d..981230f15 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -190,14 +190,17 @@ enum NXSays SAY_SAPP_DIALOG5 = 4, SAY_SAPP_DIALOG6 = 20, SAY_CAT_DIED = 5, - SAY_FIRST_WING_TAUNT = 16 + SAY_FIRST_WING_TAUNT = 16, + SAY_HORSEMEN_DIALOG1 = 5, + SAY_HORSEMEN_DIALOG2 = 6 }; enum NXEvents { EVENT_THADDIUS_SCREAMS = 0, EVENT_KELTHUZAD_WING_TAUNT = 1, - EVENT_FROSTWYRM_WATERFALL_DOOR = 2 + EVENT_FROSTWYRM_WATERFALL_DOOR = 2, + EVENT_HORSEMEN_INTRO = 3 }; template From 6d88cd40f64b75b616fd4f9d6a041c413c735d5a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 16 Feb 2025 22:15:10 +0000 Subject: [PATCH 65/97] chore(DB): import pending files Referenced commit(s): 30f273e593afefab1d8279edc048e4e67a0d49a0 --- .../rev_1731527942376561860.sql => db_world/2025_02_16_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1731527942376561860.sql => db_world/2025_02_16_03.sql} (96%) diff --git a/data/sql/updates/pending_db_world/rev_1731527942376561860.sql b/data/sql/updates/db_world/2025_02_16_03.sql similarity index 96% rename from data/sql/updates/pending_db_world/rev_1731527942376561860.sql rename to data/sql/updates/db_world/2025_02_16_03.sql index 87e5f8000..1de131016 100644 --- a/data/sql/updates/pending_db_world/rev_1731527942376561860.sql +++ b/data/sql/updates/db_world/2025_02_16_03.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_16_02 -> 2025_02_16_03 -- SET @ZELIEK = 16063; UPDATE `creature_text` SET `Comment` = 'zeliek SAY_ZELI_DIALOG1' WHERE (`CreatureID` = @ZELIEK) AND (`GroupID` = 5); From 92ef042f338d6bccebb4aa7c0873bb03768c0566 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Sun, 16 Feb 2025 23:19:50 +0100 Subject: [PATCH 66/97] fix(Scripts/Spells): Warrior IntimidationShout (#20969) --- src/server/scripts/Spells/spell_warrior.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 1e848b0a4..44b35a35c 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -542,9 +542,12 @@ class spell_warr_intimidating_shout : public SpellScript { PrepareSpellScript(spell_warr_intimidating_shout); - void FilterTargets(std::list& unitList) + void FilterTargets(std::list& targets) { - unitList.remove(GetExplTargetWorldObject()); + targets.remove(GetExplTargetWorldObject()); + uint32 maxTargets = GetSpellInfo()->MaxAffectedTargets; + if (targets.size() > maxTargets) + targets.resize(maxTargets); } void Register() override From 8cc47ab1f174e82d74b2e17b4af13ded0f37a693 Mon Sep 17 00:00:00 2001 From: Razor2142 Date: Sun, 16 Feb 2025 23:26:07 +0100 Subject: [PATCH 67/97] feat(Script/Instance): added generic instance map script (#21218) Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com> --- .../game/Scripting/ScriptDefines/InstanceMapScript.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/server/game/Scripting/ScriptDefines/InstanceMapScript.h b/src/server/game/Scripting/ScriptDefines/InstanceMapScript.h index edbc9a3ba..74b5024ba 100644 --- a/src/server/game/Scripting/ScriptDefines/InstanceMapScript.h +++ b/src/server/game/Scripting/ScriptDefines/InstanceMapScript.h @@ -34,4 +34,14 @@ public: virtual InstanceScript* GetInstanceScript(InstanceMap* /*map*/) const { return nullptr; } }; +template +class GenericInstanceMapScript : public InstanceMapScript +{ +public: + GenericInstanceMapScript(char const* name, uint32 mapId) : InstanceMapScript(name, mapId) { } + InstanceScript* GetInstanceScript(InstanceMap* map) const override { return new IS(map); } +}; + +#define RegisterInstanceScript(script_name, mapId) new GenericInstanceMapScript(#script_name, mapId) + #endif From 0c099a75ec709f30308b4b2a07c9befd450e9134 Mon Sep 17 00:00:00 2001 From: Paul <60552737+demetrzz@users.noreply.github.com> Date: Mon, 17 Feb 2025 01:27:45 +0300 Subject: [PATCH 68/97] fix(Core/Spell): Corrected values for event food (#21465) Co-authored-by: pavel_k --- src/server/game/Spells/SpellInfoCorrections.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index 85349a0c5..dc2ecf080 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4876,6 +4876,14 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->SchoolMask = SPELL_SCHOOL_MASK_NATURE; }); + // Event food, fixes to give correct stamina and spirit of 25% of the character level + ApplySpellFix({ 24870 }, [](SpellInfo* spellInfo) + { + spellInfo->Effects[EFFECT_1].BasePoints = 0; + spellInfo->Effects[EFFECT_0].RealPointsPerLevel = 0.25; + spellInfo->Effects[EFFECT_1].RealPointsPerLevel = 0.25; + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; From e28384b059f8b266ebea1da771df56f5ff36a277 Mon Sep 17 00:00:00 2001 From: iThorgrim <125808072+iThorgrim@users.noreply.github.com> Date: Mon, 17 Feb 2025 03:26:05 +0100 Subject: [PATCH 69/97] feat(Core/Scripting): Add new hooks for Ticket (#21238) --- src/server/game/Handlers/TicketHandler.cpp | 2 +- .../ScriptDefines/AllScriptsObjects.h | 1 + .../Scripting/ScriptDefines/TicketScript.cpp | 58 +++++++++++++++++++ .../Scripting/ScriptDefines/TicketScript.h | 50 ++++++++++++++++ src/server/game/Scripting/ScriptMgr.cpp | 5 +- src/server/game/Scripting/ScriptMgr.h | 8 +++ src/server/game/Scripting/ScriptObjectFwd.h | 1 + src/server/game/Tickets/TicketMgr.cpp | 11 +++- src/server/game/Tickets/TicketMgr.h | 2 +- src/server/scripts/Commands/cs_ticket.cpp | 18 +++--- 10 files changed, 143 insertions(+), 13 deletions(-) create mode 100644 src/server/game/Scripting/ScriptDefines/TicketScript.cpp create mode 100644 src/server/game/Scripting/ScriptDefines/TicketScript.h diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp index 6d53bf95b..eb6243b21 100644 --- a/src/server/game/Handlers/TicketHandler.cpp +++ b/src/server/game/Handlers/TicketHandler.cpp @@ -116,7 +116,7 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData) ticket->SetChatLog(times, chatLog); sTicketMgr->AddTicket(ticket); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); ChatHandler(nullptr).SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName(), ticket->GetId()); diff --git a/src/server/game/Scripting/ScriptDefines/AllScriptsObjects.h b/src/server/game/Scripting/ScriptDefines/AllScriptsObjects.h index aad81c070..9196c3284 100644 --- a/src/server/game/Scripting/ScriptDefines/AllScriptsObjects.h +++ b/src/server/game/Scripting/ScriptDefines/AllScriptsObjects.h @@ -58,6 +58,7 @@ #include "PlayerScript.h" #include "ServerScript.h" #include "SpellScriptLoader.h" +#include "TicketScript.h" #include "TransportScript.h" #include "UnitScript.h" #include "VehicleScript.h" diff --git a/src/server/game/Scripting/ScriptDefines/TicketScript.cpp b/src/server/game/Scripting/ScriptDefines/TicketScript.cpp new file mode 100644 index 000000000..a7e72076f --- /dev/null +++ b/src/server/game/Scripting/ScriptDefines/TicketScript.cpp @@ -0,0 +1,58 @@ +/* + * 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 "TicketScript.h" +#include "ScriptMgr.h" +#include "ScriptMgrMacros.h" + +void ScriptMgr::OnTicketCreate(GmTicket* ticket) +{ + CALL_ENABLED_HOOKS(TicketScript, TICKETHOOK_ON_TICKET_CREATE, script->OnTicketCreate(ticket)); +} + +void ScriptMgr::OnTicketUpdateLastChange(GmTicket* ticket) +{ + CALL_ENABLED_HOOKS(TicketScript, TICKETHOOK_ON_TICKET_UPDATE_LAST_CHANGE, script->OnTicketUpdateLastChange(ticket)); +} + +void ScriptMgr::OnTicketClose(GmTicket* ticket) +{ + CALL_ENABLED_HOOKS(TicketScript, TICKETHOOK_ON_TICKET_CLOSE, script->OnTicketClose(ticket)); +} + +void ScriptMgr::OnTicketStatusUpdate(GmTicket* ticket) +{ + CALL_ENABLED_HOOKS(TicketScript, TICKETHOOK_ON_TICKET_STATUS_UPDATE, script->OnTicketStatusUpdate(ticket)); +} + +void ScriptMgr::OnTicketResolve(GmTicket* ticket) +{ + CALL_ENABLED_HOOKS(TicketScript, TICKETHOOK_ON_TICKET_RESOLVE, script->OnTicketResolve(ticket)); +} + +TicketScript::TicketScript(char const* name, std::vector enabledHooks) +: ScriptObject(name, TICKETHOOK_END) +{ + // If empty - enable all available hooks. + if (enabledHooks.empty()) + for (uint16 i = 0; i < TICKETHOOK_END; ++i) + enabledHooks.emplace_back(i); + + ScriptRegistry::AddScript(this, std::move(enabledHooks)); +} + +template class AC_GAME_API ScriptRegistry; diff --git a/src/server/game/Scripting/ScriptDefines/TicketScript.h b/src/server/game/Scripting/ScriptDefines/TicketScript.h new file mode 100644 index 000000000..43bf616ae --- /dev/null +++ b/src/server/game/Scripting/ScriptDefines/TicketScript.h @@ -0,0 +1,50 @@ +/* + * 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 . + */ + +#ifndef SCRIPT_OBJECT_TICKET_SCRIPT_H_ +#define SCRIPT_OBJECT_TICKET_SCRIPT_H_ + +#include "ScriptObject.h" +#include "TicketMgr.h" +#include + +enum TicketHook +{ + TICKETHOOK_ON_TICKET_CREATE, + TICKETHOOK_ON_TICKET_UPDATE_LAST_CHANGE, + TICKETHOOK_ON_TICKET_CLOSE, + TICKETHOOK_ON_TICKET_STATUS_UPDATE, + TICKETHOOK_ON_TICKET_RESOLVE, + TICKETHOOK_END +}; + +class TicketScript : public ScriptObject +{ +protected: + TicketScript(char const* name, std::vector enabledHooks = std::vector()); + +public: + [[nodiscard]] bool IsDatabaseBound() const override { return false; } + + virtual void OnTicketCreate(GmTicket* /*ticket*/) { } + virtual void OnTicketUpdateLastChange(GmTicket* /*ticket*/) { } + virtual void OnTicketClose(GmTicket* /*ticket*/) { } + virtual void OnTicketStatusUpdate(GmTicket* /*ticket*/) { } + virtual void OnTicketResolve(GmTicket* /*ticket*/) { } +}; + +#endif diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 83af4d851..3a78145ca 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -98,6 +98,7 @@ void ScriptMgr::Initialize() ScriptRegistry::InitEnabledHooksIfNeeded(PLAYERHOOK_END); ScriptRegistry::InitEnabledHooksIfNeeded(SERVERHOOK_END); ScriptRegistry::InitEnabledHooksIfNeeded(ALLSPELLHOOK_END); + ScriptRegistry::InitEnabledHooksIfNeeded(TICKETHOOK_END); ScriptRegistry::InitEnabledHooksIfNeeded(UNITHOOK_END); ScriptRegistry::InitEnabledHooksIfNeeded(WORLDOBJECTHOOK_END); ScriptRegistry::InitEnabledHooksIfNeeded(WORLDHOOK_END); @@ -145,6 +146,7 @@ void ScriptMgr::Unload() SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); + SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); @@ -224,7 +226,8 @@ void ScriptMgr::CheckIfScriptsInDatabaseExist() !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && !ScriptRegistry::GetScriptById(sid) && - !ScriptRegistry::GetScriptById(sid)) + !ScriptRegistry::GetScriptById(sid) && + !ScriptRegistry::GetScriptById(sid)) { LOG_ERROR("sql.sql", "Script named '{}' is assigned in the database, but has no code!", scriptName); } diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index a0db4d2ea..0d7091e48 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -704,6 +704,14 @@ public: /* LootScript */ void OnLootMoney(Player* player, uint32 gold); +public: /* TicketScript */ + + void OnTicketCreate(GmTicket* ticket); + void OnTicketUpdateLastChange(GmTicket* ticket); + void OnTicketClose(GmTicket* ticket); + void OnTicketStatusUpdate(GmTicket* ticket); + void OnTicketResolve(GmTicket* ticket); + private: uint32 _scriptCount; diff --git a/src/server/game/Scripting/ScriptObjectFwd.h b/src/server/game/Scripting/ScriptObjectFwd.h index 35f425eae..03494cbb8 100644 --- a/src/server/game/Scripting/ScriptObjectFwd.h +++ b/src/server/game/Scripting/ScriptObjectFwd.h @@ -67,6 +67,7 @@ class SpellCastTargets; class SpellInfo; class SpellScript; class TempSummon; +class TicketMgr; class Transport; class Unit; class Vehicle; diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp index e4d2d94df..f339be0e1 100644 --- a/src/server/game/Tickets/TicketMgr.cpp +++ b/src/server/game/Tickets/TicketMgr.cpp @@ -25,6 +25,7 @@ #include "Log.h" #include "Opcodes.h" #include "Player.h" +#include "ScriptMgr.h" #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" @@ -364,6 +365,8 @@ void TicketMgr::AddTicket(GmTicket* ticket) ++_openTicketCount; CharacterDatabaseTransaction trans = CharacterDatabaseTransaction(nullptr); ticket->SaveToDB(trans); + + sScriptMgr->OnTicketCreate(ticket); } void TicketMgr::CloseTicket(uint32 ticketId, ObjectGuid source) @@ -375,6 +378,8 @@ void TicketMgr::CloseTicket(uint32 ticketId, ObjectGuid source) if (source) --_openTicketCount; ticket->SaveToDB(trans); + + sScriptMgr->OnTicketClose(ticket); } } @@ -398,6 +403,8 @@ void TicketMgr::ResolveAndCloseTicket(uint32 ticketId, ObjectGuid source) if (source) --_openTicketCount; ticket->SaveToDB(trans); + + sScriptMgr->OnTicketResolve(ticket); } } @@ -438,7 +445,9 @@ void TicketMgr::SendTicket(WorldSession* session, GmTicket* ticket) const session->SendPacket(&data); } -void TicketMgr::UpdateLastChange() +void TicketMgr::UpdateLastChange(GmTicket* ticket) { _lastChange = GameTime::GetGameTime().count(); + + sScriptMgr->OnTicketUpdateLastChange(ticket); } diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h index aa2369bd7..d34556716 100644 --- a/src/server/game/Tickets/TicketMgr.h +++ b/src/server/game/Tickets/TicketMgr.h @@ -230,7 +230,7 @@ public: void SetStatus(bool status) { _status = status; } uint64 GetLastChange() const { return _lastChange; } - void UpdateLastChange(); + void UpdateLastChange(GmTicket* ticket); uint32 GenerateTicketId() { return ++_lastTicketId; } uint32 GetOpenTicketCount() const { return _openTicketCount; } diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index bef6f6f13..166b0fa44 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -117,7 +117,7 @@ public: CharacterDatabaseTransaction trans = CharacterDatabaseTransaction(nullptr); ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(targetGmLevel)); ticket->SaveToDB(trans); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); std::string msg = ticket->FormatMessageString(*handler, nullptr, target.c_str(), nullptr, nullptr); handler->SendGlobalGMSysMessage(msg.c_str()); @@ -143,7 +143,7 @@ public: } sTicketMgr->ResolveAndCloseTicket(ticket->GetId(), player ? player->GetGUID() : ObjectGuid::Empty); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); std::string msg = ticket->FormatMessageString(*handler, player ? player->GetName().c_str() : "Console", nullptr, nullptr, nullptr); handler->SendGlobalGMSysMessage(msg.c_str()); @@ -182,7 +182,7 @@ public: CharacterDatabaseTransaction trans = CharacterDatabaseTransaction(nullptr); ticket->SetComment(comment.data()); ticket->SaveToDB(trans); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); std::string const assignedName = ticket->GetAssignedToName(); std::string msg = ticket->FormatMessageString(*handler, assignedName.empty() ? nullptr : assignedName.c_str(), nullptr, nullptr, nullptr); @@ -237,7 +237,7 @@ public: std::string msg = ticket->FormatMessageString(*handler, nullptr, nullptr, nullptr, nullptr); msg += handler->PGetParseString(LANG_COMMAND_TICKETCOMPLETED, gm ? gm->GetName().c_str() : "Console"); handler->SendGlobalGMSysMessage(msg.c_str()); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); return true; } @@ -260,7 +260,7 @@ public: handler->SendGlobalGMSysMessage(msg.c_str()); sTicketMgr->RemoveTicket(ticket->GetId()); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); if (Player* player = ticket->GetPlayer()) { @@ -287,7 +287,7 @@ public: if (Player* player = ticket->GetPlayer()) sTicketMgr->SendTicket(player->GetSession(), ticket); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); return true; } @@ -373,7 +373,7 @@ public: CharacterDatabaseTransaction trans = CharacterDatabaseTransaction(nullptr); ticket->SetUnassigned(); ticket->SaveToDB(trans); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); std::string msg = ticket->FormatMessageString(*handler, nullptr, assignedTo.c_str(), handler->GetSession() ? handler->GetSession()->GetPlayer()->GetName().c_str() : "Console", nullptr); @@ -464,7 +464,7 @@ public: ticket->AppendResponse("\n"); ticket->AppendResponse(response); ticket->SaveToDB(trans); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); std::string msg = ticket->FormatMessageString(*handler, nullptr, nullptr, nullptr, nullptr); msg += handler->PGetParseString(LANG_COMMAND_TICKETRESPONSEAPPENDED, response); @@ -505,7 +505,7 @@ public: CharacterDatabaseTransaction trans = CharacterDatabaseTransaction(nullptr); ticket->DeleteResponse(); ticket->SaveToDB(trans); - sTicketMgr->UpdateLastChange(); + sTicketMgr->UpdateLastChange(ticket); std::string msg = ticket->FormatMessageString(*handler, nullptr, nullptr, nullptr, nullptr); msg += handler->PGetParseString(LANG_COMMAND_TICKETRESPONSEDELETED, player ? player->GetName() : "Console"); From f89a8e0b8154013f662d5f745efecef46d3b2619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BCssig?= Date: Mon, 17 Feb 2025 06:17:51 +0100 Subject: [PATCH 70/97] fix(UnitTest): fixes unit tests not compiling under windows (#21299) --- src/common/Utilities/Random.h | 3 ++- src/test/common/Configuration/Config.cpp | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/common/Utilities/Random.h b/src/common/Utilities/Random.h index 07bc91d3a..60d543bc4 100644 --- a/src/common/Utilities/Random.h +++ b/src/common/Utilities/Random.h @@ -17,7 +17,8 @@ #ifndef Random_h__ #define Random_h__ - +#undef max +#undef min #include "Define.h" #include "Duration.h" #include diff --git a/src/test/common/Configuration/Config.cpp b/src/test/common/Configuration/Config.cpp index df1889a88..d23b87ff0 100644 --- a/src/test/common/Configuration/Config.cpp +++ b/src/test/common/Configuration/Config.cpp @@ -24,6 +24,13 @@ #include #include +#if WIN32 + void inline setenv(const char* name, const char* value, int overwrite) + { + _putenv_s(name, value); + } +#endif + std::string CreateConfigWithMap(std::map const& map) { auto mTempFileRel = boost::filesystem::unique_path("deleteme.ini"); @@ -36,8 +43,12 @@ std::string CreateConfigWithMap(std::map const& map) iniStream << itr.first << " = " << itr.second << "\n"; iniStream.close(); - +#if WIN32 + auto tmp = mTempFileAbs.native(); + return std::string(tmp.begin(), tmp.end()); +#else return mTempFileAbs.native(); +#endif } class ConfigEnvTest : public testing::Test { From 8207d1e8d0de8ddf829fafa855cfda564f86ba45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Borz=C3=AC?= Date: Mon, 17 Feb 2025 11:08:34 +0100 Subject: [PATCH 71/97] docs(README): update JetBrains logo (#21478) --- .github/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/README.md b/.github/README.md index c47d61060..d699c621b 100644 --- a/.github/README.md +++ b/.github/README.md @@ -89,4 +89,4 @@ It's important to note that AzerothCore is not an official Blizzard Entertainmen [JetBrains](https://www.jetbrains.com/?from=AzerothCore) is providing free [open-source licenses](https://www.jetbrains.com/community/opensource/) to the AzerothCore developers. -[![JetBrains](https://user-images.githubusercontent.com/75517/51205146-7f225c80-1905-11e9-82e0-835627be170d.png)](https://www.jetbrains.com/?from=AzerothCore) +[![JetBrains logo.](https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg)](https://jb.gg/OpenSourceSupport) From 58d13e69e146abc41ee3183234f9cfc9a920d216 Mon Sep 17 00:00:00 2001 From: Takenbacon Date: Mon, 17 Feb 2025 22:16:36 -0800 Subject: [PATCH 72/97] fix(Core/Grids): Standardize grid coordinates (#21479) --- src/server/game/Grids/Cells/CellImpl.h | 6 +++-- src/server/game/Grids/GridDefines.h | 27 +++++---------------- src/server/game/Grids/GridTerrainLoader.cpp | 27 +++++++++------------ src/server/game/Grids/GridTerrainLoader.h | 3 --- src/server/game/Maps/MapMgr.cpp | 6 +---- src/server/scripts/Commands/cs_misc.cpp | 13 +++------- src/server/scripts/Commands/cs_mmaps.cpp | 7 +++--- 7 files changed, 30 insertions(+), 59 deletions(-) diff --git a/src/server/game/Grids/Cells/CellImpl.h b/src/server/game/Grids/Cells/CellImpl.h index ec6e6e93a..ede2817b2 100644 --- a/src/server/game/Grids/Cells/CellImpl.h +++ b/src/server/game/Grids/Cells/CellImpl.h @@ -47,8 +47,8 @@ inline CellArea Cell::CalculateCellArea(float x, float y, float radius) return CellArea(center, center); } - CellCoord centerX = Acore::ComputeCellCoord(x - radius, y - radius).normalize(); - CellCoord centerY = Acore::ComputeCellCoord(x + radius, y + radius).normalize(); + CellCoord centerX = Acore::ComputeCellCoord(x + radius, y + radius).normalize(); + CellCoord centerY = Acore::ComputeCellCoord(x - radius, y - radius).normalize(); return CellArea(centerX, centerY); } @@ -99,6 +99,8 @@ inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor= area.low_bound.x_coord); + ASSERT(area.high_bound.y_coord >= area.low_bound.y_coord); for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x) { for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y) diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h index 62d1a6f50..7eabee5cd 100644 --- a/src/server/game/Grids/GridDefines.h +++ b/src/server/game/Grids/GridDefines.h @@ -170,20 +170,17 @@ typedef CoordPair CellCoord; namespace Acore { template - inline RET_TYPE Compute(float x, float y, float center_offset, float size) + inline RET_TYPE Compute(float x, float y, float size) { - // calculate and store temporary values in double format for having same result as same mySQL calculations - double x_offset = (double(x) - center_offset) / size; - double y_offset = (double(y) - center_offset) / size; + int gx = (int)(CENTER_VAL - x / size); + int gy = (int)(CENTER_VAL - y / size); - int x_val = int(x_offset + CENTER_VAL + 0.5f); - int y_val = int(y_offset + CENTER_VAL + 0.5f); - return RET_TYPE(x_val, y_val); + return RET_TYPE(gx, gy); } inline GridCoord ComputeGridCoord(float x, float y) { - return Compute(x, y, CENTER_GRID_OFFSET, SIZE_OF_GRIDS); + return Compute(x, y, SIZE_OF_GRIDS); } inline GridCoord ComputeGridCoordSimple(float x, float y) @@ -195,19 +192,7 @@ namespace Acore inline CellCoord ComputeCellCoord(float x, float y) { - return Compute(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL); - } - - inline CellCoord ComputeCellCoord(float x, float y, float& x_off, float& y_off) - { - double x_offset = (double(x) - CENTER_GRID_CELL_OFFSET) / SIZE_OF_GRID_CELL; - double y_offset = (double(y) - CENTER_GRID_CELL_OFFSET) / SIZE_OF_GRID_CELL; - - int x_val = int(x_offset + CENTER_GRID_CELL_ID + 0.5f); - int y_val = int(y_offset + CENTER_GRID_CELL_ID + 0.5f); - x_off = (float(x_offset) - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - y_off = (float(y_offset) - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL; - return CellCoord(x_val, y_val); + return Compute(x, y, SIZE_OF_GRID_CELL); } inline void NormalizeMapCoord(float& c) diff --git a/src/server/game/Grids/GridTerrainLoader.cpp b/src/server/game/Grids/GridTerrainLoader.cpp index b82c3b544..ecf9b0941 100644 --- a/src/server/game/Grids/GridTerrainLoader.cpp +++ b/src/server/game/Grids/GridTerrainLoader.cpp @@ -30,7 +30,7 @@ void GridTerrainLoader::LoadMap() } // map file name - std::string const mapFileName = Acore::StringFormat("{}maps/{:03}{:02}{:02}.map", sWorld->GetDataPath(), _map->GetId(), GetX(), GetY()); + std::string const mapFileName = Acore::StringFormat("{}maps/{:03}{:02}{:02}.map", sWorld->GetDataPath(), _map->GetId(), _grid.GetX(), _grid.GetY()); // loading data LOG_DEBUG("maps", "Loading map {}", mapFileName); @@ -46,25 +46,25 @@ void GridTerrainLoader::LoadMap() LOG_DEBUG("maps", "Error (result: {}) loading map file: {}", uint32(loadResult), mapFileName); } - sScriptMgr->OnLoadGridMap(_map, _grid.GetTerrainData(), GetX(), GetY()); + sScriptMgr->OnLoadGridMap(_map, _grid.GetTerrainData(), _grid.GetX(), _grid.GetY()); } void GridTerrainLoader::LoadVMap() { - int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapMgr()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), _map->GetId(), GetX(), GetY()); + int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapMgr()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), _map->GetId(), _grid.GetX(), _grid.GetY()); switch (vmapLoadResult) { case VMAP::VMAP_LOAD_RESULT_OK: LOG_DEBUG("maps", "VMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", - _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + _map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY()); break; case VMAP::VMAP_LOAD_RESULT_ERROR: LOG_DEBUG("maps", "Could not load VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", - _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + _map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY()); break; case VMAP::VMAP_LOAD_RESULT_IGNORED: LOG_DEBUG("maps", "Ignored VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", - _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + _map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY()); break; } } @@ -74,20 +74,20 @@ void GridTerrainLoader::LoadMMap() if (!DisableMgr::IsPathfindingEnabled(_map)) return; - int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(_map->GetId(), GetX(), GetY()); + int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(_map->GetId(), _grid.GetX(), _grid.GetY()); switch (mmapLoadResult) { case MMAP::MMAP_LOAD_RESULT_OK: LOG_DEBUG("maps", "MMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", - _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + _map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY()); break; case MMAP::MMAP_LOAD_RESULT_ERROR: LOG_DEBUG("maps", "Could not load MMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", - _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + _map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY()); break; case MMAP::MMAP_LOAD_RESULT_IGNORED: LOG_DEBUG("maps", "Ignored MMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", - _map->GetMapName(), _map->GetId(), GetX(), GetY(), GetX(), GetY()); + _map->GetMapName(), _map->GetId(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY()); break; } } @@ -152,9 +152,6 @@ void GridTerrainUnloader::UnloadTerrain() if (_map->GetInstanceId() != 0) return; - int gx = (MAX_NUMBER_OF_GRIDS - 1) - _grid.GetX(); - int gy = (MAX_NUMBER_OF_GRIDS - 1) - _grid.GetY(); - - VMAP::VMapFactory::createOrGetVMapMgr()->unloadMap(_map->GetId(), gx, gy); - MMAP::MMapFactory::createOrGetMMapMgr()->unloadMap(_map->GetId(), gx, gy); + VMAP::VMapFactory::createOrGetVMapMgr()->unloadMap(_map->GetId(), _grid.GetX(), _grid.GetY()); + MMAP::MMapFactory::createOrGetMMapMgr()->unloadMap(_map->GetId(), _grid.GetX(), _grid.GetY()); } diff --git a/src/server/game/Grids/GridTerrainLoader.h b/src/server/game/Grids/GridTerrainLoader.h index 03db11f7f..39cbc0d62 100644 --- a/src/server/game/Grids/GridTerrainLoader.h +++ b/src/server/game/Grids/GridTerrainLoader.h @@ -36,9 +36,6 @@ private: void LoadVMap(); void LoadMMap(); - uint16 GetX() { return (MAX_NUMBER_OF_GRIDS - 1) - _grid.GetX(); } - uint16 GetY() { return (MAX_NUMBER_OF_GRIDS - 1) - _grid.GetY(); } - MapGridType& _grid; Map* _map; }; diff --git a/src/server/game/Maps/MapMgr.cpp b/src/server/game/Maps/MapMgr.cpp index d4cf5493c..34f371a67 100644 --- a/src/server/game/Maps/MapMgr.cpp +++ b/src/server/game/Maps/MapMgr.cpp @@ -304,11 +304,7 @@ void MapMgr::DoDelayedMovesAndRemoves() bool MapMgr::ExistMapAndVMap(uint32 mapid, float x, float y) { GridCoord p = Acore::ComputeGridCoord(x, y); - - int gx = 63 - p.x_coord; - int gy = 63 - p.y_coord; - - return GridTerrainLoader::ExistMap(mapid, gx, gy) && GridTerrainLoader::ExistVMap(mapid, gx, gy); + return GridTerrainLoader::ExistMap(mapid, p.x_coord, p.y_coord) && GridTerrainLoader::ExistVMap(mapid, p.x_coord, p.y_coord); } bool MapMgr::IsValidMAP(uint32 mapid, bool startUp) diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 9f7bd9510..13ad9dec2 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -567,7 +567,8 @@ public: return false; } - Cell cell(Acore::ComputeCellCoord(object->GetPositionX(), object->GetPositionY())); + CellCoord const cellCoord = Acore::ComputeCellCoord(object->GetPositionX(), object->GetPositionY()); + Cell cell(cellCoord); uint32 zoneId, areaId; object->GetZoneAndAreaId(zoneId, areaId); @@ -584,14 +585,8 @@ public: float groundZ = object->GetMapHeight(object->GetPositionX(), object->GetPositionY(), MAX_HEIGHT); float floorZ = object->GetMapHeight(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ()); - GridCoord gridCoord = Acore::ComputeGridCoord(object->GetPositionX(), object->GetPositionY()); - - // 63? WHY? - int gridX = 63 - gridCoord.x_coord; - int gridY = 63 - gridCoord.y_coord; - - uint32 haveMap = GridTerrainLoader::ExistMap(object->GetMapId(), gridX, gridY) ? 1 : 0; - uint32 haveVMap = GridTerrainLoader::ExistVMap(object->GetMapId(), gridX, gridY) ? 1 : 0; + uint32 haveMap = GridTerrainLoader::ExistMap(object->GetMapId(), cell.GridX(), cell.GridY()) ? 1 : 0; + uint32 haveVMap = GridTerrainLoader::ExistVMap(object->GetMapId(), cell.GridX(), cell.GridY()) ? 1 : 0; uint32 haveMMAP = MMAP::MMapFactory::createOrGetMMapMgr()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()) ? 1 : 0; if (haveVMap) diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 130ec7686..f195c8f26 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -133,11 +133,10 @@ public: // grid tile location Player* player = handler->GetSession()->GetPlayer(); - int32 gx = 32 - player->GetPositionX() / SIZE_OF_GRIDS; - int32 gy = 32 - player->GetPositionY() / SIZE_OF_GRIDS; + GridCoord const gridCoord = Acore::ComputeGridCoord(player->GetPositionX(), player->GetPositionY()); - handler->PSendSysMessage("{}{}{}.mmtile", player->GetMapId(), gx, gy); - handler->PSendSysMessage("gridloc [{}, {}]", gy, gx); + handler->PSendSysMessage("{}{}{}.mmtile", player->GetMapId(), gridCoord.x_coord, gridCoord.y_coord); + handler->PSendSysMessage("gridloc [{}, {}]", gridCoord.x_coord, gridCoord.y_coord); // calculate navmesh tile location dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapMgr()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); From 854ebc8025ae8e0f6ecd713569e2f8f06b3f81b1 Mon Sep 17 00:00:00 2001 From: Takenbacon Date: Tue, 18 Feb 2025 03:15:59 -0800 Subject: [PATCH 73/97] fix(Core/Server): Add bytebuffer exception handling to addoninfo read (#21500) --- src/server/game/Server/WorldSession.cpp | 89 +++++++++++++------------ 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 4af00a0ed..bd7d556c3 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1147,57 +1147,64 @@ void WorldSession::ReadAddonsInfo(ByteBuffer& data) if (uncompress(addonInfo.contents(), &uSize, data.contents() + pos, data.size() - pos) == Z_OK) { - uint32 addonsCount; - addonInfo >> addonsCount; // addons count - - for (uint32 i = 0; i < addonsCount; ++i) + try { - std::string addonName; - uint8 enabled; - uint32 crc, unk1; + uint32 addonsCount; + addonInfo >> addonsCount; // addons count - // check next addon data format correctness - if (addonInfo.rpos() + 1 > addonInfo.size()) - return; - - addonInfo >> addonName; - - addonInfo >> enabled >> crc >> unk1; - - LOG_DEBUG("network", "ADDON: Name: {}, Enabled: 0x{:x}, CRC: 0x{:x}, Unknown2: 0x{:x}", addonName, enabled, crc, unk1); - - AddonInfo addon(addonName, enabled, crc, 2, true); - - SavedAddon const* savedAddon = AddonMgr::GetAddonInfo(addonName); - if (savedAddon) + for (uint32 i = 0; i < addonsCount; ++i) { - bool match = true; + std::string addonName; + uint8 enabled; + uint32 crc, unk1; - if (addon.CRC != savedAddon->CRC) - match = false; + // check next addon data format correctness + if (addonInfo.rpos() + 1 > addonInfo.size()) + return; - if (!match) - LOG_DEBUG("network", "ADDON: {} was known, but didn't match known CRC (0x{:x})!", addon.Name, savedAddon->CRC); + addonInfo >> addonName; + + addonInfo >> enabled >> crc >> unk1; + + LOG_DEBUG("network", "ADDON: Name: {}, Enabled: 0x{:x}, CRC: 0x{:x}, Unknown2: 0x{:x}", addonName, enabled, crc, unk1); + + AddonInfo addon(addonName, enabled, crc, 2, true); + + SavedAddon const* savedAddon = AddonMgr::GetAddonInfo(addonName); + if (savedAddon) + { + bool match = true; + + if (addon.CRC != savedAddon->CRC) + match = false; + + if (!match) + LOG_DEBUG("network", "ADDON: {} was known, but didn't match known CRC (0x{:x})!", addon.Name, savedAddon->CRC); + else + LOG_DEBUG("network", "ADDON: {} was known, CRC is correct (0x{:x})", addon.Name, savedAddon->CRC); + } else - LOG_DEBUG("network", "ADDON: {} was known, CRC is correct (0x{:x})", addon.Name, savedAddon->CRC); - } - else - { - AddonMgr::SaveAddon(addon); + { + AddonMgr::SaveAddon(addon); - LOG_DEBUG("network", "ADDON: {} (0x{:x}) was not known, saving...", addon.Name, addon.CRC); + LOG_DEBUG("network", "ADDON: {} (0x{:x}) was not known, saving...", addon.Name, addon.CRC); + } + + /// @todo: Find out when to not use CRC/pubkey, and other possible states. + m_addonsList.push_back(addon); } - /// @todo: Find out when to not use CRC/pubkey, and other possible states. - m_addonsList.push_back(addon); + uint32 currentTime; + addonInfo >> currentTime; + LOG_DEBUG("network", "ADDON: CurrentTime: {}", currentTime); + + if (addonInfo.rpos() != addonInfo.size()) + LOG_DEBUG("network", "packet under-read!"); + } + catch (ByteBufferException const& e) + { + LOG_ERROR("network", "Addon packet read error! {}", e.what()); } - - uint32 currentTime; - addonInfo >> currentTime; - LOG_DEBUG("network", "ADDON: CurrentTime: {}", currentTime); - - if (addonInfo.rpos() != addonInfo.size()) - LOG_DEBUG("network", "packet under-read!"); } else LOG_ERROR("network", "Addon packet uncompress error!"); From fca4ee32cde06aa42b4120e2540b16b52c165278 Mon Sep 17 00:00:00 2001 From: Rocco Silipo <108557877+Rorschach91@users.noreply.github.com> Date: Tue, 18 Feb 2025 18:49:00 +0100 Subject: [PATCH 74/97] fix (DB/Creature) Alarmed Blightguards now spawn as they should. (#21489) --- .../pending_db_world/Alarmed_Blightguards.sql | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 data/sql/updates/pending_db_world/Alarmed_Blightguards.sql diff --git a/data/sql/updates/pending_db_world/Alarmed_Blightguards.sql b/data/sql/updates/pending_db_world/Alarmed_Blightguards.sql new file mode 100644 index 000000000..e8907319c --- /dev/null +++ b/data/sql/updates/pending_db_world/Alarmed_Blightguards.sql @@ -0,0 +1,20 @@ + +-- Remove Wrong Spawns +DELETE FROM `creature` WHERE `id1` = 28745; + +-- Blight Cauldron Bunny 00 SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28739; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28739); +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 +(28739, 0, 0, 1, 8, 0, 100, 0, 52227, 0, 0, 0, 0, 0, 11, 52228, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Blight Cauldron Bunny 00 - On Spellhit \'Dilute Blight Cauldron\' - Cast \'Kill Credit\''), +(28739, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 52231, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blight Cauldron Bunny 00 - On Spellhit \'Dilute Blight Cauldron\' - Cast \'Cauldron Diluted Effect\''), +(28739, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 12, 28745, 4, 30000, 0, 0, 0, 202, 20, 3, 1, 0, 0, 0, 0, 0, 'Blight Cauldron Bunny 00 - On Spellhit \'Dilute Blight Cauldron\' - Summon Creature \'Alarmed Blightguard\''), +(28739, 0, 3, 0, 1, 0, 100, 512, 30000, 30000, 30000, 30000, 0, 0, 28, 52231, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blight Cauldron Bunny 00 - Out of Combat - Remove Aura \'Cauldron Diluted Effect\''); + +-- Set Random Movement for Alarmed Blightguard +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28745; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28745); +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 +(28745, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 0, 89, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alarmed Blightguard - On Reset - Start Random Movement'); From 86ee1a994c6a8e7b0ac6dc8a7e87625407b59b5e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 18 Feb 2025 17:50:05 +0000 Subject: [PATCH 75/97] chore(DB): import pending files Referenced commit(s): fca4ee32cde06aa42b4120e2540b16b52c165278 --- .../Alarmed_Blightguards.sql => db_world/2025_02_18_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/Alarmed_Blightguards.sql => db_world/2025_02_18_00.sql} (98%) diff --git a/data/sql/updates/pending_db_world/Alarmed_Blightguards.sql b/data/sql/updates/db_world/2025_02_18_00.sql similarity index 98% rename from data/sql/updates/pending_db_world/Alarmed_Blightguards.sql rename to data/sql/updates/db_world/2025_02_18_00.sql index e8907319c..2b96544f9 100644 --- a/data/sql/updates/pending_db_world/Alarmed_Blightguards.sql +++ b/data/sql/updates/db_world/2025_02_18_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_16_03 -> 2025_02_18_00 -- Remove Wrong Spawns DELETE FROM `creature` WHERE `id1` = 28745; From b80da061523e9b730a84c0776a4706d043abe785 Mon Sep 17 00:00:00 2001 From: 55Honey <71938210+55Honey@users.noreply.github.com> Date: Tue, 18 Feb 2025 20:41:11 +0100 Subject: [PATCH 76/97] fix(Core/Auth): prevent expansion overflow in SendAuthResponse (#21503) --- src/server/game/Handlers/AuthHandler.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp index 174d0f3c9..45a87579b 100644 --- a/src/server/game/Handlers/AuthHandler.cpp +++ b/src/server/game/Handlers/AuthHandler.cpp @@ -26,7 +26,12 @@ void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos) packet << uint32(0); // BillingTimeRemaining packet << uint8(0); // BillingPlanFlags packet << uint32(0); // BillingTimeRested - packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, must be set in database manually for each account + uint8 exp = Expansion(); // 0 - normal, 1 - TBC, 2 - WOTLK, must be set in database manually for each account + + if (exp >= MAX_EXPANSIONS) + exp = MAX_EXPANSIONS - 1; + + packet << uint8(exp); if (!shortForm) { From 79ba56ed3d740603ab7ba81492c19b724bd63381 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Wed, 19 Feb 2025 11:50:44 +0100 Subject: [PATCH 77/97] fix(Scripts/Spell): Priest shadowfiend attack and Shadowfiend Death proc (#20987) Co-authored-by: killerwife Co-authored-by: Grimdhex <176165533+Grimdhex@users.noreply.github.com> --- .../rev_1734727331005061017.sql | 6 ++++ src/server/scripts/Pet/pet_priest.cpp | 29 +-------------- src/server/scripts/Spells/spell_priest.cpp | 35 +++++++++++++++++++ 3 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1734727331005061017.sql diff --git a/data/sql/updates/pending_db_world/rev_1734727331005061017.sql b/data/sql/updates/pending_db_world/rev_1734727331005061017.sql new file mode 100644 index 000000000..3314a707b --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1734727331005061017.sql @@ -0,0 +1,6 @@ +-- +UPDATE `creature_template_addon` SET `auras` = '28305 8273 57989' WHERE (`entry` = 19668); +DELETE FROM `spell_script_names` WHERE `spell_id` = 57989 AND `ScriptName` = 'spell_pri_shadowfiend_death'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(57989, 'spell_pri_shadowfiend_death'); +UPDATE `creature_template` SET `ScriptName` = '' WHERE (`entry` = 19668); diff --git a/src/server/scripts/Pet/pet_priest.cpp b/src/server/scripts/Pet/pet_priest.cpp index 43ce08fbd..4dd38d8fc 100644 --- a/src/server/scripts/Pet/pet_priest.cpp +++ b/src/server/scripts/Pet/pet_priest.cpp @@ -27,10 +27,7 @@ enum PriestSpells { - SPELL_PRIEST_GLYPH_OF_SHADOWFIEND = 58228, - SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA = 58227, - SPELL_PRIEST_SHADOWFIEND_DODGE = 8273, - SPELL_PRIEST_LIGHTWELL_CHARGES = 59907 + SPELL_PRIEST_LIGHTWELL_CHARGES = 59907, }; struct npc_pet_pri_lightwell : public TotemAI @@ -55,31 +52,7 @@ struct npc_pet_pri_lightwell : public TotemAI } }; -struct npc_pet_pri_shadowfiend : public PetAI -{ - npc_pet_pri_shadowfiend(Creature* creature) : PetAI(creature) { } - - void Reset() override - { - PetAI::Reset(); - if (!me->HasAura(SPELL_PRIEST_SHADOWFIEND_DODGE)) - me->AddAura(SPELL_PRIEST_SHADOWFIEND_DODGE, me); - - if (Unit* target = me->SelectNearestTarget(15.0f)) - AttackStart(target); - } - - void JustDied(Unit* /*killer*/) override - { - if (me->IsSummon()) - if (Unit* owner = me->ToTempSummon()->GetSummonerUnit()) - if (owner->HasAura(SPELL_PRIEST_GLYPH_OF_SHADOWFIEND)) - owner->CastSpell(owner, SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA, true); - } -}; - void AddSC_priest_pet_scripts() { RegisterCreatureAI(npc_pet_pri_lightwell); - RegisterCreatureAI(npc_pet_pri_shadowfiend); } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 9253d5287..dcc482ff8 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -49,6 +49,8 @@ enum PriestSpells SPELL_PRIEST_T9_HEALING_2P = 67201, SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL = 64085, SPELL_PRIEST_T4_4P_FLEXIBILITY = 37565, + SPELL_PRIEST_GLYPH_OF_SHADOWFIEND = 58228, + SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA = 58227, SPELL_GENERIC_ARENA_DAMPENING = 74410, SPELL_GENERIC_BATTLEGROUND_DAMPENING = 74411, @@ -949,6 +951,38 @@ class spell_pri_t4_4p_bonus : public AuraScript } }; +// 57989 - Shadowfiend Death +class spell_pri_shadowfiend_death : public AuraScript +{ + PrepareAuraScript(spell_pri_shadowfiend_death); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA }); + } + + bool AfterCheckProc(ProcEventInfo& eventInfo, bool isTriggeredAtSpellProcEvent) + { + if (!isTriggeredAtSpellProcEvent) + return false; + return eventInfo.GetTypeMask() & PROC_FLAG_KILLED; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + if (Unit* owner = GetTarget()->GetOwner()) + if (owner->HasAura(SPELL_PRIEST_GLYPH_OF_SHADOWFIEND)) + owner->CastSpell(owner, SPELL_PRIEST_GLYPH_OF_SHADOWFIEND_MANA, true); + } + + void Register() override + { + DoAfterCheckProc += AuraAfterCheckProcFn(spell_pri_shadowfiend_death::AfterCheckProc); + OnEffectProc += AuraEffectProcFn(spell_pri_shadowfiend_death::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } +}; + void AddSC_priest_spell_scripts() { RegisterSpellScript(spell_pri_shadowfiend_scaling); @@ -973,4 +1007,5 @@ void AddSC_priest_spell_scripts() RegisterSpellScript(spell_pri_vampiric_touch); RegisterSpellScript(spell_pri_mind_control); RegisterSpellScript(spell_pri_t4_4p_bonus); + RegisterSpellScript(spell_pri_shadowfiend_death); } From bc17d068cdea56eaa8f95488c25ff164a58f19a6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 19 Feb 2025 10:51:50 +0000 Subject: [PATCH 78/97] chore(DB): import pending files Referenced commit(s): 79ba56ed3d740603ab7ba81492c19b724bd63381 --- .../rev_1734727331005061017.sql => db_world/2025_02_19_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1734727331005061017.sql => db_world/2025_02_19_00.sql} (89%) diff --git a/data/sql/updates/pending_db_world/rev_1734727331005061017.sql b/data/sql/updates/db_world/2025_02_19_00.sql similarity index 89% rename from data/sql/updates/pending_db_world/rev_1734727331005061017.sql rename to data/sql/updates/db_world/2025_02_19_00.sql index 3314a707b..c8e7a5cb7 100644 --- a/data/sql/updates/pending_db_world/rev_1734727331005061017.sql +++ b/data/sql/updates/db_world/2025_02_19_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_18_00 -> 2025_02_19_00 -- UPDATE `creature_template_addon` SET `auras` = '28305 8273 57989' WHERE (`entry` = 19668); DELETE FROM `spell_script_names` WHERE `spell_id` = 57989 AND `ScriptName` = 'spell_pri_shadowfiend_death'; From 4c4b04f07b48f9d9370a8153f9b8a0e611e5fdb0 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Wed, 19 Feb 2025 11:55:09 +0100 Subject: [PATCH 79/97] refactor(Core/Packet): use WorldPackets::WorldState::InitWorldStates definition (#20475) Co-authored-by: ccrs --- src/server/game/Battlefield/Battlefield.h | 4 +- .../game/Battlefield/Zones/BattlefieldWG.cpp | 61 +- .../game/Battlefield/Zones/BattlefieldWG.h | 5 +- src/server/game/Battlegrounds/Arena.cpp | 9 +- src/server/game/Battlegrounds/Arena.h | 2 +- src/server/game/Battlegrounds/Battleground.h | 3 +- .../Battlegrounds/Zones/BattlegroundAB.cpp | 23 +- .../game/Battlegrounds/Zones/BattlegroundAB.h | 2 +- .../Battlegrounds/Zones/BattlegroundAV.cpp | 30 +- .../game/Battlegrounds/Zones/BattlegroundAV.h | 2 +- .../Battlegrounds/Zones/BattlegroundBE.cpp | 7 +- .../game/Battlegrounds/Zones/BattlegroundBE.h | 2 +- .../Battlegrounds/Zones/BattlegroundDS.cpp | 7 +- .../game/Battlegrounds/Zones/BattlegroundDS.h | 2 +- .../Battlegrounds/Zones/BattlegroundEY.cpp | 52 +- .../game/Battlegrounds/Zones/BattlegroundEY.h | 8 +- .../Battlegrounds/Zones/BattlegroundIC.cpp | 18 +- .../game/Battlegrounds/Zones/BattlegroundIC.h | 2 +- .../Battlegrounds/Zones/BattlegroundNA.cpp | 6 +- .../game/Battlegrounds/Zones/BattlegroundNA.h | 3 +- .../Battlegrounds/Zones/BattlegroundRL.cpp | 6 +- .../game/Battlegrounds/Zones/BattlegroundRL.h | 2 +- .../Battlegrounds/Zones/BattlegroundRV.cpp | 6 +- .../game/Battlegrounds/Zones/BattlegroundRV.h | 2 +- .../Battlegrounds/Zones/BattlegroundSA.cpp | 58 +- .../game/Battlegrounds/Zones/BattlegroundSA.h | 2 +- .../Battlegrounds/Zones/BattlegroundWS.cpp | 17 +- .../game/Battlegrounds/Zones/BattlegroundWS.h | 2 +- src/server/game/Entities/Player/Player.cpp | 1075 +++++++++-------- src/server/game/Entities/Player/Player.h | 4 +- src/server/game/Instances/InstanceScript.h | 3 +- src/server/game/OutdoorPvP/OutdoorPvP.h | 5 +- src/server/game/Server/WorldSession.cpp | 2 +- src/server/game/World/WorldState.cpp | 24 +- src/server/game/World/WorldState.h | 2 +- .../instance_culling_of_stratholme.cpp | 14 +- .../RubySanctum/instance_ruby_sanctum.cpp | 12 +- .../instance_halls_of_reflection.cpp | 4 +- .../instance_icecrown_citadel.cpp | 16 +- .../Nexus/Oculus/instance_oculus.cpp | 1 + .../Ulduar/Ulduar/instance_ulduar.cpp | 8 +- .../scripts/OutdoorPvP/OutdoorPvPEP.cpp | 105 +- src/server/scripts/OutdoorPvP/OutdoorPvPEP.h | 14 +- .../scripts/OutdoorPvP/OutdoorPvPGH.cpp | 9 +- src/server/scripts/OutdoorPvP/OutdoorPvPGH.h | 2 +- .../scripts/OutdoorPvP/OutdoorPvPHP.cpp | 44 +- src/server/scripts/OutdoorPvP/OutdoorPvPHP.h | 4 +- .../scripts/OutdoorPvP/OutdoorPvPNA.cpp | 75 +- src/server/scripts/OutdoorPvP/OutdoorPvPNA.h | 4 +- .../scripts/OutdoorPvP/OutdoorPvPSI.cpp | 10 +- src/server/scripts/OutdoorPvP/OutdoorPvPSI.h | 3 +- .../scripts/OutdoorPvP/OutdoorPvPTF.cpp | 41 +- src/server/scripts/OutdoorPvP/OutdoorPvPTF.h | 5 +- .../scripts/OutdoorPvP/OutdoorPvPZM.cpp | 106 +- src/server/scripts/OutdoorPvP/OutdoorPvPZM.h | 18 +- 55 files changed, 1006 insertions(+), 947 deletions(-) diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index e04b180ba..966c5fc98 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -81,7 +81,7 @@ public: virtual ~BfCapturePoint() { } - virtual void FillInitialWorldStates(WorldPacket& /*data*/) {} + virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) { } // Send world state update to all players present void SendUpdateWorldState(uint32 field, uint32 value); @@ -334,7 +334,7 @@ public: /// Send all worldstate data to all player in zone. virtual void SendInitWorldStatesToAll() = 0; - virtual void FillInitialWorldStates(WorldPacket& /*data*/) = 0; + virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) = 0; /// Return if we can use mount in battlefield bool CanFlyIn() { return !m_isActive; } diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 7052f3275..91d75a385 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -29,6 +29,7 @@ #include "TemporarySummon.h" #include "Vehicle.h" #include "WorldSession.h" +#include "WorldStatePackets.h" BattlefieldWG::~BattlefieldWG() { @@ -74,7 +75,7 @@ bool BattlefieldWG::SetupBattlefield() m_saveTimer = 60000; - // Init GraveYards + // Init Graveyards SetGraveyardNumber(BATTLEFIELD_WG_GRAVEYARD_MAX); // Load from db @@ -102,12 +103,12 @@ bool BattlefieldWG::SetupBattlefield() BfGraveyardWG* graveyard = new BfGraveyardWG(this); // When between games, the graveyard is controlled by the defending team - if (WGGraveYard[i].startcontrol == TEAM_NEUTRAL) - graveyard->Initialize(WGGraveYard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SE || WGGraveYard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SW ? GetAttackerTeam() : m_DefenderTeam, WGGraveYard[i].gyid); + if (WGGraveyard[i].startcontrol == TEAM_NEUTRAL) + graveyard->Initialize(WGGraveyard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SE || WGGraveyard[i].gyid == BATTLEFIELD_WG_GY_WORKSHOP_SW ? GetAttackerTeam() : m_DefenderTeam, WGGraveyard[i].gyid); else - graveyard->Initialize(WGGraveYard[i].startcontrol, WGGraveYard[i].gyid); + graveyard->Initialize(WGGraveyard[i].startcontrol, WGGraveyard[i].gyid); - graveyard->SetTextId(WGGraveYard[i].textid); + graveyard->SetTextId(WGGraveyard[i].textid); m_GraveyardList[i] = graveyard; } @@ -933,46 +934,46 @@ uint32 BattlefieldWG::GetData(uint32 data) const return Battlefield::GetData(data); } -void BattlefieldWG::FillInitialWorldStates(WorldPacket& data) +void BattlefieldWG::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(BATTLEFIELD_WG_WORLD_STATE_ATTACKER) << uint32(GetAttackerTeam()); - data << uint32(BATTLEFIELD_WG_WORLD_STATE_DEFENDER) << uint32(GetDefenderTeam()); - data << uint32(BATTLEFIELD_WG_WORLD_STATE_ACTIVE) << uint32(IsWarTime() ? 0 : 1); // Note: cleanup these two, their names look awkward - data << uint32(BATTLEFIELD_WG_WORLD_STATE_SHOW_WORLDSTATE) << uint32(IsWarTime() ? 1 : 0); + packet.Worldstates.reserve(4+2+WG_MAX_OBJ+WG_MAX_WORKSHOP); + packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_ATTACKER, GetAttackerTeam()); + packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_DEFENDER, GetDefenderTeam()); + + // Note: cleanup these two, their names look awkward + packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_ACTIVE, IsWarTime() ? 0 : 1); + packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_SHOW_WORLDSTATE, IsWarTime() ? 1 : 0); for (uint32 i = 0; i < 2; ++i) - data << ClockWorldState[i] << uint32(GameTime::GetGameTime().count() + (m_Timer / 1000)); + packet.Worldstates.emplace_back(ClockWorldState[i], GameTime::GetGameTime().count() + (m_Timer / 1000)); - data << uint32(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_H) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_H)); - data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_H) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H); - data << uint32(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_A) << uint32(GetData(BATTLEFIELD_WG_DATA_VEHICLE_A)); - data << uint32(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_A) << GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A); + packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_VEHICLE_H)); + packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_H, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_H)); + packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_VEHICLE_A)); + packet.Worldstates.emplace_back(BATTLEFIELD_WG_WORLD_STATE_MAX_VEHICLE_A, GetData(BATTLEFIELD_WG_DATA_MAX_VEHICLE_A)); - data << uint32(WORLDSTATE_HORDE_KEEP_CAPTURED) << uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_CAPTURED)); - data << uint32(WORLDSTATE_HORDE_KEEP_DEFENDED) << uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_DEFENDED)); - data << uint32(WORLDSTATE_ALLIANCE_KEEP_CAPTURED) << uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_CAPTURED)); - data << uint32(WORLDSTATE_ALLIANCE_KEEP_DEFENDED) << uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_DEFENDED)); + packet.Worldstates.emplace_back(WORLDSTATE_ALLIANCE_KEEP_DEFENDED, uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_DEFENDED))); + packet.Worldstates.emplace_back(WORLDSTATE_HORDE_KEEP_CAPTURED, uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_CAPTURED))); + packet.Worldstates.emplace_back(WORLDSTATE_HORDE_KEEP_DEFENDED, uint32(sWorld->getWorldState(WORLDSTATE_HORDE_KEEP_DEFENDED))); + packet.Worldstates.emplace_back(WORLDSTATE_ALLIANCE_KEEP_CAPTURED, uint32(sWorld->getWorldState(WORLDSTATE_ALLIANCE_KEEP_CAPTURED))); for (GameObjectBuilding::const_iterator itr = BuildingsInZone.begin(); itr != BuildingsInZone.end(); ++itr) - data << (*itr)->m_WorldState << (*itr)->m_State; + packet.Worldstates.emplace_back((*itr)->m_WorldState, (*itr)->m_State); for (Workshop::const_iterator itr = WorkshopsList.begin(); itr != WorkshopsList.end(); ++itr) if (*itr) - data << WorkshopsData[(*itr)->workshopId].worldstate << (*itr)->state; + packet.Worldstates.emplace_back(WorkshopsData[(*itr)->workshopId].worldstate, (*itr)->state); } void BattlefieldWG::SendInitWorldStatesTo(Player* player) { - WorldPacket data(SMSG_INIT_WORLD_STATES, (4 + 4 + 4 + 2 + (BuildingsInZone.size() * 8) + (WorkshopsList.size() * 8))); + WorldPackets::WorldState::InitWorldStates packet; + packet.MapID = m_MapId; + packet.ZoneID = m_ZoneId; + packet.AreaID = player->GetAreaId(); + FillInitialWorldStates(packet); - data << uint32(m_MapId); - data << uint32(m_ZoneId); - data << uint32(0); - data << uint16(14 + BuildingsInZone.size() + WorkshopsList.size()); // Number of fields - - FillInitialWorldStates(data); - - player->GetSession()->SendPacket(&data); + player->SendDirectMessage(packet.Write()); } void BattlefieldWG::SendInitWorldStatesToAll() diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 5a53c796e..66ad47147 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -21,6 +21,7 @@ #include "Battlefield.h" #include "Log.h" #include "World.h" +#include "WorldStatePackets.h" class Group; class BattlefieldWG; @@ -238,7 +239,7 @@ const uint32 WGQuest[2][6] = { 13185, 13183, 13223, 13539, 13178, 13180 }, }; // 7 in sql, 7 in header -const BfWGCoordGY WGGraveYard[BATTLEFIELD_WG_GRAVEYARD_MAX] = +const BfWGCoordGY WGGraveyard[BATTLEFIELD_WG_GRAVEYARD_MAX] = { { 5104.750f, 2300.940f, 368.579f, 0.733038f, 1329, BATTLEFIELD_WG_GY_WORKSHOP_NE, BATTLEFIELD_WG_GOSSIPTEXT_GY_NE, TEAM_NEUTRAL }, { 5099.120f, 3466.036f, 368.484f, 5.317802f, 1330, BATTLEFIELD_WG_GY_WORKSHOP_NW, BATTLEFIELD_WG_GOSSIPTEXT_GY_NW, TEAM_NEUTRAL }, @@ -403,7 +404,7 @@ public: void SendInitWorldStatesTo(Player* player); void SendInitWorldStatesToAll() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void HandleKill(Player* killer, Unit* victim) override; void OnUnitDeath(Unit* unit) override; diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp index dc200abda..2fd0f863d 100644 --- a/src/server/game/Battlegrounds/Arena.cpp +++ b/src/server/game/Battlegrounds/Arena.cpp @@ -26,7 +26,7 @@ #include "World.h" #include "WorldSession.h" #include "WorldSessionMgr.h" -//#include "WorldStatePackets.h" +#include "WorldStatePackets.h" void ArenaScore::AppendToPacket(WorldPacket& data) { @@ -147,10 +147,11 @@ void Arena::RemovePlayer(Player* /*player*/) CheckWinConditions(); } -void Arena::FillInitialWorldStates(WorldPacket& data) +void Arena::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN) << uint32(GetAlivePlayersCountByTeam(TEAM_HORDE)); - data << uint32(ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD) << uint32(GetAlivePlayersCountByTeam(TEAM_ALLIANCE)); + packet.Worldstates.reserve(2); + packet.Worldstates.emplace_back(ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN, GetAlivePlayersCountByTeam(TEAM_HORDE)); + packet.Worldstates.emplace_back(ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD, GetAlivePlayersCountByTeam(TEAM_ALLIANCE)); } void Arena::UpdateArenaWorldState() diff --git a/src/server/game/Battlegrounds/Arena.h b/src/server/game/Battlegrounds/Arena.h index fd7460080..346d30e7a 100644 --- a/src/server/game/Battlegrounds/Arena.h +++ b/src/server/game/Battlegrounds/Arena.h @@ -52,7 +52,7 @@ protected: void AddPlayer(Player* player) override; void RemovePlayer(Player* /*player*/) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void UpdateArenaWorldState(); void HandleKillPlayer(Player* player, Player* killer) override; diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 2a9e85e0f..5e1d00f9a 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -24,6 +24,7 @@ #include "GameObject.h" #include "SharedDefines.h" #include "World.h" +#include "WorldStatePackets.h" class Creature; class GameObject; @@ -457,7 +458,7 @@ public: // Packet Transfer // method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!) - virtual void FillInitialWorldStates(WorldPacket& /*data*/) { } + virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) { } void SendPacketToTeam(TeamId teamId, WorldPacket const* packet, Player* sender = nullptr, bool self = true); void SendPacketToAll(WorldPacket const* packet); void YellToAll(Creature* creature, const char* text, uint32 language); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 4cc94a60d..b9064de35 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -23,6 +23,7 @@ #include "Util.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldStatePackets.h" void BattlegroundABScore::BuildObjectivesBlock(WorldPacket& data) { @@ -234,24 +235,26 @@ void BattlegroundAB::DeleteBanner(uint8 node) SpawnBGObject(node * BG_AB_OBJECTS_PER_NODE + BG_AB_OBJECT_AURA_ALLY + _capturePointInfo[node]._ownerTeamId, RESPAWN_ONE_DAY); } -void BattlegroundAB::FillInitialWorldStates(WorldPacket& data) +void BattlegroundAB::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { + packet.Worldstates.reserve(BG_AB_DYNAMIC_NODES_COUNT+7); for (auto& node : _capturePointInfo) { if (node._state == BG_AB_NODE_STATE_NEUTRAL) - data << uint32(node._iconNone) << uint32(1); + packet.Worldstates.emplace_back(node._iconNone, 1); for (uint8 i = BG_AB_NODE_STATE_ALLY_OCCUPIED; i <= BG_AB_NODE_STATE_HORDE_CONTESTED; ++i) - data << uint32(node._iconCapture + i - 1) << uint32(node._state == i); + packet.Worldstates.emplace_back(node._iconCapture + i - 1, node._state == i ? 1 : 0); + } - data << uint32(BG_AB_OP_OCCUPIED_BASES_ALLY) << uint32(_controlledPoints[TEAM_ALLIANCE]); - data << uint32(BG_AB_OP_OCCUPIED_BASES_HORDE) << uint32(_controlledPoints[TEAM_HORDE]); - data << uint32(BG_AB_OP_RESOURCES_MAX) << uint32(BG_AB_MAX_TEAM_SCORE); - data << uint32(BG_AB_OP_RESOURCES_WARNING) << uint32(BG_AB_WARNING_NEAR_VICTORY_SCORE); - data << uint32(BG_AB_OP_RESOURCES_ALLY) << uint32(m_TeamScores[TEAM_ALLIANCE]); - data << uint32(BG_AB_OP_RESOURCES_HORDE) << uint32(m_TeamScores[TEAM_HORDE]); - data << uint32(0x745) << uint32(0x2); // 37 1861 unk + packet.Worldstates.emplace_back(BG_AB_OP_OCCUPIED_BASES_ALLY, _controlledPoints[TEAM_ALLIANCE]); + packet.Worldstates.emplace_back(BG_AB_OP_OCCUPIED_BASES_HORDE, _controlledPoints[TEAM_HORDE]); + packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_MAX, BG_AB_MAX_TEAM_SCORE); + packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_WARNING, BG_AB_WARNING_NEAR_VICTORY_SCORE); + packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_ALLY, m_TeamScores[TEAM_ALLIANCE]); + packet.Worldstates.emplace_back(BG_AB_OP_RESOURCES_HORDE, m_TeamScores[TEAM_HORDE]); + packet.Worldstates.emplace_back(0x745, 2); } void BattlegroundAB::SendNodeUpdate(uint8 node) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h index 403664faf..b63b9fae9 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h @@ -304,7 +304,7 @@ public: GraveyardStruct const* GetClosestGraveyard(Player* player) override; bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void EventPlayerClickedOnFlag(Player* source, GameObject* gameObject) override; bool AllNodesConrolledByTeam(TeamId teamId) const override; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index a5e246dae..f4c601fa8 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -25,6 +25,7 @@ #include "Player.h" #include "SpellAuras.h" #include "WorldPacket.h" +#include "WorldStatePackets.h" void BattlegroundAVScore::BuildObjectivesBlock(WorldPacket& data) { @@ -1084,9 +1085,10 @@ void BattlegroundAV::EventPlayerAssaultsPoint(Player* player, uint32 object) player->KilledMonsterCredit((IsTower(node)) ? BG_AV_QUEST_CREDIT_TOWER : BG_AV_QUEST_CREDIT_GRAVEYARD); } -void BattlegroundAV::FillInitialWorldStates(WorldPacket& data) +void BattlegroundAV::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { bool stateok; + packet.Worldstates.reserve(7*2*2 + 8*2*2 + 5); //graveyards for (uint8 i = BG_AV_NODES_FIRSTAID_STATION; i <= BG_AV_NODES_FROSTWOLF_HUT; i++) { @@ -1094,8 +1096,8 @@ void BattlegroundAV::FillInitialWorldStates(WorldPacket& data) { //j=1=assaulted j=3=controled stateok = (m_Nodes[i].State == j); - data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)]) << uint32((m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0); - data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)]) << uint32((m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0); + packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)], (m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0); + packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)], (m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0); } } @@ -1105,23 +1107,19 @@ void BattlegroundAV::FillInitialWorldStates(WorldPacket& data) { //j=1=assaulted j=3=controled //i dont have j=2=destroyed cause destroyed is the same like enemy-team controll stateok = (m_Nodes[i].State == j || (m_Nodes[i].State == POINT_DESTROYED && j == 3)); - data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)]) << uint32((m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0); - data << uint32(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)]) << uint32((m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0); + packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_ALLIANCE)], (m_Nodes[i].OwnerId == TEAM_ALLIANCE && stateok) ? 1 : 0); + packet.Worldstates.emplace_back(BG_AV_NodeWorldStates[i][GetWorldStateType(j, TEAM_HORDE)], (m_Nodes[i].OwnerId == TEAM_HORDE && stateok) ? 1 : 0); } if (m_Nodes[BG_AV_NODES_SNOWFALL_GRAVE].OwnerId == TEAM_NEUTRAL) //cause neutral teams aren't handled generic - data << uint32(AV_SNOWFALL_N) << uint32(1); - data << uint32(AV_Alliance_Score) << uint32(m_Team_Scores[0]); - data << uint32(AV_Horde_Score) << uint32(m_Team_Scores[1]); - if (GetStatus() == STATUS_IN_PROGRESS) //only if game started the teamscores are displayed { - data << uint32(AV_SHOW_A_SCORE) << uint32(1); - data << uint32(AV_SHOW_H_SCORE) << uint32(1); - } - else - { - data << uint32(AV_SHOW_A_SCORE) << uint32(0); - data << uint32(AV_SHOW_H_SCORE) << uint32(0); + packet.Worldstates.emplace_back(AV_SNOWFALL_N, 1); } + packet.Worldstates.emplace_back(AV_Alliance_Score, m_Team_Scores[0]); + packet.Worldstates.emplace_back(AV_Horde_Score, m_Team_Scores[1]); + + packet.Worldstates.emplace_back(AV_SHOW_A_SCORE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0); + packet.Worldstates.emplace_back(AV_SHOW_H_SCORE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0); + SendMineWorldStates(AV_NORTH_MINE); SendMineWorldStates(AV_SOUTH_MINE); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h index 2af1c50b6..e0195206a 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h @@ -1936,7 +1936,7 @@ private: void ChangeMineOwner(uint8 mine, TeamId teamId, bool initial = false); /*worldstates*/ - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; uint8 GetWorldStateType(uint8 state, TeamId teamId); void SendMineWorldStates(uint32 mine); void UpdateNodeWorldState(BG_AV_Nodes node); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp index 4acc4fafe..ce210aa60 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp @@ -19,6 +19,7 @@ #include "Log.h" #include "Player.h" #include "WorldPacket.h" +#include "WorldStatePackets.h" BattlegroundBE::BattlegroundBE() { @@ -87,10 +88,10 @@ void BattlegroundBE::HandleAreaTrigger(Player* player, uint32 trigger) } } -void BattlegroundBE::FillInitialWorldStates(WorldPacket& data) +void BattlegroundBE::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(0x9f3) << uint32(1); // 9 - Arena::FillInitialWorldStates(data); + packet.Worldstates.emplace_back(0x9f3, 1); // BATTLEGROUND_BLADES_EDGE_ARENA_SHOW + Arena::FillInitialWorldStates(packet); } bool BattlegroundBE::SetupBattleground() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.h b/src/server/game/Battlegrounds/Zones/BattlegroundBE.h index 9d7790d9b..77d5c3423 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.h @@ -54,7 +54,7 @@ public: void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void FillInitialWorldStates(WorldPacket& d) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; bool HandlePlayerUnderMap(Player* player) override; }; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp index 53d4b3314..5a91f57ac 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp @@ -22,6 +22,7 @@ #include "ObjectAccessor.h" #include "Player.h" #include "WorldPacket.h" +#include "WorldStatePackets.h" BattlegroundDS::BattlegroundDS() { @@ -173,10 +174,10 @@ bool BattlegroundDS::HandlePlayerUnderMap(Player* player) return true; } -void BattlegroundDS::FillInitialWorldStates(WorldPacket& data) +void BattlegroundDS::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(3610) << uint32(1); // 9 show - Arena::FillInitialWorldStates(data); + packet.Worldstates.emplace_back(0xe1a, 1); // ARENA_WORLD_STATE_ALIVE_PLAYERS_SHOW + Arena::FillInitialWorldStates(packet); } bool BattlegroundDS::SetupBattleground() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h index 3ff673154..2c8340f70 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h @@ -101,7 +101,7 @@ public: void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void FillInitialWorldStates(WorldPacket& d) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; bool HandlePlayerUnderMap(Player* player) override; private: diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index 226bcf709..8cf1f7813 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -26,6 +26,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldStatePackets.h" void BattlegroundEYScore::BuildObjectivesBlock(WorldPacket& data) { @@ -506,7 +507,7 @@ void BattlegroundEY::EventTeamCapturedPoint(Player* player, TeamId teamId, uint3 _capturePointInfo[point]._ownerTeamId = teamId; - GraveyardStruct const* sg = sGraveyard->GetGraveyard(m_CapturingPointTypes[point].GraveYardId); + GraveyardStruct const* sg = sGraveyard->GetGraveyard(m_CapturingPointTypes[point].GraveyardId); AddSpiritGuide(point, sg->x, sg->y, sg->z, 3.124139f, teamId); UpdatePointsIcons(point); @@ -568,30 +569,31 @@ bool BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value return true; } -void BattlegroundEY::FillInitialWorldStates(WorldPacket& data) +void BattlegroundEY::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(EY_HORDE_BASE) << uint32(_ownedPointsCount[TEAM_HORDE]); - data << uint32(EY_ALLIANCE_BASE) << uint32(_ownedPointsCount[TEAM_ALLIANCE]); - data << uint32(DRAENEI_RUINS_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_HORDE)); - data << uint32(DRAENEI_RUINS_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_ALLIANCE)); - data << uint32(DRAENEI_RUINS_UNCONTROL) << uint32(_capturePointInfo[POINT_DRAENEI_RUINS].IsUncontrolled()); - data << uint32(MAGE_TOWER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_HORDE)); - data << uint32(MAGE_TOWER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_ALLIANCE)); - data << uint32(MAGE_TOWER_UNCONTROL) << uint32(_capturePointInfo[POINT_MAGE_TOWER].IsUncontrolled()); - data << uint32(FEL_REAVER_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_HORDE)); - data << uint32(FEL_REAVER_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_ALLIANCE)); - data << uint32(FEL_REAVER_UNCONTROL) << uint32(_capturePointInfo[POINT_FEL_REAVER].IsUncontrolled()); - data << uint32(BLOOD_ELF_HORDE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_HORDE)); - data << uint32(BLOOD_ELF_ALLIANCE_CONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_ALLIANCE)); - data << uint32(BLOOD_ELF_UNCONTROL) << uint32(_capturePointInfo[POINT_BLOOD_ELF].IsUncontrolled()); - data << uint32(NETHERSTORM_FLAG) << uint32(_flagState == BG_EY_FLAG_STATE_ON_BASE); - data << uint32(NETHERSTORM_FLAG_STATE_HORDE) << uint32(1); - data << uint32(NETHERSTORM_FLAG_STATE_ALLIANCE) << uint32(1); - data << uint32(EY_HORDE_RESOURCES) << uint32(GetTeamScore(TEAM_HORDE)); - data << uint32(EY_ALLIANCE_RESOURCES) << uint32(GetTeamScore(TEAM_ALLIANCE)); - data << uint32(PROGRESS_BAR_SHOW) << uint32(0); - data << uint32(PROGRESS_BAR_PERCENT_GREY) << uint32(0); - data << uint32(PROGRESS_BAR_STATUS) << uint32(0); + packet.Worldstates.reserve(22); + packet.Worldstates.emplace_back(EY_HORDE_BASE, _ownedPointsCount[TEAM_HORDE]); + packet.Worldstates.emplace_back(EY_ALLIANCE_BASE, _ownedPointsCount[TEAM_ALLIANCE]); + packet.Worldstates.emplace_back(DRAENEI_RUINS_HORDE_CONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_HORDE)); + packet.Worldstates.emplace_back(DRAENEI_RUINS_ALLIANCE_CONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUnderControl(TEAM_ALLIANCE)); + packet.Worldstates.emplace_back(DRAENEI_RUINS_UNCONTROL, _capturePointInfo[POINT_DRAENEI_RUINS].IsUncontrolled()); + packet.Worldstates.emplace_back(MAGE_TOWER_ALLIANCE_CONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_HORDE)); + packet.Worldstates.emplace_back(MAGE_TOWER_HORDE_CONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUnderControl(TEAM_ALLIANCE)); + packet.Worldstates.emplace_back(MAGE_TOWER_UNCONTROL, _capturePointInfo[POINT_MAGE_TOWER].IsUncontrolled()); + packet.Worldstates.emplace_back(FEL_REAVER_HORDE_CONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_HORDE)); + packet.Worldstates.emplace_back(FEL_REAVER_ALLIANCE_CONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUnderControl(TEAM_ALLIANCE)); + packet.Worldstates.emplace_back(FEL_REAVER_UNCONTROL, _capturePointInfo[POINT_FEL_REAVER].IsUncontrolled()); + packet.Worldstates.emplace_back(BLOOD_ELF_HORDE_CONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_HORDE)); + packet.Worldstates.emplace_back(BLOOD_ELF_ALLIANCE_CONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUnderControl(TEAM_ALLIANCE)); + packet.Worldstates.emplace_back(BLOOD_ELF_UNCONTROL, _capturePointInfo[POINT_BLOOD_ELF].IsUncontrolled()); + packet.Worldstates.emplace_back(NETHERSTORM_FLAG, _flagState == BG_EY_FLAG_STATE_ON_BASE); + packet.Worldstates.emplace_back(NETHERSTORM_FLAG_STATE_HORDE, 1); + packet.Worldstates.emplace_back(NETHERSTORM_FLAG_STATE_ALLIANCE, 1); + packet.Worldstates.emplace_back(EY_HORDE_RESOURCES, GetTeamScore(TEAM_HORDE)); + packet.Worldstates.emplace_back(EY_ALLIANCE_RESOURCES, GetTeamScore(TEAM_ALLIANCE)); + packet.Worldstates.emplace_back(PROGRESS_BAR_SHOW, 0); + packet.Worldstates.emplace_back(PROGRESS_BAR_PERCENT_GREY, 0); + packet.Worldstates.emplace_back(PROGRESS_BAR_STATUS, 0); } GraveyardStruct const* BattlegroundEY::GetClosestGraveyard(Player* player) @@ -608,7 +610,7 @@ GraveyardStruct const* BattlegroundEY::GetClosestGraveyard(Player* player) for (uint8 i = 0; i < EY_POINTS_MAX; ++i) if (_capturePointInfo[i].IsUnderControl(player->GetTeamId())) { - entry = sGraveyard->GetGraveyard(m_CapturingPointTypes[i].GraveYardId); + entry = sGraveyard->GetGraveyard(m_CapturingPointTypes[i].GraveyardId); dist = (entry->x - pX) * (entry->x - pX) + (entry->y - pY) * (entry->y - pY) + (entry->z - pZ) * (entry->z - pZ); if (dist < minDist) { diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h index 936e9e9b5..acd51fddc 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h @@ -305,11 +305,11 @@ struct BattlegroundEYLosingPointStruct struct BattlegroundEYCapturingPointStruct { - BattlegroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveYardId) + BattlegroundEYCapturingPointStruct(uint32 _DespawnNeutralObjectType, uint32 _SpawnObjectTypeAlliance, uint32 _MessageIdAlliance, uint32 _SpawnObjectTypeHorde, uint32 _MessageIdHorde, uint32 _GraveyardId) : DespawnNeutralObjectType(_DespawnNeutralObjectType), SpawnObjectTypeAlliance(_SpawnObjectTypeAlliance), MessageIdAlliance(_MessageIdAlliance), SpawnObjectTypeHorde(_SpawnObjectTypeHorde), MessageIdHorde(_MessageIdHorde), - GraveYardId(_GraveYardId) + GraveyardId(_GraveyardId) {} uint32 DespawnNeutralObjectType; @@ -317,7 +317,7 @@ struct BattlegroundEYCapturingPointStruct uint32 MessageIdAlliance; uint32 SpawnObjectTypeHorde; uint32 MessageIdHorde; - uint32 GraveYardId; + uint32 GraveyardId; }; const uint32 BG_EY_TickPoints[EY_POINTS_MAX] = {1, 2, 5, 10}; @@ -402,7 +402,7 @@ public: void Init() override; void EndBattleground(TeamId winnerTeamId) override; bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void SetDroppedFlagGUID(ObjectGuid guid, TeamId /*teamId*/ = TEAM_NEUTRAL) override { _droppedFlagGUID = guid; } ObjectGuid GetDroppedFlagGUID() const { return _droppedFlagGUID; } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index 205323289..e9957a17f 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -26,6 +26,7 @@ #include "Transport.h" #include "Vehicle.h" #include "WorldPacket.h" +#include "WorldStatePackets.h" void BattlegroundICScore::BuildObjectivesBlock(WorldPacket& data) { @@ -381,21 +382,24 @@ bool BattlegroundIC::UpdatePlayerScore(Player* player, uint32 type, uint32 value return true; } -void BattlegroundIC::FillInitialWorldStates(WorldPacket& data) +void BattlegroundIC::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(BG_IC_ALLIANCE_RENFORT_SET) << uint32(1); - data << uint32(BG_IC_HORDE_RENFORT_SET) << uint32(1); - data << uint32(BG_IC_ALLIANCE_RENFORT) << uint32(factionReinforcements[TEAM_ALLIANCE]); - data << uint32(BG_IC_HORDE_RENFORT) << uint32(factionReinforcements[TEAM_HORDE]); + packet.Worldstates.reserve(4+MAX_FORTRESS_GATES_SPAWNS+MAX_NODE_TYPES+1); + packet.Worldstates.emplace_back(BG_IC_ALLIANCE_RENFORT_SET, 1); + packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT_SET, 1); + packet.Worldstates.emplace_back(BG_IC_ALLIANCE_RENFORT, factionReinforcements[TEAM_ALLIANCE]); + packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT, factionReinforcements[TEAM_HORDE]); for (uint8 i = 0; i < MAX_FORTRESS_GATES_SPAWNS; ++i) { uint32 uws = GetWorldStateFromGateEntry(BG_IC_ObjSpawnlocs[i].entry, (GateStatus[GetGateIDFromEntry(BG_IC_ObjSpawnlocs[i].entry)] == BG_IC_GATE_DESTROYED)); - data << uint32(uws) << uint32(1); + packet.Worldstates.emplace_back(uws, 1); } for (uint8 i = 0; i < MAX_NODE_TYPES; ++i) - data << uint32(nodePoint[i].worldStates[nodePoint[i].nodeState]) << uint32(1); + packet.Worldstates.emplace_back(nodePoint[i].worldStates[nodePoint[i].nodeState], 1); + + packet.Worldstates.emplace_back(BG_IC_HORDE_RENFORT_SET, 1); } bool BattlegroundIC::SetupBattleground() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h index 6a6b40188..a067b794a 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h @@ -974,7 +974,7 @@ public: /* Scorekeeping */ bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void HandlePlayerResurrect(Player* player) override; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp index 36a55b71c..f2585d387 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp @@ -64,10 +64,10 @@ void BattlegroundNA::HandleAreaTrigger(Player* player, uint32 trigger) } } -void BattlegroundNA::FillInitialWorldStates(WorldPacket& data) +void BattlegroundNA::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(0xa11) << uint32(1); // 9 - Arena::FillInitialWorldStates(data); + packet.Worldstates.emplace_back(0xa11, 1); // BATTLEGROUND_NAGRAND_ARENA_SHOW + Arena::FillInitialWorldStates(packet); } bool BattlegroundNA::SetupBattleground() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.h b/src/server/game/Battlegrounds/Zones/BattlegroundNA.h index c13eb9d6d..e75b30d22 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.h @@ -54,7 +54,8 @@ public: void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; - void FillInitialWorldStates(WorldPacket& d) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; + bool HandlePlayerUnderMap(Player* player) override; }; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp index 483d5a9c3..a8447a953 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp @@ -91,10 +91,10 @@ void BattlegroundRL::HandleAreaTrigger(Player* player, uint32 trigger) } } -void BattlegroundRL::FillInitialWorldStates(WorldPacket& data) +void BattlegroundRL::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(0xbba) << uint32(1); // 9 - Arena::FillInitialWorldStates(data); + packet.Worldstates.emplace_back(0xbba, 1); // BATTELGROUND_RUINS_OF_LORDAERNON_SHOW + Arena::FillInitialWorldStates(packet); } bool BattlegroundRL::SetupBattleground() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.h b/src/server/game/Battlegrounds/Zones/BattlegroundRL.h index 81174f9db..bfcf6f5ff 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.h @@ -45,7 +45,7 @@ public: BattlegroundRL(); /* inherited from BattlegroundClass */ - void FillInitialWorldStates(WorldPacket& d) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void StartingEventCloseDoors() override; void StartingEventOpenDoors() override; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp index 4eccb3cf0..faae3a2ed 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp @@ -204,10 +204,10 @@ void BattlegroundRV::HandleAreaTrigger(Player* player, uint32 trigger) } } -void BattlegroundRV::FillInitialWorldStates(WorldPacket& data) +void BattlegroundRV::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(BG_RV_WORLD_STATE) << uint32(1); - Arena::FillInitialWorldStates(data); + packet.Worldstates.emplace_back(BG_RV_WORLD_STATE, 1); + Arena::FillInitialWorldStates(packet); } void BattlegroundRV::Init() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.h b/src/server/game/Battlegrounds/Zones/BattlegroundRV.h index 5845b52dd..5596723ff 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.h @@ -90,7 +90,7 @@ public: /* inherited from BattlegroundClass */ void StartingEventOpenDoors() override; void Init() override; - void FillInitialWorldStates(WorldPacket& d) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void HandleAreaTrigger(Player* player, uint32 trigger) override; bool SetupBattleground() override; bool HandlePlayerUnderMap(Player* player) override; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp index 443a8a46c..0d6e80804 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp @@ -467,44 +467,46 @@ void BattlegroundSA::StartingEventOpenDoors() { } -void BattlegroundSA::FillInitialWorldStates(WorldPacket& data) +void BattlegroundSA::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - uint32 ally_attacks = uint32(Attackers == TEAM_ALLIANCE ? 1 : 0); - uint32 horde_attacks = uint32(Attackers == TEAM_HORDE ? 1 : 0); + bool const ally_attacks = Attackers == TEAM_ALLIANCE; + bool const horde_attacks = Attackers == TEAM_HORDE; - data << uint32(BG_SA_ANCIENT_GATEWS) << uint32(GateStatus[BG_SA_ANCIENT_GATE]); - data << uint32(BG_SA_YELLOW_GATEWS) << uint32(GateStatus[BG_SA_YELLOW_GATE]); - data << uint32(BG_SA_GREEN_GATEWS) << uint32(GateStatus[BG_SA_GREEN_GATE]); - data << uint32(BG_SA_BLUE_GATEWS) << uint32(GateStatus[BG_SA_BLUE_GATE]); - data << uint32(BG_SA_RED_GATEWS) << uint32(GateStatus[BG_SA_RED_GATE]); - data << uint32(BG_SA_PURPLE_GATEWS) << uint32(GateStatus[BG_SA_PURPLE_GATE]); + packet.Worldstates.reserve(25); + packet.Worldstates.emplace_back(BG_SA_ANCIENT_GATEWS, GateStatus[BG_SA_ANCIENT_GATE]); + packet.Worldstates.emplace_back(BG_SA_YELLOW_GATEWS, GateStatus[BG_SA_YELLOW_GATE]); + packet.Worldstates.emplace_back(BG_SA_GREEN_GATEWS, GateStatus[BG_SA_GREEN_GATE]); + packet.Worldstates.emplace_back(BG_SA_BLUE_GATEWS, GateStatus[BG_SA_BLUE_GATE]); + packet.Worldstates.emplace_back(BG_SA_RED_GATEWS, GateStatus[BG_SA_RED_GATE]); + packet.Worldstates.emplace_back(BG_SA_PURPLE_GATEWS, GateStatus[BG_SA_PURPLE_GATE]); - data << uint32(BG_SA_BONUS_TIMER) << uint32(0); + packet.Worldstates.emplace_back(BG_SA_BONUS_TIMER, 0); - data << uint32(BG_SA_HORDE_ATTACKS) << horde_attacks; - data << uint32(BG_SA_ALLY_ATTACKS) << ally_attacks; + packet.Worldstates.emplace_back(BG_SA_HORDE_ATTACKS, horde_attacks); + packet.Worldstates.emplace_back(BG_SA_ALLY_ATTACKS, ally_attacks); //Time will be sent on first update... - data << uint32(BG_SA_ENABLE_TIMER) << ((TimerEnabled) ? uint32(1) : uint32(0)); - data << uint32(BG_SA_TIMER_MINS) << uint32(0); - data << uint32(BG_SA_TIMER_SEC_TENS) << uint32(0); - data << uint32(BG_SA_TIMER_SEC_DECS) << uint32(0); + packet.Worldstates.emplace_back(BG_SA_ENABLE_TIMER, TimerEnabled ? 1 : 0); - data << uint32(BG_SA_RIGHT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); - data << uint32(BG_SA_LEFT_GY_HORDE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); - data << uint32(BG_SA_CENTER_GY_HORDE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); + packet.Worldstates.emplace_back(BG_SA_TIMER_MINS, 0); + packet.Worldstates.emplace_back(BG_SA_TIMER_SEC_TENS, 0); + packet.Worldstates.emplace_back(BG_SA_TIMER_SEC_DECS, 0); - data << uint32(BG_SA_RIGHT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); - data << uint32(BG_SA_LEFT_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); - data << uint32(BG_SA_CENTER_GY_ALLIANCE) << uint32(GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); + packet.Worldstates.emplace_back(BG_SA_RIGHT_GY_HORDE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); + packet.Worldstates.emplace_back(BG_SA_LEFT_GY_HORDE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); + packet.Worldstates.emplace_back(BG_SA_CENTER_GY_HORDE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_HORDE ? 1 : 0); - data << uint32(BG_SA_HORDE_DEFENCE_TOKEN) << ally_attacks; - data << uint32(BG_SA_ALLIANCE_DEFENCE_TOKEN) << horde_attacks; + packet.Worldstates.emplace_back(BG_SA_RIGHT_GY_ALLIANCE, GraveyardStatus[BG_SA_RIGHT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); + packet.Worldstates.emplace_back(BG_SA_LEFT_GY_ALLIANCE, GraveyardStatus[BG_SA_LEFT_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); + packet.Worldstates.emplace_back(BG_SA_CENTER_GY_ALLIANCE, GraveyardStatus[BG_SA_CENTRAL_CAPTURABLE_GY] == TEAM_ALLIANCE ? 1 : 0); - data << uint32(BG_SA_LEFT_ATT_TOKEN_HRD) << horde_attacks; - data << uint32(BG_SA_RIGHT_ATT_TOKEN_HRD) << horde_attacks; - data << uint32(BG_SA_RIGHT_ATT_TOKEN_ALL) << ally_attacks; - data << uint32(BG_SA_LEFT_ATT_TOKEN_ALL) << ally_attacks; + packet.Worldstates.emplace_back(BG_SA_HORDE_DEFENCE_TOKEN, ally_attacks); + packet.Worldstates.emplace_back(BG_SA_ALLIANCE_DEFENCE_TOKEN, horde_attacks); + + packet.Worldstates.emplace_back(BG_SA_LEFT_ATT_TOKEN_HRD, horde_attacks); + packet.Worldstates.emplace_back(BG_SA_RIGHT_ATT_TOKEN_HRD, horde_attacks); + packet.Worldstates.emplace_back(BG_SA_RIGHT_ATT_TOKEN_ALL, ally_attacks); + packet.Worldstates.emplace_back(BG_SA_LEFT_ATT_TOKEN_ALL, ally_attacks); } void BattlegroundSA::AddPlayer(Player* player) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h index 4e0832a23..e816ad1cb 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h @@ -475,7 +475,7 @@ public: bool SetupBattleground() override; void Init() override; /// Called for generate packet contain worldstate data - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; /// Called when a player deal damage to building (door) void EventPlayerDamagedGO(Player* player, GameObject* go, uint32 eventType) override; /// Called when a player kill a unit in bg diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 1f84f6f6f..64f30a7a0 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -546,17 +546,18 @@ GraveyardStruct const* BattlegroundWS::GetClosestGraveyard(Player* player) return sGraveyard->GetGraveyard(player->GetTeamId() == TEAM_ALLIANCE ? WS_GRAVEYARD_FLAGROOM_ALLIANCE : WS_GRAVEYARD_FLAGROOM_HORDE); } -void BattlegroundWS::FillInitialWorldStates(WorldPacket& data) +void BattlegroundWS::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(BG_WS_FLAG_CAPTURES_ALLIANCE) << uint32(GetTeamScore(TEAM_ALLIANCE)); - data << uint32(BG_WS_FLAG_CAPTURES_HORDE) << uint32(GetTeamScore(TEAM_HORDE)); - data << uint32(BG_WS_FLAG_CAPTURES_MAX) << uint32(BG_WS_MAX_TEAM_SCORE); + packet.Worldstates.reserve(7); + packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_ALLIANCE, GetTeamScore(TEAM_ALLIANCE)); + packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_HORDE, GetTeamScore(TEAM_HORDE)); + packet.Worldstates.emplace_back(BG_WS_FLAG_CAPTURES_MAX, BG_WS_MAX_TEAM_SCORE); - data << uint32(BG_WS_STATE_TIMER_ACTIVE) << uint32(GetStatus() == STATUS_IN_PROGRESS); - data << uint32(BG_WS_STATE_TIMER) << uint32(GetMatchTime()); + packet.Worldstates.emplace_back(BG_WS_STATE_TIMER_ACTIVE, GetStatus() == STATUS_IN_PROGRESS ? 1 : 0); + packet.Worldstates.emplace_back(BG_WS_STATE_TIMER, GetMatchTime()); - data << uint32(BG_WS_FLAG_STATE_HORDE) << uint32(GetFlagState(TEAM_HORDE)); - data << uint32(BG_WS_FLAG_STATE_ALLIANCE) << uint32(GetFlagState(TEAM_ALLIANCE)); + packet.Worldstates.emplace_back(BG_WS_FLAG_STATE_HORDE, GetFlagState(TEAM_HORDE)); + packet.Worldstates.emplace_back(BG_WS_FLAG_STATE_ALLIANCE, GetFlagState(TEAM_ALLIANCE)); } TeamId BattlegroundWS::GetPrematureWinner() diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h index 1620ca1fd..5b97d5d39 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h @@ -252,7 +252,7 @@ public: bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; void SetDroppedFlagGUID(ObjectGuid guid, TeamId teamId) override { _droppedFlagGUID[teamId] = guid; } ObjectGuid GetDroppedFlagGUID(TeamId teamId) const { return _droppedFlagGUID[teamId];} - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; /* Scorekeeping */ void AddPoints(TeamId teamId, uint32 points) { m_TeamScores[teamId] += points; } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b875c363d..9aeda887c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -86,6 +86,7 @@ #include "WorldSession.h" #include "WorldSessionMgr.h" #include "WorldState.h" +#include "WorldStatePackets.h" #include /// @todo: this import is not necessary for compilation and marked as unused by the IDE @@ -8221,643 +8222,667 @@ void Player::SendNotifyLootItemRemoved(uint8 lootSlot) GetSession()->SendPacket(&data); } -void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) +// TODO - InitWorldStates should NOT always send the same states +// Some should keep the same value between different zoneIds and areaIds on the same map +void Player::SendInitWorldStates(uint32 zoneId, uint32 areaId) { // data depends on zoneid/mapid... - Battleground* bg = GetBattleground(); - uint32 mapid = GetMapId(); - OutdoorPvP* pvp = sOutdoorPvPMgr->GetOutdoorPvPToZoneId(zoneid); + uint32 mapId = GetMapId(); + Battleground* battleground = GetBattleground(); + OutdoorPvP* outdoorPvP = sOutdoorPvPMgr->GetOutdoorPvPToZoneId(zoneId); InstanceScript* instance = GetInstanceScript(); - Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(zoneid); + Battlefield* battlefield = sBattlefieldMgr->GetBattlefieldToZoneId(zoneId); - LOG_DEBUG("network", "Sending SMSG_INIT_WORLD_STATES to Map: {}, Zone: {}", mapid, zoneid); + LOG_DEBUG("network", "Sending SMSG_INIT_WORLD_STATES to Map: {}, Zone: {}", mapId, zoneId); + + WorldPackets::WorldState::InitWorldStates packet; + packet.MapID = mapId; + packet.ZoneID = zoneId; + packet.AreaID = areaId; + + packet.Worldstates.reserve(8); + packet.Worldstates.emplace_back(0x8d8, 0); // SCOURGE_EVENT_WORLDSTATE_EASTERN_PLAGUELANDS + packet.Worldstates.emplace_back(0x8d7, 0); // SCOURGE_EVENT_WORLDSTATE_TANARIS + packet.Worldstates.emplace_back(0x8d6, 0); // SCOURGE_EVENT_WORLDSTATE_BURNING_STEPPES + packet.Worldstates.emplace_back(0x8d5, 0); // SCOURGE_EVENT_WORLDSTATE_BLASTED_LANDS + packet.Worldstates.emplace_back(0x8d4, 0); // SCOURGE_EVENT_WORLDSTATE_AZSHARA + packet.Worldstates.emplace_back(0x8d3, 0); // SCOURGE_EVENT_WORLDSTATE_WINTERSPRING - WorldPacket data(SMSG_INIT_WORLD_STATES, (4 + 4 + 4 + 2 + (12 * 8))); - data << uint32(mapid); // mapid - data << uint32(zoneid); // zone id - data << uint32(areaid); // area id, new 2.1.0 - std::size_t countPos = data.wpos(); - data << uint16(0); // count of uint64 blocks - data << uint32(0x8d8) << uint32(0x0); // 1 - data << uint32(0x8d7) << uint32(0x0); // 2 - data << uint32(0x8d6) << uint32(0x0); // 3 - data << uint32(0x8d5) << uint32(0x0); // 4 - data << uint32(0x8d4) << uint32(0x0); // 5 - data << uint32(0x8d3) << uint32(0x0); // 6 // 7 1 - Arena season in progress, 0 - end of season - data << uint32(0xC77) << uint32(sArenaSeasonMgr->GetSeasonState() == ARENA_SEASON_STATE_IN_PROGRESS); + packet.Worldstates.emplace_back(0xc77, sArenaSeasonMgr->GetSeasonState() == ARENA_SEASON_STATE_IN_PROGRESS); // 8 Arena season id - data << uint32(0xF3D) << uint32(sArenaSeasonMgr->GetCurrentSeason()); + packet.Worldstates.emplace_back(0xf3d, sArenaSeasonMgr->GetCurrentSeason()); - if (mapid == 530) // Outland + if (mapId == 530) // Outland { - data << uint32(0x9bf) << uint32(0x0); // 7 - data << uint32(0x9bd) << uint32(0xF); // 8 - data << uint32(0x9bb) << uint32(0xF); // 9 + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0x9bf, 0); // NA_UI_OUTLAND_01 "Progress: %2494w" + packet.Worldstates.emplace_back(0x9bd, 15); // NA_UI_GUARDS_MAX + packet.Worldstates.emplace_back(0x9bb, 15); // NA_UI_GUARDS_LEFT } - if (Player::bgZoneIdToFillWorldStates.find(zoneid) != Player::bgZoneIdToFillWorldStates.end()) + if (Player::bgZoneIdToFillWorldStates.find(zoneId) != Player::bgZoneIdToFillWorldStates.end()) { - Player::bgZoneIdToFillWorldStates[zoneid](bg, data); + Player::bgZoneIdToFillWorldStates[zoneId](battleground, packet); } else { // insert - switch (zoneid) + switch (zoneId) { - case 1: // Dun Morogh - case 11: // Wetlands - case 12: // Elwynn Forest - case 38: // Loch Modan - case 40: // Westfall - case 51: // Searing Gorge - case 1519: // Stormwind City - case 1537: // Ironforge - case 2257: // Deeprun Tram - case 3703: // Shattrath City + case 1: // Dun Morogh + case 11: // Wetlands + case 12: // Elwynn Forest + case 38: // Loch Modan + case 40: // Westfall + case 51: // Searing Gorge + case 1519: // Stormwind City + case 1537: // Ironforge + case 2257: // Deeprun Tram + case 3703: // Shattrath City break; - case 139: // Eastern Plaguelands - if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_EP) - pvp->FillInitialWorldStates(data); + case 139: // Eastern Plaguelands + if (outdoorPvP && outdoorPvP->GetTypeId() == OUTDOOR_PVP_EP) + outdoorPvP->FillInitialWorldStates(packet); else { - data << uint32(0x97a) << uint32(0x0); // 10 2426 - data << uint32(0x917) << uint32(0x0); // 11 2327 - data << uint32(0x918) << uint32(0x0); // 12 2328 - data << uint32(0x97b) << uint32(0x32); // 13 2427 - data << uint32(0x97c) << uint32(0x32); // 14 2428 - data << uint32(0x933) << uint32(0x1); // 15 2355 - data << uint32(0x946) << uint32(0x0); // 16 2374 - data << uint32(0x947) << uint32(0x0); // 17 2375 - data << uint32(0x948) << uint32(0x0); // 18 2376 - data << uint32(0x949) << uint32(0x0); // 19 2377 - data << uint32(0x94a) << uint32(0x0); // 20 2378 - data << uint32(0x94b) << uint32(0x0); // 21 2379 - data << uint32(0x932) << uint32(0x0); // 22 2354 - data << uint32(0x934) << uint32(0x0); // 23 2356 - data << uint32(0x935) << uint32(0x0); // 24 2357 - data << uint32(0x936) << uint32(0x0); // 25 2358 - data << uint32(0x937) << uint32(0x0); // 26 2359 - data << uint32(0x938) << uint32(0x0); // 27 2360 - data << uint32(0x939) << uint32(0x1); // 28 2361 - data << uint32(0x930) << uint32(0x1); // 29 2352 - data << uint32(0x93a) << uint32(0x0); // 30 2362 - data << uint32(0x93b) << uint32(0x0); // 31 2363 - data << uint32(0x93c) << uint32(0x0); // 32 2364 - data << uint32(0x93d) << uint32(0x0); // 33 2365 - data << uint32(0x944) << uint32(0x0); // 34 2372 - data << uint32(0x945) << uint32(0x0); // 35 2373 - data << uint32(0x931) << uint32(0x1); // 36 2353 - data << uint32(0x93e) << uint32(0x0); // 37 2366 - data << uint32(0x931) << uint32(0x1); // 38 2367 ?? grey horde not in dbc! send for consistency's sake, and to match field count - data << uint32(0x940) << uint32(0x0); // 39 2368 - data << uint32(0x941) << uint32(0x0); // 7 2369 - data << uint32(0x942) << uint32(0x0); // 8 2370 - data << uint32(0x943) << uint32(0x0); // 9 2371 + packet.Worldstates.reserve(32); + packet.Worldstates.emplace_back(0x97a, 0); // GENERAL_WORLDSTATES_01 "Progress: %2427w" + packet.Worldstates.emplace_back(0x917, 0); // EP_UI_TOWER_COUNT_A + packet.Worldstates.emplace_back(0x918, 0); // EP_UI_TOWER_COUNT_H + packet.Worldstates.emplace_back(0x97b, 50); // GENERAL_WORLDSTATES_02 + packet.Worldstates.emplace_back(0x97c, 50); // GENERAL_WORLDSTATES_03 + packet.Worldstates.emplace_back(0x933, 1); // EP_CGT_N + packet.Worldstates.emplace_back(0x946, 0); // EP_CGT_N_A + packet.Worldstates.emplace_back(0x947, 0); // EP_CGT_N_H + packet.Worldstates.emplace_back(0x948, 0); // GENERAL_WORLDSTATES_04 + packet.Worldstates.emplace_back(0x949, 0); // GENERAL_WORLDSTATES_05 + packet.Worldstates.emplace_back(0x94a, 0); // EP_CGT_A + packet.Worldstates.emplace_back(0x94b, 0); // EP_CGT_H + packet.Worldstates.emplace_back(0x932, 0); // EP_EWT_A + packet.Worldstates.emplace_back(0x934, 0); // EP_EWT_H + packet.Worldstates.emplace_back(0x935, 0); // GENERAL_WORLDSTATES_06 + packet.Worldstates.emplace_back(0x936, 0); // GENERAL_WORLDSTATES_07 + packet.Worldstates.emplace_back(0x937, 0); // EP_EWT_N_A + packet.Worldstates.emplace_back(0x938, 0); // EP_EWT_N_H + packet.Worldstates.emplace_back(0x939, 1); // EP_EWT_N + packet.Worldstates.emplace_back(0x930, 1); // EP_NPT_N + packet.Worldstates.emplace_back(0x93a, 0); // EP_NPT_N_A + packet.Worldstates.emplace_back(0x93b, 0); // GENERAL_WORLDSTATES_08 + packet.Worldstates.emplace_back(0x93c, 0); // GENERAL_WORLDSTATES_09 + packet.Worldstates.emplace_back(0x93d, 0); // GENERAL_WORLDSTATES_10 + packet.Worldstates.emplace_back(0x944, 0); // EP_NPT_A + packet.Worldstates.emplace_back(0x945, 0); // EP_NPT_H + packet.Worldstates.emplace_back(0x931, 1); // EP_PWT_N + packet.Worldstates.emplace_back(0x93e, 0); // EP_PWT_N_A + //packet.Worldstates.emplace_back(0x93f, 1); // GENERAL_WORLDSTATES_13 grey horde not in dbc! + packet.Worldstates.emplace_back(0x940, 0); // GENERAL_WORLDSTATES_11 + packet.Worldstates.emplace_back(0x941, 0); // GENERAL_WORLDSTATES_12 + packet.Worldstates.emplace_back(0x942, 0); // EP_PWT_A + packet.Worldstates.emplace_back(0x943, 0); // EP_PWT_H + + break; + case 1377: // Silithus + if (outdoorPvP && outdoorPvP->GetTypeId() == OUTDOOR_PVP_SI) + outdoorPvP->FillInitialWorldStates(packet); + else + { + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0x909, 0); // SI_GATHERED_A + packet.Worldstates.emplace_back(0x90a, 0); // SI_GATHERED_H + packet.Worldstates.emplace_back(0x90d, 0); // SI_SILITHYST_MAX + } + // unknown, aq opening? + packet.Worldstates.reserve(4); + packet.Worldstates.emplace_back(0x912, 0); // AQ_SANDWORM_N + packet.Worldstates.emplace_back(0x913, 0); // AQ_SANDWORM_S + packet.Worldstates.emplace_back(0x914, 0); // AQ_SANDWORM_SW + packet.Worldstates.emplace_back(0x915, 0); // AQ_SANDWORM_E + break; + case 2597: // Alterac Valley + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_AV) + battleground->FillInitialWorldStates(packet); + else + { + packet.Worldstates.reserve(75); + packet.Worldstates.emplace_back(0x7ae, 1); // AV_SNOWFALL_N + packet.Worldstates.emplace_back(0x532, 1); // AV_FROSTWOLFHUT_H_C + packet.Worldstates.emplace_back(0x531, 0); // AV_FROSTWOLFHUT_A_C + packet.Worldstates.emplace_back(0x52e, 0); // AV_AID_A_A + packet.Worldstates.emplace_back(0x571, 0); // East Frostwolf Tower Horde Assaulted - UNUSED + packet.Worldstates.emplace_back(0x570, 0); // West Frostwolf Tower Horde Assaulted - UNUSED + packet.Worldstates.emplace_back(0x567, 1); // AV_FROSTWOLFE_CONTROLLED + packet.Worldstates.emplace_back(0x566, 1); // AV_FROSTWOLFW_CONTROLLED + packet.Worldstates.emplace_back(0x550, 1); // AV_N_MINE_N + packet.Worldstates.emplace_back(0x544, 0); // AV_ICEBLOOD_A_A + packet.Worldstates.emplace_back(0x536, 0); // AV_PIKEGRAVE_H_C + packet.Worldstates.emplace_back(0x535, 1); // AV_PIKEGRAVE_A_C + packet.Worldstates.emplace_back(0x518, 0); // AV_STONEHEART_A_A + packet.Worldstates.emplace_back(0x517, 0); // AV_STONEHEART_H_A + packet.Worldstates.emplace_back(0x574, 0); // unk + packet.Worldstates.emplace_back(0x573, 0); // Iceblood Tower Horde Assaulted - UNUSED + packet.Worldstates.emplace_back(0x572, 0); // Towerpoint Horde Assaulted - UNUSED + packet.Worldstates.emplace_back(0x56f, 0); // unk + packet.Worldstates.emplace_back(0x56e, 0); // AV_ICEBLOOD_ASSAULTED + packet.Worldstates.emplace_back(0x56d, 0); // AV_TOWERPOINT_ASSAULTED + packet.Worldstates.emplace_back(0x56c, 0); // AV_FROSTWOLFE_ASSAULTED + packet.Worldstates.emplace_back(0x56b, 0); // AV_FROSTWOLFW_ASSAULTED + packet.Worldstates.emplace_back(0x56a, 1); // unk + packet.Worldstates.emplace_back(0x569, 1); // AV_ICEBLOOD_CONTROLLED + packet.Worldstates.emplace_back(0x568, 1); // AV_TOWERPOINT_CONTROLLED + packet.Worldstates.emplace_back(0x565, 0); // AV_STONEH_ASSAULTED + packet.Worldstates.emplace_back(0x564, 0); // AV_ICEWING_ASSAULTED + packet.Worldstates.emplace_back(0x563, 0); // AV_DUNN_ASSAULTED + packet.Worldstates.emplace_back(0x562, 0); // AV_DUNS_ASSAULTED + packet.Worldstates.emplace_back(0x561, 0); // Stoneheart Bunker Alliance Assaulted - UNUSED + packet.Worldstates.emplace_back(0x560, 0); // Icewing Bunker Alliance Assaulted - UNUSED + packet.Worldstates.emplace_back(0x55f, 0); // Dunbaldar South Alliance Assaulted - UNUSED + packet.Worldstates.emplace_back(0x55e, 0); // Dunbaldar North Alliance Assaulted - UNUSED + packet.Worldstates.emplace_back(0x55d, 0); // AV_STONEH_DESTROYED + packet.Worldstates.emplace_back(0x3c6, 0); // AV_UNK_02 + packet.Worldstates.emplace_back(0x3c4, 0); // AV_UNK_01 + packet.Worldstates.emplace_back(0x3c2, 0); // AV_STORMPIKE_COMMANDERS + packet.Worldstates.emplace_back(0x516, 1); // AV_STONEHEART_A_C + packet.Worldstates.emplace_back(0x515, 0); // AV_STONEHEART_H_C + packet.Worldstates.emplace_back(0x3b6, 0); // AV_STORMPIKE_LIEUTENANTS + packet.Worldstates.emplace_back(0x55c, 0); // AV_ICEWING_DESTROYED + packet.Worldstates.emplace_back(0x55b, 0); // AV_DUNN_DESTROYED + packet.Worldstates.emplace_back(0x55a, 0); // AV_DUNS_DESTROYED + packet.Worldstates.emplace_back(0x559, 0); // unk + packet.Worldstates.emplace_back(0x558, 0); // AV_ICEBLOOD_DESTROYED + packet.Worldstates.emplace_back(0x557, 0); // AV_TOWERPOINT_DESTROYED + packet.Worldstates.emplace_back(0x556, 0); // AV_FROSTWOLFE_DESTROYED + packet.Worldstates.emplace_back(0x555, 0); // AV_FROSTWOLFW_DESTROYED + packet.Worldstates.emplace_back(0x554, 1); // AV_STONEH_CONTROLLED + packet.Worldstates.emplace_back(0x553, 1); // AV_ICEWING_CONTROLLED + packet.Worldstates.emplace_back(0x552, 1); // AV_DUNN_CONTROLLED + packet.Worldstates.emplace_back(0x551, 1); // AV_DUNS_CONTROLLED + packet.Worldstates.emplace_back(0x54f, 0); // AV_N_MINE_H + packet.Worldstates.emplace_back(0x54e, 0); // AV_N_MINE_A + packet.Worldstates.emplace_back(0x54d, 1); // AV_S_MINE_N + packet.Worldstates.emplace_back(0x54c, 0); // AV_S_MINE_H + packet.Worldstates.emplace_back(0x54b, 0); // AV_S_MINE_A + packet.Worldstates.emplace_back(0x545, 0); // AV_ICEBLOOD_H_A + packet.Worldstates.emplace_back(0x543, 1); // AV_ICEBLOOD_H_C + packet.Worldstates.emplace_back(0x542, 0); // AV_ICEBLOOD_A_C + packet.Worldstates.emplace_back(0x540, 0); // AV_SNOWFALL_H_A + packet.Worldstates.emplace_back(0x53f, 0); // AV_SNOWFALL_A_A + packet.Worldstates.emplace_back(0x53e, 0); // AV_SNOWFALL_H_C + packet.Worldstates.emplace_back(0x53d, 0); // AV_SNOWFALL_A_C + packet.Worldstates.emplace_back(0x53c, 0); // AV_FROSTWOLF_H_A + packet.Worldstates.emplace_back(0x53b, 0); // AV_FROSTWOLF_A_A + packet.Worldstates.emplace_back(0x53a, 1); // AV_FROSTWOLF_H_C + packet.Worldstates.emplace_back(0x539, 0); // AV_FROSTWOLF_A_C + packet.Worldstates.emplace_back(0x538, 0); // AV_PIKEGRAVE_H_A + packet.Worldstates.emplace_back(0x537, 0); // AV_PIKEGRAVE_A_A + packet.Worldstates.emplace_back(0x534, 0); // AV_FROSTWOLFHUT_H_A + packet.Worldstates.emplace_back(0x533, 0); // AV_FROSTWOLFHUT_A_A + packet.Worldstates.emplace_back(0x530, 0); // AV_AID_H_A + packet.Worldstates.emplace_back(0x52f, 0); // AV_AID_H_C + packet.Worldstates.emplace_back(0x52d, 1); // AV_AID_A_C } break; - case 1377: // Silithus - if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_SI) - pvp->FillInitialWorldStates(data); + case 3277: // Warsong Gulch + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_WS) + battleground->FillInitialWorldStates(packet); else { - // states are always shown - data << uint32(2313) << uint32(0x0); // 7 ally silityst gathered - data << uint32(2314) << uint32(0x0); // 8 horde silityst gathered - data << uint32(2317) << uint32(0x0); // 9 max silithyst - } - // dunno about these... aq opening event maybe? - data << uint32(2322) << uint32(0x0); // 10 sandworm N - data << uint32(2323) << uint32(0x0); // 11 sandworm S - data << uint32(2324) << uint32(0x0); // 12 sandworm SW - data << uint32(2325) << uint32(0x0); // 13 sandworm E - break; - case 2597: // Alterac Valley - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_AV) - bg->FillInitialWorldStates(data); - else - { - data << uint32(0x7ae) << uint32(0x1); // 7 snowfall n - data << uint32(0x532) << uint32(0x1); // 8 frostwolfhut hc - data << uint32(0x531) << uint32(0x0); // 9 frostwolfhut ac - data << uint32(0x52e) << uint32(0x0); // 10 stormpike firstaid a_a - data << uint32(0x571) << uint32(0x0); // 11 east frostwolf tower horde assaulted -unused - data << uint32(0x570) << uint32(0x0); // 12 west frostwolf tower horde assaulted - unused - data << uint32(0x567) << uint32(0x1); // 13 frostwolfe c - data << uint32(0x566) << uint32(0x1); // 14 frostwolfw c - data << uint32(0x550) << uint32(0x1); // 15 irondeep (N) ally - data << uint32(0x544) << uint32(0x0); // 16 ice grave a_a - data << uint32(0x536) << uint32(0x0); // 17 stormpike grave h_c - data << uint32(0x535) << uint32(0x1); // 18 stormpike grave a_c - data << uint32(0x518) << uint32(0x0); // 19 stoneheart grave a_a - data << uint32(0x517) << uint32(0x0); // 20 stoneheart grave h_a - data << uint32(0x574) << uint32(0x0); // 21 1396 unk - data << uint32(0x573) << uint32(0x0); // 22 iceblood tower horde assaulted -unused - data << uint32(0x572) << uint32(0x0); // 23 towerpoint horde assaulted - unused - data << uint32(0x56f) << uint32(0x0); // 24 1391 unk - data << uint32(0x56e) << uint32(0x0); // 25 iceblood a - data << uint32(0x56d) << uint32(0x0); // 26 towerp a - data << uint32(0x56c) << uint32(0x0); // 27 frostwolfe a - data << uint32(0x56b) << uint32(0x0); // 28 froswolfw a - data << uint32(0x56a) << uint32(0x1); // 29 1386 unk - data << uint32(0x569) << uint32(0x1); // 30 iceblood c - data << uint32(0x568) << uint32(0x1); // 31 towerp c - data << uint32(0x565) << uint32(0x0); // 32 stoneh tower a - data << uint32(0x564) << uint32(0x0); // 33 icewing tower a - data << uint32(0x563) << uint32(0x0); // 34 dunn a - data << uint32(0x562) << uint32(0x0); // 35 duns a - data << uint32(0x561) << uint32(0x0); // 36 stoneheart bunker alliance assaulted - unused - data << uint32(0x560) << uint32(0x0); // 37 icewing bunker alliance assaulted - unused - data << uint32(0x55f) << uint32(0x0); // 38 dunbaldar south alliance assaulted - unused - data << uint32(0x55e) << uint32(0x0); // 39 dunbaldar north alliance assaulted - unused - data << uint32(0x55d) << uint32(0x0); // 40 stone tower d - data << uint32(0x3c6) << uint32(0x0); // 41 966 unk - data << uint32(0x3c4) << uint32(0x0); // 42 964 unk - data << uint32(0x3c2) << uint32(0x0); // 43 962 unk - data << uint32(0x516) << uint32(0x1); // 44 stoneheart grave a_c - data << uint32(0x515) << uint32(0x0); // 45 stonheart grave h_c - data << uint32(0x3b6) << uint32(0x0); // 46 950 unk - data << uint32(0x55c) << uint32(0x0); // 47 icewing tower d - data << uint32(0x55b) << uint32(0x0); // 48 dunn d - data << uint32(0x55a) << uint32(0x0); // 49 duns d - data << uint32(0x559) << uint32(0x0); // 50 1369 unk - data << uint32(0x558) << uint32(0x0); // 51 iceblood d - data << uint32(0x557) << uint32(0x0); // 52 towerp d - data << uint32(0x556) << uint32(0x0); // 53 frostwolfe d - data << uint32(0x555) << uint32(0x0); // 54 frostwolfw d - data << uint32(0x554) << uint32(0x1); // 55 stoneh tower c - data << uint32(0x553) << uint32(0x1); // 56 icewing tower c - data << uint32(0x552) << uint32(0x1); // 57 dunn c - data << uint32(0x551) << uint32(0x1); // 58 duns c - data << uint32(0x54f) << uint32(0x0); // 59 irondeep (N) horde - data << uint32(0x54e) << uint32(0x0); // 60 irondeep (N) ally - data << uint32(0x54d) << uint32(0x1); // 61 mine (S) neutral - data << uint32(0x54c) << uint32(0x0); // 62 mine (S) horde - data << uint32(0x54b) << uint32(0x0); // 63 mine (S) ally - data << uint32(0x545) << uint32(0x0); // 64 iceblood h_a - data << uint32(0x543) << uint32(0x1); // 65 iceblod h_c - data << uint32(0x542) << uint32(0x0); // 66 iceblood a_c - data << uint32(0x540) << uint32(0x0); // 67 snowfall h_a - data << uint32(0x53f) << uint32(0x0); // 68 snowfall a_a - data << uint32(0x53e) << uint32(0x0); // 69 snowfall h_c - data << uint32(0x53d) << uint32(0x0); // 70 snowfall a_c - data << uint32(0x53c) << uint32(0x0); // 71 frostwolf g h_a - data << uint32(0x53b) << uint32(0x0); // 72 frostwolf g a_a - data << uint32(0x53a) << uint32(0x1); // 73 frostwolf g h_c - data << uint32(0x539) << uint32(0x0); // 74 frostwolf g a_c - data << uint32(0x538) << uint32(0x0); // 75 stormpike grave h_a - data << uint32(0x537) << uint32(0x0); // 76 stormpike grave a_a - data << uint32(0x534) << uint32(0x0); // 77 frostwolf hut h_a - data << uint32(0x533) << uint32(0x0); // 78 frostwolf hut a_a - data << uint32(0x530) << uint32(0x0); // 79 stormpike first aid h_a - data << uint32(0x52f) << uint32(0x0); // 80 stormpike first aid h_c - data << uint32(0x52d) << uint32(0x1); // 81 stormpike first aid a_c + packet.Worldstates.reserve(8); + packet.Worldstates.emplace_back(0x62d, 0); // alliance flag captures + packet.Worldstates.emplace_back(0x62e, 0); // horde flag captures + packet.Worldstates.emplace_back(0x609, 0); // unk, set to 1 on alliance flag pickup... + packet.Worldstates.emplace_back(0x60a, 0); // unk, set to 1 on horde flag pickup, after drop it's -1 + packet.Worldstates.emplace_back(0x60b, 2); // unk + packet.Worldstates.emplace_back(0x641, 3); // unk (max flag captures?) + packet.Worldstates.emplace_back(0x922, 1); // horde (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing) + packet.Worldstates.emplace_back(0x923, 1); // alliance (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing) } break; - case 3277: // Warsong Gulch - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_WS) - bg->FillInitialWorldStates(data); + case 3358: // Arathi Basin + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_AB) + battleground->FillInitialWorldStates(packet); else { - data << uint32(0x62d) << uint32(0x0); // 7 1581 alliance flag captures - data << uint32(0x62e) << uint32(0x0); // 8 1582 horde flag captures - data << uint32(0x609) << uint32(0x0); // 9 1545 unk, set to 1 on alliance flag pickup... - data << uint32(0x60a) << uint32(0x0); // 10 1546 unk, set to 1 on horde flag pickup, after drop it's -1 - data << uint32(0x60b) << uint32(0x2); // 11 1547 unk - data << uint32(0x641) << uint32(0x3); // 12 1601 unk (max flag captures?) - data << uint32(0x922) << uint32(0x1); // 13 2338 horde (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing) - data << uint32(0x923) << uint32(0x1); // 14 2339 alliance (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing) + packet.Worldstates.reserve(32); + packet.Worldstates.emplace_back(0x6e7, 0); // stables alliance + packet.Worldstates.emplace_back(0x6e8, 0); // stables horde + packet.Worldstates.emplace_back(0x6e9, 0); // stables alliance controlled + packet.Worldstates.emplace_back(0x6ea, 0); // stables horde controlled + packet.Worldstates.emplace_back(0x6ec, 0); // farm alliance + packet.Worldstates.emplace_back(0x6ed, 0); // farm horde + packet.Worldstates.emplace_back(0x6ee, 0); // farm alliance controlled + packet.Worldstates.emplace_back(0x6ef, 0); // farm horde controlled + packet.Worldstates.emplace_back(0x6f0, 0); // alliance resources + packet.Worldstates.emplace_back(0x6f1, 0); // horde resources + packet.Worldstates.emplace_back(0x6f2, 0); // horde bases + packet.Worldstates.emplace_back(0x6f3, 0); // alliance bases + packet.Worldstates.emplace_back(0x6f4, 1600); // max resources (1600) + packet.Worldstates.emplace_back(0x6f6, 0); // blacksmith alliance + packet.Worldstates.emplace_back(0x6f7, 0); // blacksmith horde + packet.Worldstates.emplace_back(0x6f8, 0); // blacksmith alliance controlled + packet.Worldstates.emplace_back(0x6f9, 0); // blacksmith horde controlled + packet.Worldstates.emplace_back(0x6fb, 0); // gold mine alliance + packet.Worldstates.emplace_back(0x6fc, 0); // gold mine horde + packet.Worldstates.emplace_back(0x6fd, 0); // gold mine alliance controlled + packet.Worldstates.emplace_back(0x6fe, 0); // gold mine horde controlled + packet.Worldstates.emplace_back(0x700, 0); // lumber mill alliance + packet.Worldstates.emplace_back(0x701, 0); // lumber mill horde + packet.Worldstates.emplace_back(0x702, 0); // lumber mill alliance controlled + packet.Worldstates.emplace_back(0x703, 0); // lumber mill horde controlled + packet.Worldstates.emplace_back(0x732, 1); // stables (1 - uncontrolled) + packet.Worldstates.emplace_back(0x733, 1); // gold mine (1 - uncontrolled) + packet.Worldstates.emplace_back(0x734, 1); // lumber mill (1 - uncontrolled) + packet.Worldstates.emplace_back(0x735, 1); // farm (1 - uncontrolled) + packet.Worldstates.emplace_back(0x736, 1); // blacksmith (1 - uncontrolled) + packet.Worldstates.emplace_back(0x745, 2); // unk + packet.Worldstates.emplace_back(0x7a3, 1400); // warning limit (1400) } break; - case 3358: // Arathi Basin - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_AB) - bg->FillInitialWorldStates(data); + case 3820: // Eye of the Storm + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_EY) + battleground->FillInitialWorldStates(packet); else { - data << uint32(0x6e7) << uint32(0x0); // 7 1767 stables alliance - data << uint32(0x6e8) << uint32(0x0); // 8 1768 stables horde - data << uint32(0x6e9) << uint32(0x0); // 9 1769 unk, ST? - data << uint32(0x6ea) << uint32(0x0); // 10 1770 stables (show/hide) - data << uint32(0x6ec) << uint32(0x0); // 11 1772 farm (0 - horde controlled, 1 - alliance controlled) - data << uint32(0x6ed) << uint32(0x0); // 12 1773 farm (show/hide) - data << uint32(0x6ee) << uint32(0x0); // 13 1774 farm color - data << uint32(0x6ef) << uint32(0x0); // 14 1775 gold mine color, may be FM? - data << uint32(0x6f0) << uint32(0x0); // 15 1776 alliance resources - data << uint32(0x6f1) << uint32(0x0); // 16 1777 horde resources - data << uint32(0x6f2) << uint32(0x0); // 17 1778 horde bases - data << uint32(0x6f3) << uint32(0x0); // 18 1779 alliance bases - data << uint32(0x6f4) << uint32(0x640); // 19 1780 max resources (1600) - data << uint32(0x6f6) << uint32(0x0); // 20 1782 blacksmith color - data << uint32(0x6f7) << uint32(0x0); // 21 1783 blacksmith (show/hide) - data << uint32(0x6f8) << uint32(0x0); // 22 1784 unk, bs? - data << uint32(0x6f9) << uint32(0x0); // 23 1785 unk, bs? - data << uint32(0x6fb) << uint32(0x0); // 24 1787 gold mine (0 - horde contr, 1 - alliance contr) - data << uint32(0x6fc) << uint32(0x0); // 25 1788 gold mine (0 - conflict, 1 - horde) - data << uint32(0x6fd) << uint32(0x0); // 26 1789 gold mine (1 - show/0 - hide) - data << uint32(0x6fe) << uint32(0x0); // 27 1790 gold mine color - data << uint32(0x700) << uint32(0x0); // 28 1792 gold mine color, may be LM? - data << uint32(0x701) << uint32(0x0); // 29 1793 lumber mill color (0 - conflict, 1 - horde contr) - data << uint32(0x702) << uint32(0x0); // 30 1794 lumber mill (show/hide) - data << uint32(0x703) << uint32(0x0); // 31 1795 lumber mill color color - data << uint32(0x732) << uint32(0x1); // 32 1842 stables (1 - uncontrolled) - data << uint32(0x733) << uint32(0x1); // 33 1843 gold mine (1 - uncontrolled) - data << uint32(0x734) << uint32(0x1); // 34 1844 lumber mill (1 - uncontrolled) - data << uint32(0x735) << uint32(0x1); // 35 1845 farm (1 - uncontrolled) - data << uint32(0x736) << uint32(0x1); // 36 1846 blacksmith (1 - uncontrolled) - data << uint32(0x745) << uint32(0x2); // 37 1861 unk - data << uint32(0x7a3) << uint32(0x578); // 38 1955 warning limit (1400) - } - break; - case 3820: // Eye of the Storm - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_EY) - bg->FillInitialWorldStates(data); - else - { - data << uint32(0xac1) << uint32(0x0); // 7 2753 Horde Bases - data << uint32(0xac0) << uint32(0x0); // 8 2752 Alliance Bases - data << uint32(0xab6) << uint32(0x0); // 9 2742 Mage Tower - Horde conflict - data << uint32(0xab5) << uint32(0x0); // 10 2741 Mage Tower - Alliance conflict - data << uint32(0xab4) << uint32(0x0); // 11 2740 Fel Reaver - Horde conflict - data << uint32(0xab3) << uint32(0x0); // 12 2739 Fel Reaver - Alliance conflict - data << uint32(0xab2) << uint32(0x0); // 13 2738 Draenei - Alliance conflict - data << uint32(0xab1) << uint32(0x0); // 14 2737 Draenei - Horde conflict - data << uint32(0xab0) << uint32(0x0); // 15 2736 unk // 0 at start - data << uint32(0xaaf) << uint32(0x0); // 16 2735 unk // 0 at start - data << uint32(0xaad) << uint32(0x0); // 17 2733 Draenei - Horde control - data << uint32(0xaac) << uint32(0x0); // 18 2732 Draenei - Alliance control - data << uint32(0xaab) << uint32(0x1); // 19 2731 Draenei uncontrolled (1 - yes, 0 - no) - data << uint32(0xaaa) << uint32(0x0); // 20 2730 Mage Tower - Alliance control - data << uint32(0xaa9) << uint32(0x0); // 21 2729 Mage Tower - Horde control - data << uint32(0xaa8) << uint32(0x1); // 22 2728 Mage Tower uncontrolled (1 - yes, 0 - no) - data << uint32(0xaa7) << uint32(0x0); // 23 2727 Fel Reaver - Horde control - data << uint32(0xaa6) << uint32(0x0); // 24 2726 Fel Reaver - Alliance control - data << uint32(0xaa5) << uint32(0x1); // 25 2725 Fel Reaver uncontrolled (1 - yes, 0 - no) - data << uint32(0xaa4) << uint32(0x0); // 26 2724 Boold Elf - Horde control - data << uint32(0xaa3) << uint32(0x0); // 27 2723 Boold Elf - Alliance control - data << uint32(0xaa2) << uint32(0x1); // 28 2722 Boold Elf uncontrolled (1 - yes, 0 - no) - data << uint32(0xac5) << uint32(0x1); // 29 2757 Flag (1 - show, 0 - hide) - doesn't work exactly this way! - data << uint32(0xad2) << uint32(0x1); // 30 2770 Horde top-stats (1 - show, 0 - hide) // 02 -> horde picked up the flag - data << uint32(0xad1) << uint32(0x1); // 31 2769 Alliance top-stats (1 - show, 0 - hide) // 02 -> alliance picked up the flag - data << uint32(0xabe) << uint32(0x0); // 32 2750 Horde resources - data << uint32(0xabd) << uint32(0x0); // 33 2749 Alliance resources - data << uint32(0xa05) << uint32(0x8e); // 34 2565 unk, constant? - data << uint32(0xaa0) << uint32(0x0); // 35 2720 Capturing progress-bar (100 -> empty (only grey), 0 -> blue|red (no grey), default 0) - data << uint32(0xa9f) << uint32(0x0); // 36 2719 Capturing progress-bar (0 - left, 100 - right) - data << uint32(0xa9e) << uint32(0x0); // 37 2718 Capturing progress-bar (1 - show, 0 - hide) - data << uint32(0xc0d) << uint32(0x17b); // 38 3085 unk - // and some more ... unknown + packet.Worldstates.reserve(32); + packet.Worldstates.emplace_back(0xac1, 0); // Horde Bases + packet.Worldstates.emplace_back(0xac0, 0); // Alliance Bases + packet.Worldstates.emplace_back(0xab6, 0); // Mage Tower - Horde conflict + packet.Worldstates.emplace_back(0xab5, 0); // Mage Tower - Alliance conflict + packet.Worldstates.emplace_back(0xab4, 0); // Fel Reaver - Horde conflict + packet.Worldstates.emplace_back(0xab3, 0); // Fel Reaver - Alliance conflict + packet.Worldstates.emplace_back(0xab2, 0); // Draenei - Alliance conflict + packet.Worldstates.emplace_back(0xab1, 0); // Draenei - Horde conflict + packet.Worldstates.emplace_back(0xab0, 0); // unk (0 at start) + packet.Worldstates.emplace_back(0xaaf, 0); // unk (0 at start) + packet.Worldstates.emplace_back(0xaad, 0); // Draenei - Horde control + packet.Worldstates.emplace_back(0xaac, 0); // Draenei - Alliance control + packet.Worldstates.emplace_back(0xaab, 1); // Draenei uncontrolled (1 - yes, 0 - no) + packet.Worldstates.emplace_back(0xaaa, 0); // Mage Tower - Alliance control + packet.Worldstates.emplace_back(0xaa9, 0); // Mage Tower - Horde control + packet.Worldstates.emplace_back(0xaa8, 1); // Mage Tower uncontrolled (1 - yes, 0 - no) + packet.Worldstates.emplace_back(0xaa7, 0); // Fel Reaver - Horde control + packet.Worldstates.emplace_back(0xaa6, 0); // Fel Reaver - Alliance control + packet.Worldstates.emplace_back(0xaa5, 1); // Fel Reaver uncontrolled (1 - yes, 0 - no) + packet.Worldstates.emplace_back(0xaa4, 0); // Boold Elf - Horde control + packet.Worldstates.emplace_back(0xaa3, 0); // Boold Elf - Alliance control + packet.Worldstates.emplace_back(0xaa2, 1); // Boold Elf uncontrolled (1 - yes, 0 - no) + packet.Worldstates.emplace_back(0xac5, 1); // Flag (1 - show, 0 - hide) - doesn't work exactly this way! + packet.Worldstates.emplace_back(0xad2, 1); // Horde top-stats (1 - show, 0 - hide) // 02 -> horde picked up the flag + packet.Worldstates.emplace_back(0xad1, 1); // Alliance top-stats (1 - show, 0 - hide) // 02 -> alliance picked up the flag + packet.Worldstates.emplace_back(0xabe, 0); // Horde resources + packet.Worldstates.emplace_back(0xabd, 0); // Alliance resources + packet.Worldstates.emplace_back(0xa05, 142); // unk, constant? + packet.Worldstates.emplace_back(0xaa0, 0); // Capturing progress-bar (100 -> empty (only grey), 0 -> blue|red (no grey), default 0) + packet.Worldstates.emplace_back(0xa9f, 0); // Capturing progress-bar (0 - left, 100 - right) + packet.Worldstates.emplace_back(0xa9e, 0); // Capturing progress-bar (1 - show, 0 - hide) + packet.Worldstates.emplace_back(0xc0d, 379); // unk, constant? + // missing unknowns } break; // any of these needs change! the client remembers the prev setting! // ON EVERY ZONE LEAVE, RESET THE OLD ZONE'S WORLD STATE, BUT AT LEAST THE UI STUFF! - case 3483: // Hellfire Peninsula - if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_HP) - pvp->FillInitialWorldStates(data); + case 3483: // Hellfire Peninsula + if (outdoorPvP && outdoorPvP->GetTypeId() == OUTDOOR_PVP_HP) + outdoorPvP->FillInitialWorldStates(packet); else { - data << uint32(0x9ba) << uint32(0x1); // 10 // add ally tower main gui icon // maybe should be sent only on login? - data << uint32(0x9b9) << uint32(0x1); // 11 // add horde tower main gui icon // maybe should be sent only on login? - data << uint32(0x9b5) << uint32(0x0); // 12 // show neutral broken hill icon // 2485 - data << uint32(0x9b4) << uint32(0x1); // 13 // show icon above broken hill // 2484 - data << uint32(0x9b3) << uint32(0x0); // 14 // show ally broken hill icon // 2483 - data << uint32(0x9b2) << uint32(0x0); // 15 // show neutral overlook icon // 2482 - data << uint32(0x9b1) << uint32(0x1); // 16 // show the overlook arrow // 2481 - data << uint32(0x9b0) << uint32(0x0); // 17 // show ally overlook icon // 2480 - data << uint32(0x9ae) << uint32(0x0); // 18 // horde pvp objectives captured // 2478 - data << uint32(0x9ac) << uint32(0x0); // 19 // ally pvp objectives captured // 2476 - data << uint32(2475) << uint32(100); //: ally / horde slider grey area // show only in direct vicinity! - data << uint32(2474) << uint32(50); //: ally / horde slider percentage, 100 for ally, 0 for horde // show only in direct vicinity! - data << uint32(2473) << uint32(0); //: ally / horde slider display // show only in direct vicinity! - data << uint32(0x9a8) << uint32(0x0); // 20 // show the neutral stadium icon // 2472 - data << uint32(0x9a7) << uint32(0x0); // 21 // show the ally stadium icon // 2471 - data << uint32(0x9a6) << uint32(0x1); // 22 // show the horde stadium icon // 2470 + packet.Worldstates.reserve(16); + packet.Worldstates.emplace_back(0x9ba, 1); // add ally tower main gui icon // maybe should be sent only on login? + packet.Worldstates.emplace_back(0x9b9, 1); // add horde tower main gui icon // maybe should be sent only on login? + packet.Worldstates.emplace_back(0x9b5, 0); // show neutral broken hill icon + packet.Worldstates.emplace_back(0x9b4, 1); // show icon above broken hill + packet.Worldstates.emplace_back(0x9b3, 0); // show ally broken hill icon + packet.Worldstates.emplace_back(0x9b2, 0); // show neutral overlook icon + packet.Worldstates.emplace_back(0x9b1, 1); // show the overlook arrow + packet.Worldstates.emplace_back(0x9b0, 0); // show ally overlook icon + packet.Worldstates.emplace_back(0x9ae, 0); // horde pvp objectives captured + packet.Worldstates.emplace_back(0x9ac, 0); // ally pvp objectives captured + packet.Worldstates.emplace_back(0x9ab, 100); //: ally / horde slider grey area // show only in direct vicinity! + packet.Worldstates.emplace_back(0x9aa, 50); //: ally / horde slider percentage, 100 for ally, 0 for horde // show only in direct vicinity! + packet.Worldstates.emplace_back(0x9a9, 0); //: ally / horde slider display // show only in direct vicinity! + packet.Worldstates.emplace_back(0x9a8, 0); // show the neutral stadium icon + packet.Worldstates.emplace_back(0x9a7, 0); // show the ally stadium icon + packet.Worldstates.emplace_back(0x9a6, 1); // show the horde stadium icon } break; - case 3518: // Nagrand - if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_NA) - pvp->FillInitialWorldStates(data); + case 3518: // Nagrand + if (outdoorPvP && outdoorPvP->GetTypeId() == OUTDOOR_PVP_NA) + outdoorPvP->FillInitialWorldStates(packet); + else + { + packet.Worldstates.reserve(28); + packet.Worldstates.emplace_back(0x9c7, 0); // NA_UI_HORDE_GUARDS_SHOW + packet.Worldstates.emplace_back(0x9c6, 0); // NA_UI_ALLIANCE_GUARDS_SHOW + packet.Worldstates.emplace_back(0x9bd, 0); // NA_UI_GUARDS_MAX + packet.Worldstates.emplace_back(0x9bb, 0); // NA_UI_GUARDS_LEFT + packet.Worldstates.emplace_back(0x9bf, 0); // NA_UI_OUTLAND_01 + packet.Worldstates.emplace_back(0x9be, 0); // NA_UI_UNK_1 + packet.Worldstates.emplace_back(0x9c1, 0); // NA_UI_UNK_2 + packet.Worldstates.emplace_back(0xaca, 0); // NA_MAP_WYVERN_NORTH_NEU_H + packet.Worldstates.emplace_back(0xa66, 0); // NA_MAP_WYVERN_NORTH_NEU_A + packet.Worldstates.emplace_back(0xa67, 0); // NA_MAP_WYVERN_NORTH_H + packet.Worldstates.emplace_back(0xa68, 0); // NA_MAP_WYVERN_NORTH_A + packet.Worldstates.emplace_back(0xac8, 0); // NA_MAP_WYVERN_SOUTH_NEU_H + packet.Worldstates.emplace_back(0xa6e, 0); // NA_MAP_WYVERN_SOUTH_NEU_A + packet.Worldstates.emplace_back(0xa6c, 0); // NA_MAP_WYVERN_SOUTH_H + packet.Worldstates.emplace_back(0xa6d, 0); // NA_MAP_WYVERN_SOUTH_A + packet.Worldstates.emplace_back(0xac9, 0); // NA_MAP_WYVERN_WEST_NEU_H + packet.Worldstates.emplace_back(0xa6b, 0); // NA_MAP_WYVERN_WEST_NEU_A + packet.Worldstates.emplace_back(0xa69, 0); // NA_MAP_WYVERN_WEST_H + packet.Worldstates.emplace_back(0xa6a, 0); // NA_MAP_WYVERN_WEST_A + packet.Worldstates.emplace_back(0xacb, 0); // NA_MAP_WYVERN_EAST_NEU_H + packet.Worldstates.emplace_back(0xa63, 0); // NA_MAP_WYVERN_EAST_NEU_A + packet.Worldstates.emplace_back(0xa64, 0); // NA_MAP_WYVERN_EAST_H + packet.Worldstates.emplace_back(0xa65, 0); // NA_MAP_WYVERN_EAST_A + packet.Worldstates.emplace_back(0xa6f, 0); // NA_MAP_HALAA_NEUTRAL + packet.Worldstates.emplace_back(0xa74, 0); // NA_MAP_HALAA_NEU_A + packet.Worldstates.emplace_back(0xa75, 0); // NA_MAP_HALAA_NEU_H + packet.Worldstates.emplace_back(0xa70, 0); // NA_MAP_HALAA_HORDE + packet.Worldstates.emplace_back(0xa71, 0); // NA_MAP_HALAA_ALLIANCE + } + break; + case 3519: // Terokkar Forest + if (outdoorPvP && outdoorPvP->GetTypeId() == OUTDOOR_PVP_TF) + outdoorPvP->FillInitialWorldStates(packet); else { - data << uint32(2503) << uint32(0x0); // 10 - data << uint32(2502) << uint32(0x0); // 11 - data << uint32(2493) << uint32(0x0); // 12 - data << uint32(2491) << uint32(0x0); // 13 - - data << uint32(2495) << uint32(0x0); // 14 - data << uint32(2494) << uint32(0x0); // 15 - data << uint32(2497) << uint32(0x0); // 16 - - data << uint32(2762) << uint32(0x0); // 17 - data << uint32(2662) << uint32(0x0); // 18 - data << uint32(2663) << uint32(0x0); // 19 - data << uint32(2664) << uint32(0x0); // 20 - - data << uint32(2760) << uint32(0x0); // 21 - data << uint32(2670) << uint32(0x0); // 22 - data << uint32(2668) << uint32(0x0); // 23 - data << uint32(2669) << uint32(0x0); // 24 - - data << uint32(2761) << uint32(0x0); // 25 - data << uint32(2667) << uint32(0x0); // 26 - data << uint32(2665) << uint32(0x0); // 27 - data << uint32(2666) << uint32(0x0); // 28 - - data << uint32(2763) << uint32(0x0); // 29 - data << uint32(2659) << uint32(0x0); // 30 - data << uint32(2660) << uint32(0x0); // 31 - data << uint32(2661) << uint32(0x0); // 32 - - data << uint32(2671) << uint32(0x0); // 33 - data << uint32(2676) << uint32(0x0); // 34 - data << uint32(2677) << uint32(0x0); // 35 - data << uint32(2672) << uint32(0x0); // 36 - data << uint32(2673) << uint32(0x0); // 37 + packet.Worldstates.reserve(28); + packet.Worldstates.emplace_back(0xa41, 0); // TF_UI_CAPTURE_BAR_POS + packet.Worldstates.emplace_back(0xa40, 20); // TF_UI_CAPTURE_BAR_NEUTRAL + packet.Worldstates.emplace_back(0xa3f, 0); // TF_UI_SHOW CAPTURE BAR + packet.Worldstates.emplace_back(0xa3e, 0); // TF_UI_TOWER_COUNT_H + packet.Worldstates.emplace_back(0xa3d, 5); // TF_UI_TOWER_COUNT_A + packet.Worldstates.emplace_back(0xa3c, 0); // TF_UI_TOWERS_CONTROLLED_DISPLAY + packet.Worldstates.emplace_back(0xa88, 0); // TF_TOWER_NUM_15 - SE Neutral + packet.Worldstates.emplace_back(0xa87, 0); // TF_TOWER_NUM_14 - SE Horde + packet.Worldstates.emplace_back(0xa86, 0); // TF_TOWER_NUM_13 - SE Alliance + packet.Worldstates.emplace_back(0xa85, 0); // TF_TOWER_NUM_12 - S Neutral + packet.Worldstates.emplace_back(0xa84, 0); // TF_TOWER_NUM_11 - S Horde + packet.Worldstates.emplace_back(0xa83, 0); // TF_TOWER_NUM_10 - S Alliance + packet.Worldstates.emplace_back(0xa82, 0); // TF_TOWER_NUM_09 - NE Neutral + packet.Worldstates.emplace_back(0xa81, 0); // TF_TOWER_NUM_08 - NE Horde + packet.Worldstates.emplace_back(0xa80, 0); // TF_TOWER_NUM_07 - NE Alliance + packet.Worldstates.emplace_back(0xa7f, 0); // TF_TOWER_NUM_16 - unk + packet.Worldstates.emplace_back(0xa7e, 0); // TF_TOWER_NUM_06 - N Neutral + packet.Worldstates.emplace_back(0xa7d, 0); // TF_TOWER_NUM_05 - N Horde + packet.Worldstates.emplace_back(0xa7c, 0); // TF_TOWER_NUM_04 - N Alliance + packet.Worldstates.emplace_back(0xa7b, 0); // TF_TOWER_NUM_03 - NW Alliance + packet.Worldstates.emplace_back(0xa7a, 0); // TF_TOWER_NUM_02 - NW Horde + packet.Worldstates.emplace_back(0xa79, 0); // TF_TOWER_NUM_01 - NW Neutral + packet.Worldstates.emplace_back(0x9d0, 5); // TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT + packet.Worldstates.emplace_back(0x9ce, 0); // TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT + packet.Worldstates.emplace_back(0x9cd, 0); // TF_UI_LOCKED_TIME_HOURS + packet.Worldstates.emplace_back(0x9cc, 0); // TF_UI_LOCKED_DISPLAY_NEUTRAL + packet.Worldstates.emplace_back(0xad0, 0); // TF_UI_LOCKED_DISPLAY_HORDE + packet.Worldstates.emplace_back(0xacf, 1); // TF_UI_LOCKED_DISPLAY_ALLIANCE } break; - case 3519: // Terokkar Forest - if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_TF) - pvp->FillInitialWorldStates(data); + case 3521: // Zangarmarsh + if (outdoorPvP && outdoorPvP->GetTypeId() == OUTDOOR_PVP_ZM) + outdoorPvP->FillInitialWorldStates(packet); else { - data << uint32(0xa41) << uint32(0x0); // 10 // 2625 capture bar pos - data << uint32(0xa40) << uint32(0x14); // 11 // 2624 capture bar neutral - data << uint32(0xa3f) << uint32(0x0); // 12 // 2623 show capture bar - data << uint32(0xa3e) << uint32(0x0); // 13 // 2622 horde towers controlled - data << uint32(0xa3d) << uint32(0x5); // 14 // 2621 ally towers controlled - data << uint32(0xa3c) << uint32(0x0); // 15 // 2620 show towers controlled - data << uint32(0xa88) << uint32(0x0); // 16 // 2696 SE Neu - data << uint32(0xa87) << uint32(0x0); // 17 // SE Horde - data << uint32(0xa86) << uint32(0x0); // 18 // SE Ally - data << uint32(0xa85) << uint32(0x0); // 19 //S Neu - data << uint32(0xa84) << uint32(0x0); // 20 S Horde - data << uint32(0xa83) << uint32(0x0); // 21 S Ally - data << uint32(0xa82) << uint32(0x0); // 22 NE Neu - data << uint32(0xa81) << uint32(0x0); // 23 NE Horde - data << uint32(0xa80) << uint32(0x0); // 24 NE Ally - data << uint32(0xa7e) << uint32(0x0); // 25 // 2686 N Neu - data << uint32(0xa7d) << uint32(0x0); // 26 N Horde - data << uint32(0xa7c) << uint32(0x0); // 27 N Ally - data << uint32(0xa7b) << uint32(0x0); // 28 NW Ally - data << uint32(0xa7a) << uint32(0x0); // 29 NW Horde - data << uint32(0xa79) << uint32(0x0); // 30 NW Neutral - data << uint32(0x9d0) << uint32(0x5); // 31 // 2512 locked time remaining seconds first digit - data << uint32(0x9ce) << uint32(0x0); // 32 // 2510 locked time remaining seconds second digit - data << uint32(0x9cd) << uint32(0x0); // 33 // 2509 locked time remaining minutes - data << uint32(0x9cc) << uint32(0x0); // 34 // 2508 neutral locked time show - data << uint32(0xad0) << uint32(0x0); // 35 // 2768 horde locked time show - data << uint32(0xacf) << uint32(0x1); // 36 // 2767 ally locked time show + packet.Worldstates.reserve(26); + packet.Worldstates.emplace_back(0x9e1, 0); // ZM_UNK_1 + packet.Worldstates.emplace_back(0x9e0, 0); // ZM_UNK_2 + packet.Worldstates.emplace_back(0x9df, 0); // ZM_UNK_3 + packet.Worldstates.emplace_back(0xa5d, 1); // ZM_WORLDSTATE_UNK_1 + packet.Worldstates.emplace_back(0xa5c, 0); // ZM_MAP_TOWER_EAST_N + packet.Worldstates.emplace_back(0xa5b, 1); // ZM_MAP_TOWER_EAST_H + packet.Worldstates.emplace_back(0xa5a, 0); // ZM_MAP_TOWER_EAST_A + packet.Worldstates.emplace_back(0xa59, 1); // ZM_MAP_GRAVEYARD_H - Twin spire graveyard horde + packet.Worldstates.emplace_back(0xa58, 0); // ZM_MAP_GRAVEYARD_A + packet.Worldstates.emplace_back(0xa57, 0); // ZM_MAP_GRAVEYARD_N + packet.Worldstates.emplace_back(0xa56, 0); // ZM_MAP_TOWER_WEST_N + packet.Worldstates.emplace_back(0xa55, 1); // ZM_MAP_TOWER_WEST_H + packet.Worldstates.emplace_back(0xa54, 0); // ZM_MAP_TOWER_WEST_A + packet.Worldstates.emplace_back(0x9e7, 0); // ZM_UNK_4 + packet.Worldstates.emplace_back(0x9e6, 0); // ZM_UNK_5 + packet.Worldstates.emplace_back(0x9e5, 0); // ZM_UNK_6 + packet.Worldstates.emplace_back(0xa00, 0); // ZM_UI_TOWER_EAST_N + packet.Worldstates.emplace_back(0x9ff, 1); // ZM_UI_TOWER_EAST_H + packet.Worldstates.emplace_back(0x9fe, 0); // ZM_UI_TOWER_EAST_A + packet.Worldstates.emplace_back(0x9fd, 0); // ZM_UI_TOWER_WEST_N + packet.Worldstates.emplace_back(0x9fc, 1); // ZM_UI_TOWER_WEST_H + packet.Worldstates.emplace_back(0x9fb, 0); // ZM_UI_TOWER_WEST_A + packet.Worldstates.emplace_back(0xa62, 0); // ZM_MAP_HORDE_FLAG_READY + packet.Worldstates.emplace_back(0xa61, 1); // ZM_MAP_HORDE_FLAG_NOT_READY + packet.Worldstates.emplace_back(0xa60, 1); // ZM_MAP_ALLIANCE_FLAG_NOT_READY + packet.Worldstates.emplace_back(0xa5f, 0); // ZM_MAP_ALLIANCE_FLAG_READY } break; - case 3521: // Zangarmarsh - if (pvp && pvp->GetTypeId() == OUTDOOR_PVP_ZM) - pvp->FillInitialWorldStates(data); + case 3698: // Nagrand Arena + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_NA) + battleground->FillInitialWorldStates(packet); else { - data << uint32(0x9e1) << uint32(0x0); // 10 //2529 - data << uint32(0x9e0) << uint32(0x0); // 11 - data << uint32(0x9df) << uint32(0x0); // 12 - data << uint32(0xa5d) << uint32(0x1); // 13 //2653 - data << uint32(0xa5c) << uint32(0x0); // 14 //2652 east beacon neutral - data << uint32(0xa5b) << uint32(0x1); // 15 horde - data << uint32(0xa5a) << uint32(0x0); // 16 ally - data << uint32(0xa59) << uint32(0x1); // 17 // 2649 Twin spire graveyard horde 12??? - data << uint32(0xa58) << uint32(0x0); // 18 ally 14 ??? - data << uint32(0xa57) << uint32(0x0); // 19 neutral 7??? - data << uint32(0xa56) << uint32(0x0); // 20 // 2646 west beacon neutral - data << uint32(0xa55) << uint32(0x1); // 21 horde - data << uint32(0xa54) << uint32(0x0); // 22 ally - data << uint32(0x9e7) << uint32(0x0); // 23 // 2535 - data << uint32(0x9e6) << uint32(0x0); // 24 - data << uint32(0x9e5) << uint32(0x0); // 25 - data << uint32(0xa00) << uint32(0x0); // 26 // 2560 - data << uint32(0x9ff) << uint32(0x1); // 27 - data << uint32(0x9fe) << uint32(0x0); // 28 - data << uint32(0x9fd) << uint32(0x0); // 29 - data << uint32(0x9fc) << uint32(0x1); // 30 - data << uint32(0x9fb) << uint32(0x0); // 31 - data << uint32(0xa62) << uint32(0x0); // 32 // 2658 - data << uint32(0xa61) << uint32(0x1); // 33 - data << uint32(0xa60) << uint32(0x1); // 34 - data << uint32(0xa5f) << uint32(0x0); // 35 + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0xa0f, 0); // BATTLEGROUND_NAGRAND_ARENA_GOLD + packet.Worldstates.emplace_back(0xa10, 0); // BATTLEGROUND_NAGRAND_ARENA_GREEN + packet.Worldstates.emplace_back(0xa11, 0); // BATTLEGROUND_NAGRAND_ARENA_SHOW } break; - case 3698: // Nagrand Arena - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_NA) - bg->FillInitialWorldStates(data); + case 3702: // Blade's Edge Arena + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_BE) + battleground->FillInitialWorldStates(packet); else { - data << uint32(0xa0f) << uint32(0x0); // 7 - data << uint32(0xa10) << uint32(0x0); // 8 - data << uint32(0xa11) << uint32(0x0); // 9 show + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0x9f0, 0); // BATTLEGROUND_BLADES_EDGE_ARENA_GOLD + packet.Worldstates.emplace_back(0x9f1, 0); // BATTLEGROUND_BLADES_EDGE_ARENA_GREEN + packet.Worldstates.emplace_back(0x9f3, 0); // BATTLEGROUND_BLADES_EDGE_ARENA_SHOW } break; - case 3702: // Blade's Edge Arena - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_BE) - bg->FillInitialWorldStates(data); + case 3968: // Ruins of Lordaeron + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_RL) + battleground->FillInitialWorldStates(packet); else { - data << uint32(0x9f0) << uint32(0x0); // 7 gold - data << uint32(0x9f1) << uint32(0x0); // 8 green - data << uint32(0x9f3) << uint32(0x0); // 9 show + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0xbb8, 0); // BATTELGROUND_RUINS_OF_LORDAERNON_GOLD + packet.Worldstates.emplace_back(0xbb9, 0); // BATTELGROUND_RUINS_OF_LORDAERNON_GREEN + packet.Worldstates.emplace_back(0xbba, 0); // BATTELGROUND_RUINS_OF_LORDAERNON_SHOW } break; - case 3968: // Ruins of Lordaeron - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_RL) - bg->FillInitialWorldStates(data); + case 4378: // Dalaran Sewers + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_DS) + battleground->FillInitialWorldStates(packet); else { - data << uint32(0xbb8) << uint32(0x0); // 7 gold - data << uint32(0xbb9) << uint32(0x0); // 8 green - data << uint32(0xbba) << uint32(0x0); // 9 show + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0xe11, 0); // ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD + packet.Worldstates.emplace_back(0xe10, 0); // ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN + packet.Worldstates.emplace_back(0xe1a, 0); // ARENA_WORLD_STATE_ALIVE_PLAYERS_SHOW } break; - case 4378: // Dalaran Sewers - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_DS) - bg->FillInitialWorldStates(data); - else - { - data << uint32(3601) << uint32(0x0); // 7 gold - data << uint32(3600) << uint32(0x0); // 8 green - data << uint32(3610) << uint32(0x0); // 9 show - } - break; - case 4384: // Strand of the Ancients - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_SA) - bg->FillInitialWorldStates(data); + case 4384: // Strand of the Ancients + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_SA) + battleground->FillInitialWorldStates(packet); else { + packet.Worldstates.reserve(24); // 1-3 A defend, 4-6 H defend, 7-9 unk defend, 1 - ok, 2 - half destroyed, 3 - destroyed - data << uint32(0xf09) << uint32(0x0); // 7 3849 Gate of Temple - data << uint32(0xe36) << uint32(0x0); // 8 3638 Gate of Yellow Moon - data << uint32(0xe27) << uint32(0x0); // 9 3623 Gate of Green Emerald - data << uint32(0xe24) << uint32(0x0); // 10 3620 Gate of Blue Sapphire - data << uint32(0xe21) << uint32(0x0); // 11 3617 Gate of Red Sun - data << uint32(0xe1e) << uint32(0x0); // 12 3614 Gate of Purple Ametyst + packet.Worldstates.emplace_back(0xf09, 0); // Gate of Temple + packet.Worldstates.emplace_back(0xe36, 0); // Gate of Yellow Moon + packet.Worldstates.emplace_back(0xe27, 0); // Gate of Green Emerald + packet.Worldstates.emplace_back(0xe24, 0); // Gate of Blue Sapphire + packet.Worldstates.emplace_back(0xe21, 0); // Gate of Red Sun + packet.Worldstates.emplace_back(0xe1e, 0); // Gate of Purple Ametyst + packet.Worldstates.emplace_back(0xdf3, 0); // bonus timer (1 - on, 0 - off) + packet.Worldstates.emplace_back(0xded, 0); // Horde Attacker + packet.Worldstates.emplace_back(0xdec, 0); // Alliance Attacker - data << uint32(0xdf3) << uint32(0x0); // 13 3571 bonus timer (1 - on, 0 - off) - data << uint32(0xded) << uint32(0x0); // 14 3565 Horde Attacker - data << uint32(0xdec) << uint32(0x0); // 15 3564 Alliance Attacker - // End Round (timer), better explain this by example, eg. ends in 19:59 -> A:BC - data << uint32(0xde9) << uint32(0x0); // 16 3561 C - data << uint32(0xde8) << uint32(0x0); // 17 3560 B - data << uint32(0xde7) << uint32(0x0); // 18 3559 A - data << uint32(0xe35) << uint32(0x0); // 19 3637 East g - Horde control - data << uint32(0xe34) << uint32(0x0); // 20 3636 West g - Horde control - data << uint32(0xe33) << uint32(0x0); // 21 3635 South g - Horde control - data << uint32(0xe32) << uint32(0x0); // 22 3634 East g - Alliance control - data << uint32(0xe31) << uint32(0x0); // 23 3633 West g - Alliance control - data << uint32(0xe30) << uint32(0x0); // 24 3632 South g - Alliance control - data << uint32(0xe2f) << uint32(0x0); // 25 3631 Chamber of Ancients - Horde control - data << uint32(0xe2e) << uint32(0x0); // 26 3630 Chamber of Ancients - Alliance control - data << uint32(0xe2d) << uint32(0x0); // 27 3629 Beach1 - Horde control - data << uint32(0xe2c) << uint32(0x0); // 28 3628 Beach2 - Horde control - data << uint32(0xe2b) << uint32(0x0); // 29 3627 Beach1 - Alliance control - data << uint32(0xe2a) << uint32(0x0); // 30 3626 Beach2 - Alliance control - // and many unks... - } - break; - case 4406: // Ring of Valor - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_RV) - bg->FillInitialWorldStates(data); - else - { - data << uint32(0xe10) << uint32(0x0); // 7 gold - data << uint32(0xe11) << uint32(0x0); // 8 green - data << uint32(0xe1a) << uint32(0x0); // 9 show - } - break; - case 4710: // Isle of Conquest - if (bg && bg->GetBgTypeID(true) == BATTLEGROUND_IC) - bg->FillInitialWorldStates(data); - else - { - data << uint32(4221) << uint32(1); // 7 BG_IC_ALLIANCE_RENFORT_SET - data << uint32(4222) << uint32(1); // 8 BG_IC_HORDE_RENFORT_SET - data << uint32(4226) << uint32(300); // 9 BG_IC_ALLIANCE_RENFORT - data << uint32(4227) << uint32(300); // 10 BG_IC_HORDE_RENFORT - data << uint32(4322) << uint32(1); // 11 BG_IC_GATE_FRONT_H_WS_OPEN - data << uint32(4321) << uint32(1); // 12 BG_IC_GATE_WEST_H_WS_OPEN - data << uint32(4320) << uint32(1); // 13 BG_IC_GATE_EAST_H_WS_OPEN - data << uint32(4323) << uint32(1); // 14 BG_IC_GATE_FRONT_A_WS_OPEN - data << uint32(4324) << uint32(1); // 15 BG_IC_GATE_WEST_A_WS_OPEN - data << uint32(4325) << uint32(1); // 16 BG_IC_GATE_EAST_A_WS_OPEN - data << uint32(4317) << uint32(1); // 17 unknown + // End Round timer, example: 19:59 -> A:BC + packet.Worldstates.emplace_back(0xde9, 0); // C + packet.Worldstates.emplace_back(0xde8, 0); // B + packet.Worldstates.emplace_back(0xde7, 0); // A - data << uint32(4301) << uint32(1); // 18 BG_IC_DOCKS_UNCONTROLLED - data << uint32(4296) << uint32(1); // 19 BG_IC_HANGAR_UNCONTROLLED - data << uint32(4306) << uint32(1); // 20 BG_IC_QUARRY_UNCONTROLLED - data << uint32(4311) << uint32(1); // 21 BG_IC_REFINERY_UNCONTROLLED - data << uint32(4294) << uint32(1); // 22 BG_IC_WORKSHOP_UNCONTROLLED - data << uint32(4243) << uint32(1); // 23 unknown - data << uint32(4345) << uint32(1); // 24 unknown + packet.Worldstates.emplace_back(0xe35, 0); // BG_SA_CENTER_GY_ALLIANCE + packet.Worldstates.emplace_back(0xe34, 0); // BG_SA_RIGHT_GY_ALLIANCE + packet.Worldstates.emplace_back(0xe33, 0); // BG_SA_LEFT_GY_ALLIANCE + packet.Worldstates.emplace_back(0xe32, 0); // BG_SA_CENTER_GY_HORDE + packet.Worldstates.emplace_back(0xe31, 0); // BG_SA_LEFT_GY_HORDE + packet.Worldstates.emplace_back(0xe30, 0); // BG_SA_RIGHT_GY_HORDE + packet.Worldstates.emplace_back(0xe2f, 0); // BG_SA_HORDE_DEFENCE_TOKEN + packet.Worldstates.emplace_back(0xe2e, 0); // BG_SA_ALLIANCE_DEFENCE_TOKEN + packet.Worldstates.emplace_back(0xe2d, 0); // BG_SA_LEFT_ATT_TOKEN_HRD + packet.Worldstates.emplace_back(0xe2c, 0); // BG_SA_RIGHT_ATT_TOKEN_HRD + packet.Worldstates.emplace_back(0xe2b, 0); // BG_SA_RIGHT_ATT_TOKEN_ALL + packet.Worldstates.emplace_back(0xe2a, 0); // BG_SA_LEFT_ATT_TOKEN_ALL + // missing unknowns } break; - // The Ruby Sanctum - case 4987: - if (instance && mapid == 724) - instance->FillInitialWorldStates(data); + case 4406: // Ring of Valor + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_RV) + battleground->FillInitialWorldStates(packet); else { - data << uint32(5049) << uint32(50); // 9 WORLDSTATE_CORPOREALITY_MATERIAL - data << uint32(5050) << uint32(50); // 10 WORLDSTATE_CORPOREALITY_TWILIGHT - data << uint32(5051) << uint32(0); // 11 WORLDSTATE_CORPOREALITY_TOGGLE + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0xe10, 0); // ARENA_WORLD_STATE_ALIVE_PLAYERS_GREEN + packet.Worldstates.emplace_back(0xe11, 0); // ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD + packet.Worldstates.emplace_back(0xe1a, 0); // ARENA_WORLD_STATE_ALIVE_PLAYERS_SHOW } break; - // Icecrown Citadel - case 4812: - if (instance && mapid == 631) - instance->FillInitialWorldStates(data); + case 4710: // Isle of Conquest + if (battleground && battleground->GetBgTypeID(true) == BATTLEGROUND_IC) + battleground->FillInitialWorldStates(packet); else { - data << uint32(4903) << uint32(0); // 9 WORLDSTATE_SHOW_TIMER (Blood Quickening weekly) - data << uint32(4904) << uint32(30); // 10 WORLDSTATE_EXECUTION_TIME - data << uint32(4940) << uint32(0); // 11 WORLDSTATE_SHOW_ATTEMPTS - data << uint32(4941) << uint32(50); // 12 WORLDSTATE_ATTEMPTS_REMAINING - data << uint32(4942) << uint32(50); // 13 WORLDSTATE_ATTEMPTS_MAX + packet.Worldstates.reserve(18); + packet.Worldstates.emplace_back(0x107d, 1); // BG_IC_ALLIANCE_RENFORT_SET + packet.Worldstates.emplace_back(0x107e, 1); // BG_IC_HORDE_RENFORT_SET + packet.Worldstates.emplace_back(0x1082, 300); // BG_IC_ALLIANCE_RENFORT + packet.Worldstates.emplace_back(0x1083, 300); // BG_IC_HORDE_RENFORT + packet.Worldstates.emplace_back(0x10e2, 1); // BG_IC_GATE_FRONT_H_WS_OPEN + packet.Worldstates.emplace_back(0x10e1, 1); // BG_IC_GATE_WEST_H_WS_OPEN + packet.Worldstates.emplace_back(0x10e0, 1); // BG_IC_GATE_EAST_H_WS_OPEN + packet.Worldstates.emplace_back(0x10e3, 1); // BG_IC_GATE_FRONT_A_WS_OPEN + packet.Worldstates.emplace_back(0x10e4, 1); // BG_IC_GATE_WEST_A_WS_OPEN + packet.Worldstates.emplace_back(0x10e5, 1); // BG_IC_GATE_EAST_A_WS_OPEN + packet.Worldstates.emplace_back(0x10dd, 1); // unk + packet.Worldstates.emplace_back(0x10cd, 1); // BG_IC_DOCKS_UNCONTROLLED + packet.Worldstates.emplace_back(0x10c8, 1); // BG_IC_HANGAR_UNCONTROLLED + packet.Worldstates.emplace_back(0x10d2, 1); // BG_IC_QUARRY_UNCONTROLLED + packet.Worldstates.emplace_back(0x10d7, 1); // BG_IC_REFINERY_UNCONTROLLED + packet.Worldstates.emplace_back(0x10c6, 1); // BG_IC_WORKSHOP_UNCONTROLLED + packet.Worldstates.emplace_back(0x1093, 1); // unk + packet.Worldstates.emplace_back(0x10f9, 1); // unk } break; - // The Culling of Stratholme - case 4100: - if (instance && mapid == 595) - instance->FillInitialWorldStates(data); + case 4987: // The Ruby Sanctum + if (instance) + instance->FillInitialWorldStates(packet); else { - data << uint32(3479) << uint32(0); // 9 WORLDSTATE_SHOW_CRATES - data << uint32(3480) << uint32(0); // 10 WORLDSTATE_CRATES_REVEALED - data << uint32(3504) << uint32(0); // 11 WORLDSTATE_WAVE_COUNT - data << uint32(3931) << uint32(25); // 12 WORLDSTATE_TIME_GUARDIAN - data << uint32(3932) << uint32(0); // 13 WORLDSTATE_TIME_GUARDIAN_SHOW + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0x13b9, 50); // WORLDSTATE_CORPOREALITY_MATERIAL + packet.Worldstates.emplace_back(0x13ba, 50); // WORLDSTATE_CORPOREALITY_TWILIGHT + packet.Worldstates.emplace_back(0x13bb, 0); // WORLDSTATE_CORPOREALITY_TOGGLE } break; - // The Oculus - case 4228: - if (instance && mapid == 578) - instance->FillInitialWorldStates(data); + case 4812: // Icecrown Citadel + if (instance && mapId == 631) + instance->FillInitialWorldStates(packet); else { - data << uint32(3524) << uint32(0); // 9 WORLD_STATE_CENTRIFUGE_CONSTRUCT_SHOW - data << uint32(3486) << uint32(0); // 10 WORLD_STATE_CENTRIFUGE_CONSTRUCT_AMOUNT + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(0x1327, 0); // WORLDSTATE_SHOW_TIMER (Blood Quickening weekly) + packet.Worldstates.emplace_back(0x1328, 30); // WORLDSTATE_EXECUTION_TIME + packet.Worldstates.emplace_back(0x134c, 0); // WORLDSTATE_SHOW_ATTEMPTS + packet.Worldstates.emplace_back(0x134d, 50); // WORLDSTATE_ATTEMPTS_REMAINING + packet.Worldstates.emplace_back(0x134e, 50); // WORLDSTATE_ATTEMPTS_MAX } break; - // Ulduar - case 4273: - if (instance && mapid == 603) - instance->FillInitialWorldStates(data); + case 4100: // The Culling of Stratholme + if (instance && mapId == 595) + instance->FillInitialWorldStates(packet); else { - data << uint32(4132) << uint32(0); // 9 WORLDSTATE_ALGALON_TIMER_ENABLED - data << uint32(4131) << uint32(0); // 10 WORLDSTATE_ALGALON_DESPAWN_TIMER + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(0xd97, 0); // WORLDSTATE_SHOW_CRATES + packet.Worldstates.emplace_back(0xd98, 0); // WORLDSTATE_CRATES_REVEALED + packet.Worldstates.emplace_back(0xdb0, 0); // WORLDSTATE_WAVE_COUNT + packet.Worldstates.emplace_back(0xf5b, 25); // WORLDSTATE_TIME_GUARDIAN + packet.Worldstates.emplace_back(0xf5c, 0); // WORLDSTATE_TIME_GUARDIAN_SHOW } break; - // Halls of Refection - case 4820: - if (instance && mapid == 668) - instance->FillInitialWorldStates(data); + case 4228: // The Oculus + if (instance && mapId == 578) + instance->FillInitialWorldStates(packet); else { - data << uint32(4884) << uint32(0); // 9 WORLD_STATE_HOR_WAVES_ENABLED - data << uint32(4882) << uint32(0); // 10 WORLD_STATE_HOR_WAVE_COUNT + packet.Worldstates.reserve(2); + packet.Worldstates.emplace_back(0xdc4, 0); // WORLD_STATE_CENTRIFUGE_CONSTRUCT_SHOW + packet.Worldstates.emplace_back(0xd9e, 0); // WORLD_STATE_CENTRIFUGE_CONSTRUCT_AMOUNT } break; - // Scarlet Enclave (DK starting zone) - case 4298: + case 4273: // Ulduar + if (instance && mapId == 603) + instance->FillInitialWorldStates(packet); + else + { + packet.Worldstates.reserve(2); + packet.Worldstates.emplace_back(0x1024, 0); // WORLDSTATE_ALGALON_TIMER_ENABLED + packet.Worldstates.emplace_back(0x1023, 0); // WORLDSTATE_ALGALON_DESPAWN_TIMER + } + break; + case 4415: // Violet Hold + if (instance) + instance->FillInitialWorldStates(packet); + else + { + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(0xee8, 0); // WORLD_STATE_VH_SHOW + packet.Worldstates.emplace_back(0xee7, 100); // WORLD_STATE_VH_PRISON_STATE + packet.Worldstates.emplace_back(0xee2, 0); // WORLD_STATE_VH_WAVE_COUNT + } + break; + case 4820: // Halls of Refection + if (instance && mapId == 668) + instance->FillInitialWorldStates(packet); + else + { + packet.Worldstates.reserve(2); + packet.Worldstates.emplace_back(0x1314, 0); // WORLD_STATE_HOR_WAVES_ENABLED + packet.Worldstates.emplace_back(0x1312, 0); // WORLD_STATE_HOR_WAVE_COUNT + } + break; + case 4298: // Scarlet Enclave (DK starting zone) // Get Mograine, GUID and ENTRY should NEVER change if (Creature* mograine = ObjectAccessor::GetCreature(*this, ObjectGuid::Create(29173, 130956))) { if (CreatureAI* mograineAI = mograine->AI()) { - data << uint32(3590) << uint32(mograineAI->GetData(3590)); - data << uint32(3591) << uint32(mograineAI->GetData(3591)); - data << uint32(3592) << uint32(mograineAI->GetData(3592)); - data << uint32(3603) << uint32(mograineAI->GetData(3603)); - data << uint32(3604) << uint32(mograineAI->GetData(3604)); - data << uint32(3605) << uint32(mograineAI->GetData(3605)); + packet.Worldstates.reserve(6); + packet.Worldstates.emplace_back(0xe06, mograineAI->GetData(3590)); + packet.Worldstates.emplace_back(0xe07, mograineAI->GetData(3591)); + packet.Worldstates.emplace_back(0xe08, mograineAI->GetData(3592)); + packet.Worldstates.emplace_back(0xe13, mograineAI->GetData(3603)); + packet.Worldstates.emplace_back(0xe14, mograineAI->GetData(3604)); + packet.Worldstates.emplace_back(0xe15, mograineAI->GetData(3605)); } } break; - // Wintergrasp - case 4197: - if (bf && bf->GetTypeId() == BATTLEFIELD_WG) + case 4197: // Wintergrasp + if (battlefield && battlefield->GetTypeId() == BATTLEFIELD_WG) { - bf->FillInitialWorldStates(data); + battlefield->FillInitialWorldStates(packet); break; } [[fallthrough]]; default: - data << uint32(0x914) << uint32(0x0); // 7 - data << uint32(0x913) << uint32(0x0); // 8 - data << uint32(0x912) << uint32(0x0); // 9 - data << uint32(0x915) << uint32(0x0); // 10 + packet.Worldstates.reserve(4); + packet.Worldstates.emplace_back(0x914, 0); + packet.Worldstates.emplace_back(0x913, 0); + packet.Worldstates.emplace_back(0x912, 0); + packet.Worldstates.emplace_back(0x915, 0); break; + } } } - sWorldState->FillInitialWorldStates(data, zoneid, areaid); - - uint16 length = (data.wpos() - countPos) / 8; - data.put(countPos, length); - - GetSession()->SendPacket(&data); + sWorldState->FillInitialWorldStates(packet, zoneId, areaId); + SendDirectMessage(packet.Write()); SendBGWeekendWorldStates(); SendBattlefieldWorldStates(); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 3c3b5781d..22e694143 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -65,7 +65,7 @@ class SpellCastTargets; class UpdateMask; typedef std::deque PlayerMails; -typedef void(*bgZoneRef)(Battleground*, WorldPacket&); +typedef void(*bgZoneRef)(Battleground*, WorldPackets::WorldState::InitWorldStates&); #define PLAYER_MAX_SKILLS 127 #define PLAYER_MAX_DAILY_QUESTS 25 @@ -2236,7 +2236,7 @@ public: void SetEquipmentSet(uint32 index, EquipmentSet eqset); void DeleteEquipmentSet(uint64 setGuid); - void SendInitWorldStates(uint32 zone, uint32 area); + void SendInitWorldStates(uint32 zoneId, uint32 areaId); void SendUpdateWorldState(uint32 variable, uint32 value) const; void SendDirectMessage(WorldPacket const* data) const; void SendBGWeekendWorldStates(); diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 89246ed96..86ec413a9 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -23,6 +23,7 @@ #include "TaskScheduler.h" #include "World.h" #include "ZoneScript.h" +#include "WorldStatePackets.h" #include #define OUT_SAVE_INST_DATA LOG_DEBUG("scripts.ai", "Saving Instance Data for Instance {} (Map {}, Instance Id {})", instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) @@ -260,7 +261,7 @@ public: void SendEncounterUnit(uint32 type, Unit* unit = nullptr, uint8 param1 = 0, uint8 param2 = 0); - virtual void FillInitialWorldStates(WorldPacket& /*data*/) {} + virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) { } uint32 GetEncounterCount() const { return bosses.size(); } diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h index 1d4c8c9e7..fe773f1d3 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvP.h +++ b/src/server/game/OutdoorPvP/OutdoorPvP.h @@ -20,6 +20,7 @@ #include "SharedDefines.h" #include "ZoneScript.h" +#include "WorldStatePackets.h" #include class GameObject; @@ -92,7 +93,7 @@ public: explicit OPvPCapturePoint(OutdoorPvP* pvp); virtual ~OPvPCapturePoint() = default; - virtual void FillInitialWorldStates(WorldPacket& /*data*/) {} + virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) { } // send world state update to all players present void SendUpdateWorldState(uint32 field, uint32 value); @@ -199,7 +200,7 @@ public: typedef std::pair GoScriptPair; typedef std::pair CreatureScriptPair; - virtual void FillInitialWorldStates(WorldPacket& /*data*/) {} + virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& /*packet*/) {} // called when a player triggers an area trigger virtual bool HandleAreaTrigger(Player* player, uint32 trigger); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index bd7d556c3..4d193306c 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -681,7 +681,7 @@ void WorldSession::LogoutPlayer(bool save) if (!_player->IsBeingTeleportedFar() && !_player->m_InstanceValid && !_player->IsGameMaster()) _player->RepopAtGraveyard(); - // Repop at GraveYard or other player far teleport will prevent saving player because of not present map + // Repop at Graveyard or other player far teleport will prevent saving player because of not present map // Teleport player immediately for correct player save while (_player && _player->IsBeingTeleportedFar()) HandleMoveWorldportAck(); diff --git a/src/server/game/World/WorldState.cpp b/src/server/game/World/WorldState.cpp index d2fe8f64f..dcec3b958 100644 --- a/src/server/game/World/WorldState.cpp +++ b/src/server/game/World/WorldState.cpp @@ -1035,7 +1035,7 @@ uint32 SunsReachReclamationData::GetSunwellGatePercentage(uint32 gate) return percentage < 0 ? 0 : uint32(percentage); } -void WorldState::FillInitialWorldStates(ByteBuffer& data, uint32 zoneId, uint32 /*areaId*/) +void WorldState::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet, uint32 zoneId, uint32 /*areaId*/) { switch (zoneId) { @@ -1048,38 +1048,38 @@ void WorldState::FillInitialWorldStates(ByteBuffer& data, uint32 zoneId, uint32 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); + packet.Worldstates.emplace_back(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); + packet.Worldstates.emplace_back(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); + packet.Worldstates.emplace_back(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); + packet.Worldstates.emplace_back(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); + packet.Worldstates.emplace_back(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); + packet.Worldstates.emplace_back(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; + packet.Worldstates.emplace_back(WORLD_STATE_QUEL_DANAS_ANVIL, m_sunsReachData.GetSubPhasePercentage(SUBPHASE_ANVIL)); + packet.Worldstates.emplace_back(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); + packet.Worldstates.emplace_back(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); + packet.Worldstates.emplace_back(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); + packet.Worldstates.emplace_back(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 81a084e34..b6198a7b9 100644 --- a/src/server/game/World/WorldState.h +++ b/src/server/game/World/WorldState.h @@ -206,7 +206,7 @@ class WorldState void AddSunwellGateProgress(uint32 questId); void AddSunsReachProgress(uint32 questId); std::string GetSunsReachPrintout(); - void FillInitialWorldStates(ByteBuffer& data, uint32 zoneId, uint32 areaId); + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet, uint32 zoneId, uint32 /*areaId*/); void HandleSunsReachPhaseTransition(uint32 newPhase); void HandleSunsReachSubPhaseTransition(int32 subPhaseMask, bool initial = false); void SetSunsReachCounter(SunsReachCounters index, uint32 value); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp index c6a17339a..8d8d7eb23 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp @@ -22,6 +22,7 @@ #include "ScriptedCreature.h" #include "SpellInfo.h" #include "TemporarySummon.h" +#include "WorldStatePackets.h" #include "culling_of_stratholme.h" class instance_culling_of_stratholme : public InstanceMapScript @@ -53,13 +54,14 @@ public: return false; } - void FillInitialWorldStates(WorldPacket& data) override + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override { - data << uint32(WORLDSTATE_SHOW_CRATES) << uint32(0); - data << uint32(WORLDSTATE_CRATES_REVEALED) << uint32(_crateCount); - data << uint32(WORLDSTATE_WAVE_COUNT) << uint32(0); - data << uint32(WORLDSTATE_TIME_GUARDIAN) << uint32(25); - data << uint32(WORLDSTATE_TIME_GUARDIAN_SHOW) << uint32(0); + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(WORLDSTATE_SHOW_CRATES, 0); + packet.Worldstates.emplace_back(WORLDSTATE_CRATES_REVEALED, _crateCount); + packet.Worldstates.emplace_back(WORLDSTATE_WAVE_COUNT, 0); + packet.Worldstates.emplace_back(WORLDSTATE_TIME_GUARDIAN, 25); + packet.Worldstates.emplace_back(WORLDSTATE_TIME_GUARDIAN_SHOW, 0); } void OnPlayerEnter(Player* plr) override diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp index d70eb3b62..b1ed2bf5d 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp @@ -19,10 +19,11 @@ #include "InstanceMapScript.h" #include "InstanceScript.h" #include "Player.h" +#include "SpellScript.h" #include "SpellScriptLoader.h" #include "WorldPacket.h" +#include "WorldStatePackets.h" #include "ruby_sanctum.h" -#include "SpellScript.h" BossBoundaryData const boundaries = { @@ -217,11 +218,12 @@ public: return true; } - void FillInitialWorldStates(WorldPacket& data) override + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override { - data << uint32(WORLDSTATE_CORPOREALITY_MATERIAL) << uint32(50); - data << uint32(WORLDSTATE_CORPOREALITY_TWILIGHT) << uint32(50); - data << uint32(WORLDSTATE_CORPOREALITY_TOGGLE) << uint32(0); + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(WORLDSTATE_CORPOREALITY_MATERIAL, 50); + packet.Worldstates.emplace_back(WORLDSTATE_CORPOREALITY_TWILIGHT, 50); + packet.Worldstates.emplace_back(WORLDSTATE_CORPOREALITY_TOGGLE, 0); } protected: diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp index fd43fce38..34c096d0f 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp @@ -15,12 +15,12 @@ * with this program. If not, see . */ +#include "Group.h" #include "InstanceMapScript.h" +#include "InstanceScript.h" #include "MapMgr.h" #include "Transport.h" #include "halls_of_reflection.h" -#include "InstanceScript.h" -#include "Group.h" class UtherBatteredHiltEvent : public BasicEvent { diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index e62411087..fa49b8e2a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -230,16 +230,14 @@ public: IsSindragosaIntroDone = false; } - void FillInitialWorldStates(WorldPacket& data) override + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override { - if (instance->IsHeroic()) - { - data << uint32(WORLDSTATE_SHOW_TIMER) << uint32(BloodQuickeningState == IN_PROGRESS); - data << uint32(WORLDSTATE_EXECUTION_TIME) << uint32(BloodQuickeningMinutes); - data << uint32(WORLDSTATE_SHOW_ATTEMPTS) << uint32(1); - data << uint32(WORLDSTATE_ATTEMPTS_REMAINING) << uint32(HeroicAttempts); - data << uint32(WORLDSTATE_ATTEMPTS_MAX) << uint32(MaxHeroicAttempts); - } + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(WORLDSTATE_SHOW_TIMER, BloodQuickeningState == IN_PROGRESS ? 1 : 0); + packet.Worldstates.emplace_back(WORLDSTATE_EXECUTION_TIME, BloodQuickeningMinutes); + packet.Worldstates.emplace_back(WORLDSTATE_SHOW_ATTEMPTS, 1); // instance->IsHeroic() ? 1 : 0 + packet.Worldstates.emplace_back(WORLDSTATE_ATTEMPTS_REMAINING, HeroicAttempts); + packet.Worldstates.emplace_back(WORLDSTATE_ATTEMPTS_MAX, MaxHeroicAttempts); } void OnPlayerAreaUpdate(Player* player, uint32 /*oldArea*/, uint32 newArea) override diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index 33069679b..a9be11304 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -20,6 +20,7 @@ #include "LFGMgr.h" #include "Player.h" #include "ScriptedCreature.h" +#include "WorldStatePackets.h" #include "oculus.h" class instance_oculus : public InstanceMapScript diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 04ab6e9a7..a9de02208 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -22,6 +22,7 @@ #include "ScriptedCreature.h" #include "Transport.h" #include "WorldPacket.h" +#include "WorldStatePackets.h" #include "ulduar.h" class instance_ulduar : public InstanceMapScript @@ -169,10 +170,11 @@ public: m_mimironTramUsed = false; } - void FillInitialWorldStates(WorldPacket& packet) override + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override { - packet << uint32(WORLD_STATE_ALGALON_TIMER_ENABLED) << uint32(m_algalonTimer && m_algalonTimer <= 60); - packet << uint32(WORLD_STATE_ALGALON_DESPAWN_TIMER) << uint32(std::min(m_algalonTimer, 60)); + packet.Worldstates.reserve(2); + packet.Worldstates.emplace_back(WORLD_STATE_ALGALON_TIMER_ENABLED, (m_algalonTimer && m_algalonTimer <= 60) ? 1 : 0); + packet.Worldstates.emplace_back(WORLD_STATE_ALGALON_DESPAWN_TIMER, std::min(m_algalonTimer, 60)); } void OnPlayerEnter(Player* player) override diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp index 33a1e63ee..e2c7d86e5 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp @@ -28,6 +28,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSessionMgr.h" +#include "WorldStatePackets.h" OPvPCapturePointEP_EWT::OPvPCapturePointEP_EWT(OutdoorPvP* pvp) : OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_UnitsSummonedSideId(TEAM_NEUTRAL) @@ -41,12 +42,12 @@ void OPvPCapturePointEP_EWT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_NEUTRAL); } @@ -59,14 +60,14 @@ void OPvPCapturePointEP_EWT::ChangeState() artkit = 2; SummonSupportUnitAtNorthpassTower(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_ALLIANCE); - if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; SummonSupportUnitAtNorthpassTower(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_HORDE); - if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -108,13 +109,14 @@ void OPvPCapturePointEP_EWT::SendChangePhase() SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, _neutralValuePct); } -void OPvPCapturePointEP_EWT::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointEP_EWT::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << EP_EWT_A << uint32(bool(m_TowerState & EP_TS_A)); - data << EP_EWT_H << uint32(bool(m_TowerState & EP_TS_H)); - data << EP_EWT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); - data << EP_EWT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); - data << EP_EWT_N << uint32(bool(m_TowerState & EP_TS_N)); + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(EP_EWT_A, (m_TowerState & EP_TS_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_EWT_H, (m_TowerState & EP_TS_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_EWT_N_A, (m_TowerState & EP_TS_N_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_EWT_N_H, (m_TowerState & EP_TS_N_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_EWT_N, (m_TowerState & EP_TS_N) != 0 ? 1 : 0); } void OPvPCapturePointEP_EWT::UpdateTowerState() @@ -173,12 +175,12 @@ void OPvPCapturePointEP_NPT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_NEUTRAL); } @@ -191,14 +193,14 @@ void OPvPCapturePointEP_NPT::ChangeState() artkit = 2; SummonGO(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_ALLIANCE); - if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; SummonGO(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_HORDE); - if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -250,13 +252,14 @@ void OPvPCapturePointEP_NPT::SendChangePhase() SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, _neutralValuePct); } -void OPvPCapturePointEP_NPT::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointEP_NPT::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << EP_NPT_A << uint32(bool(m_TowerState & EP_TS_A)); - data << EP_NPT_H << uint32(bool(m_TowerState & EP_TS_H)); - data << EP_NPT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); - data << EP_NPT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); - data << EP_NPT_N << uint32(bool(m_TowerState & EP_TS_N)); + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(EP_NPT_A, (m_TowerState & EP_TS_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_NPT_H, (m_TowerState & EP_TS_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_NPT_N_A, (m_TowerState & EP_TS_N_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_NPT_N_H, (m_TowerState & EP_TS_N_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_NPT_N, (m_TowerState & EP_TS_N) != 0 ? 1 : 0); } void OPvPCapturePointEP_NPT::UpdateTowerState() @@ -315,12 +318,12 @@ void OPvPCapturePointEP_CGT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_NEUTRAL); } @@ -333,14 +336,14 @@ void OPvPCapturePointEP_CGT::ChangeState() artkit = 2; LinkGraveyard(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_ALLIANCE); - if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; LinkGraveyard(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_HORDE); - if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -382,13 +385,14 @@ void OPvPCapturePointEP_CGT::SendChangePhase() SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, _neutralValuePct); } -void OPvPCapturePointEP_CGT::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointEP_CGT::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << EP_CGT_A << uint32(bool(m_TowerState & EP_TS_A)); - data << EP_CGT_H << uint32(bool(m_TowerState & EP_TS_H)); - data << EP_CGT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); - data << EP_CGT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); - data << EP_CGT_N << uint32(bool(m_TowerState & EP_TS_N)); + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(EP_CGT_A, (m_TowerState & EP_TS_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_CGT_H, (m_TowerState & EP_TS_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_CGT_N_A, (m_TowerState & EP_TS_N_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_CGT_N_H, (m_TowerState & EP_TS_N_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_CGT_N, (m_TowerState & EP_TS_N) != 0 ? 1 : 0); } void OPvPCapturePointEP_CGT::UpdateTowerState() @@ -423,8 +427,8 @@ void OPvPCapturePointEP_CGT::LinkGraveyard(TeamId teamId) { if (m_GraveyardSide != teamId) { - sGraveyard->RemoveGraveyardLink(EP_GraveYardId, EP_GraveYardZone, m_GraveyardSide, false); - sGraveyard->AddGraveyardLink(EP_GraveYardId, EP_GraveYardZone, teamId, false); + sGraveyard->RemoveGraveyardLink(EP_GraveyardId, EP_GraveyardZone, m_GraveyardSide, false); + sGraveyard->AddGraveyardLink(EP_GraveyardId, EP_GraveyardZone, teamId, false); m_GraveyardSide = teamId; } } @@ -442,12 +446,12 @@ void OPvPCapturePointEP_PWT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_NEUTRAL); } @@ -460,14 +464,14 @@ void OPvPCapturePointEP_PWT::ChangeState() SummonFlightMaster(TEAM_ALLIANCE); artkit = 2; ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_ALLIANCE); - if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; SummonFlightMaster(TEAM_HORDE); artkit = 1; ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_HORDE); - if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveyardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -519,13 +523,14 @@ void OPvPCapturePointEP_PWT::SendChangePhase() SendUpdateWorldState(EP_UI_TOWER_SLIDER_N, _neutralValuePct); } -void OPvPCapturePointEP_PWT::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointEP_PWT::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << EP_PWT_A << uint32(bool(m_TowerState & EP_TS_A)); - data << EP_PWT_H << uint32(bool(m_TowerState & EP_TS_H)); - data << EP_PWT_N_A << uint32(bool(m_TowerState & EP_TS_N_A)); - data << EP_PWT_N_H << uint32(bool(m_TowerState & EP_TS_N_H)); - data << EP_PWT_N << uint32(bool(m_TowerState & EP_TS_N)); + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(EP_PWT_A, (m_TowerState & EP_TS_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_PWT_H, (m_TowerState & EP_TS_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_PWT_N_A, (m_TowerState & EP_TS_N_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_PWT_N_H, (m_TowerState & EP_TS_N_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(EP_PWT_N, (m_TowerState & EP_TS_N) != 0 ? 1 : 0); } void OPvPCapturePointEP_PWT::UpdateTowerState() @@ -712,16 +717,18 @@ void OutdoorPvPEP::SetControlledState(uint32 index, TeamId teamId) EP_ControlsId[index] = teamId; } -void OutdoorPvPEP::FillInitialWorldStates(WorldPacket& data) +void OutdoorPvPEP::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << EP_UI_TOWER_COUNT_A << m_AllianceTowersControlled; - data << EP_UI_TOWER_COUNT_H << m_HordeTowersControlled; - data << EP_UI_TOWER_SLIDER_DISPLAY << uint32(0); - data << EP_UI_TOWER_SLIDER_POS << uint32(50); - data << EP_UI_TOWER_SLIDER_N << uint32(100); + packet.Worldstates.reserve(5); + packet.Worldstates.emplace_back(EP_UI_TOWER_COUNT_A, m_AllianceTowersControlled); + packet.Worldstates.emplace_back(EP_UI_TOWER_COUNT_H, m_HordeTowersControlled); + packet.Worldstates.emplace_back(EP_UI_TOWER_SLIDER_DISPLAY, 0); + packet.Worldstates.emplace_back(EP_UI_TOWER_SLIDER_POS, 50); + packet.Worldstates.emplace_back(EP_UI_TOWER_SLIDER_N, 100); + for (OPvPCapturePointMap::iterator itr = _capturePoints.begin(); itr != _capturePoints.end(); ++itr) { - itr->second->FillInitialWorldStates(data); + itr->second->FillInitialWorldStates(packet); } } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.h b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.h index 84f9306ab..b6e5fab91 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.h @@ -25,9 +25,9 @@ const uint32 EP_AllianceBuffs[4] = {11413, 11414, 11415, 1386}; const uint32 EP_HordeBuffs[4] = {30880, 30683, 30682, 29520}; -const uint32 EP_GraveYardZone = 139; +const uint32 EP_GraveyardZone = 139; -const uint32 EP_GraveYardId = 927; +const uint32 EP_GraveyardId = 927; const uint8 EPBuffZonesNum = 3; @@ -191,7 +191,7 @@ public: void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; // used when player is activated/inactivated in the area bool HandlePlayerEnter(Player* player) override; @@ -217,7 +217,7 @@ public: void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; // used when player is activated/inactivated in the area bool HandlePlayerEnter(Player* player) override; @@ -243,7 +243,7 @@ public: void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; // used when player is activated/inactivated in the area bool HandlePlayerEnter(Player* player) override; @@ -269,7 +269,7 @@ public: void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; // used when player is activated/inactivated in the area bool HandlePlayerEnter(Player* player) override; @@ -298,7 +298,7 @@ public: bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void SendRemoveWorldStates(Player* player) override; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPGH.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPGH.cpp index e60a89a0b..5037503a9 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPGH.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPGH.cpp @@ -49,11 +49,12 @@ OPvPCapturePointGH::OPvPCapturePointGH(OutdoorPvP* pvp) : OPvPCapturePoint(pvp) SetCapturePointData(189310, 571, 2483.68f, -1873.6f, 10.6877f, -0.104719f, 0.0f, 0.0f, 0.0f, 1.0f); } -void OPvPCapturePointGH::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointGH::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << GH_UI_SLIDER_DISPLAY << uint32(0); - data << GH_UI_SLIDER_POS << uint32(50); - data << GH_UI_SLIDER_N << uint32(20); + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(GH_UI_SLIDER_DISPLAY, 0); + packet.Worldstates.emplace_back(GH_UI_SLIDER_POS, 50); + packet.Worldstates.emplace_back(GH_UI_SLIDER_N, 20); } void OPvPCapturePointGH::SendChangePhase() diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPGH.h b/src/server/scripts/OutdoorPvP/OutdoorPvPGH.h index d924f6b49..4ec3f2784 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPGH.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPGH.h @@ -52,7 +52,7 @@ public: void ChangeState() override; void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; bool HandlePlayerEnter(Player* player) override; void HandlePlayerLeave(Player* player) override; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp index b26af4d6f..9e32988d3 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp @@ -154,18 +154,21 @@ void OutdoorPvPHP::SendRemoveWorldStates(Player* player) } } -void OutdoorPvPHP::FillInitialWorldStates(WorldPacket& data) +void OutdoorPvPHP::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(HP_UI_TOWER_DISPLAY_A) << uint32(1); - data << uint32(HP_UI_TOWER_DISPLAY_H) << uint32(1); - data << uint32(HP_UI_TOWER_COUNT_A) << uint32(m_AllianceTowersControlled); - data << uint32(HP_UI_TOWER_COUNT_H) << uint32(m_HordeTowersControlled); - data << uint32(HP_UI_TOWER_SLIDER_DISPLAY) << uint32(0); - data << uint32(HP_UI_TOWER_SLIDER_POS) << uint32(50); - data << uint32(HP_UI_TOWER_SLIDER_N) << uint32(100); + packet.Worldstates.reserve(8); + packet.Worldstates.emplace_back(HP_UI_TOWER_DISPLAY_A, 1); + packet.Worldstates.emplace_back(HP_UI_TOWER_DISPLAY_H, 1); + packet.Worldstates.emplace_back(HP_UI_TOWER_COUNT_A, m_AllianceTowersControlled); + packet.Worldstates.emplace_back(HP_UI_TOWER_COUNT_H, m_HordeTowersControlled); + + packet.Worldstates.emplace_back(HP_UI_TOWER_COUNT_H, m_HordeTowersControlled); + packet.Worldstates.emplace_back(HP_UI_TOWER_SLIDER_DISPLAY, 0); + packet.Worldstates.emplace_back(HP_UI_TOWER_SLIDER_POS, 50); + packet.Worldstates.emplace_back(HP_UI_TOWER_SLIDER_N, 100); for (OPvPCapturePointMap::iterator itr = _capturePoints.begin(); itr != _capturePoints.end(); ++itr) { - itr->second->FillInitialWorldStates(data); + itr->second->FillInitialWorldStates(packet); } } @@ -274,29 +277,32 @@ void OPvPCapturePointHP::SendChangePhase() SendUpdateWorldState(HP_UI_TOWER_SLIDER_DISPLAY, 1); } -void OPvPCapturePointHP::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointHP::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { switch (_state) { case OBJECTIVESTATE_ALLIANCE: case OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE: - data << uint32(HP_MAP_N[m_TowerType]) << uint32(0); - data << uint32(HP_MAP_A[m_TowerType]) << uint32(1); - data << uint32(HP_MAP_H[m_TowerType]) << uint32(0); + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(HP_MAP_N[m_TowerType], 0); + packet.Worldstates.emplace_back(HP_MAP_A[m_TowerType], 1); + packet.Worldstates.emplace_back(HP_MAP_H[m_TowerType], 0); break; case OBJECTIVESTATE_HORDE: case OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE: - data << uint32(HP_MAP_N[m_TowerType]) << uint32(0); - data << uint32(HP_MAP_A[m_TowerType]) << uint32(0); - data << uint32(HP_MAP_H[m_TowerType]) << uint32(1); + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(HP_MAP_N[m_TowerType], 0); + packet.Worldstates.emplace_back(HP_MAP_A[m_TowerType], 0); + packet.Worldstates.emplace_back(HP_MAP_H[m_TowerType], 1); break; case OBJECTIVESTATE_NEUTRAL: case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: case OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE: default: - data << uint32(HP_MAP_N[m_TowerType]) << uint32(1); - data << uint32(HP_MAP_A[m_TowerType]) << uint32(0); - data << uint32(HP_MAP_H[m_TowerType]) << uint32(0); + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(HP_MAP_N[m_TowerType], 1); + packet.Worldstates.emplace_back(HP_MAP_A[m_TowerType], 0); + packet.Worldstates.emplace_back(HP_MAP_H[m_TowerType], 0); break; } } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.h b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.h index cfcf5a085..95646e5cc 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.h @@ -94,7 +94,7 @@ public: void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; // used when player is activated/inactivated in the area bool HandlePlayerEnter(Player* player) override; @@ -116,7 +116,7 @@ public: bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void SendRemoveWorldStates(Player* player) override; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp index 77d1b0a73..05930308a 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp @@ -29,6 +29,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSessionMgr.h" +#include "WorldStatePackets.h" OutdoorPvPNA::OutdoorPvPNA() { @@ -300,61 +301,53 @@ void OutdoorPvPNA::HandlePlayerLeaveZone(Player* player, uint32 zone) OutdoorPvP::HandlePlayerLeaveZone(player, zone); } -void OutdoorPvPNA::FillInitialWorldStates(WorldPacket& data) +void OutdoorPvPNA::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - m_obj->FillInitialWorldStates(data); + m_obj->FillInitialWorldStates(packet); } -void OPvPCapturePointNA::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointNA::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { + packet.Worldstates.reserve(25); if (m_ControllingFaction == TEAM_ALLIANCE) { - data << NA_UI_HORDE_GUARDS_SHOW << uint32(0); - data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(1); + packet.Worldstates.emplace_back(NA_UI_HORDE_GUARDS_SHOW, 0); + packet.Worldstates.emplace_back(NA_UI_ALLIANCE_GUARDS_SHOW, 1); } else if (m_ControllingFaction == TEAM_HORDE) { - data << NA_UI_HORDE_GUARDS_SHOW << uint32(1); - data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(0); + packet.Worldstates.emplace_back(NA_UI_HORDE_GUARDS_SHOW, 1); + packet.Worldstates.emplace_back(NA_UI_ALLIANCE_GUARDS_SHOW, 0); } else { - data << NA_UI_HORDE_GUARDS_SHOW << uint32(0); - data << NA_UI_ALLIANCE_GUARDS_SHOW << uint32(0); + packet.Worldstates.emplace_back(NA_UI_HORDE_GUARDS_SHOW, 0); + packet.Worldstates.emplace_back(NA_UI_ALLIANCE_GUARDS_SHOW, 0); } - data << NA_UI_GUARDS_MAX << NA_GUARDS_MAX; - data << NA_UI_GUARDS_LEFT << uint32(m_GuardsAlive); - - data << NA_UI_TOWER_SLIDER_DISPLAY << uint32(0); - data << NA_UI_TOWER_SLIDER_POS << uint32(50); - data << NA_UI_TOWER_SLIDER_N << uint32(100); - - data << NA_MAP_WYVERN_NORTH_NEU_H << uint32(bool(m_WyvernStateNorth & WYVERN_NEU_HORDE)); - data << NA_MAP_WYVERN_NORTH_NEU_A << uint32(bool(m_WyvernStateNorth & WYVERN_NEU_ALLIANCE)); - data << NA_MAP_WYVERN_NORTH_H << uint32(bool(m_WyvernStateNorth & WYVERN_HORDE)); - data << NA_MAP_WYVERN_NORTH_A << uint32(bool(m_WyvernStateNorth & WYVERN_ALLIANCE)); - - data << NA_MAP_WYVERN_SOUTH_NEU_H << uint32(bool(m_WyvernStateSouth & WYVERN_NEU_HORDE)); - data << NA_MAP_WYVERN_SOUTH_NEU_A << uint32(bool(m_WyvernStateSouth & WYVERN_NEU_ALLIANCE)); - data << NA_MAP_WYVERN_SOUTH_H << uint32(bool(m_WyvernStateSouth & WYVERN_HORDE)); - data << NA_MAP_WYVERN_SOUTH_A << uint32(bool(m_WyvernStateSouth & WYVERN_ALLIANCE)); - - data << NA_MAP_WYVERN_WEST_NEU_H << uint32(bool(m_WyvernStateWest & WYVERN_NEU_HORDE)); - data << NA_MAP_WYVERN_WEST_NEU_A << uint32(bool(m_WyvernStateWest & WYVERN_NEU_ALLIANCE)); - data << NA_MAP_WYVERN_WEST_H << uint32(bool(m_WyvernStateWest & WYVERN_HORDE)); - data << NA_MAP_WYVERN_WEST_A << uint32(bool(m_WyvernStateWest & WYVERN_ALLIANCE)); - - data << NA_MAP_WYVERN_EAST_NEU_H << uint32(bool(m_WyvernStateEast & WYVERN_NEU_HORDE)); - data << NA_MAP_WYVERN_EAST_NEU_A << uint32(bool(m_WyvernStateEast & WYVERN_NEU_ALLIANCE)); - data << NA_MAP_WYVERN_EAST_H << uint32(bool(m_WyvernStateEast & WYVERN_HORDE)); - data << NA_MAP_WYVERN_EAST_A << uint32(bool(m_WyvernStateEast & WYVERN_ALLIANCE)); - - data << NA_MAP_HALAA_NEUTRAL << uint32(bool(m_HalaaState & HALAA_N)); - data << NA_MAP_HALAA_NEU_A << uint32(bool(m_HalaaState & HALAA_N_A)); - data << NA_MAP_HALAA_NEU_H << uint32(bool(m_HalaaState & HALAA_N_H)); - data << NA_MAP_HALAA_HORDE << uint32(bool(m_HalaaState & HALAA_H)); - data << NA_MAP_HALAA_ALLIANCE << uint32(bool(m_HalaaState & HALAA_A)); + packet.Worldstates.emplace_back(NA_UI_GUARDS_MAX, NA_GUARDS_MAX); + packet.Worldstates.emplace_back(NA_UI_GUARDS_LEFT, m_GuardsAlive); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_NORTH_NEU_H, (m_WyvernStateNorth & WYVERN_NEU_HORDE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_NORTH_NEU_A, (m_WyvernStateNorth & WYVERN_NEU_ALLIANCE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_NORTH_H, (m_WyvernStateNorth & WYVERN_HORDE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_NORTH_A, (m_WyvernStateNorth & WYVERN_ALLIANCE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_SOUTH_NEU_H, (m_WyvernStateSouth & WYVERN_NEU_HORDE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_SOUTH_NEU_A, (m_WyvernStateSouth & WYVERN_NEU_ALLIANCE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_SOUTH_H, (m_WyvernStateSouth & WYVERN_HORDE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_SOUTH_A, (m_WyvernStateSouth & WYVERN_ALLIANCE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_WEST_NEU_H, (m_WyvernStateWest & WYVERN_NEU_HORDE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_WEST_NEU_A, (m_WyvernStateWest & WYVERN_NEU_ALLIANCE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_WEST_H, (m_WyvernStateWest & WYVERN_HORDE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_WEST_A, (m_WyvernStateWest & WYVERN_ALLIANCE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_EAST_NEU_H, (m_WyvernStateEast & WYVERN_NEU_HORDE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_EAST_NEU_A, (m_WyvernStateEast & WYVERN_NEU_ALLIANCE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_EAST_H, (m_WyvernStateEast & WYVERN_HORDE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_WYVERN_EAST_A, (m_WyvernStateEast & WYVERN_ALLIANCE) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_HALAA_NEUTRAL, (m_HalaaState & HALAA_N) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_HALAA_NEU_A, (m_HalaaState & HALAA_N_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_HALAA_NEU_H, (m_HalaaState & HALAA_N_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_HALAA_HORDE, (m_HalaaState & HALAA_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(NA_MAP_HALAA_ALLIANCE, (m_HalaaState & HALAA_A) != 0 ? 1 : 0); } void OutdoorPvPNA::SendRemoveWorldStates(Player* player) diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h index c3a9b8e25..0f8f6ab13 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h @@ -229,7 +229,7 @@ public: void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; // used when player is activated/inactivated in the area bool HandlePlayerEnter(Player* player) override; @@ -287,7 +287,7 @@ public: bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void SendRemoveWorldStates(Player* player) override; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp index bde78c3aa..2e01c38e8 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp @@ -29,6 +29,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSessionMgr.h" +#include "WorldStatePackets.h" OutdoorPvPSI::OutdoorPvPSI() { @@ -38,11 +39,12 @@ OutdoorPvPSI::OutdoorPvPSI() m_LastController = TEAM_NEUTRAL; } -void OutdoorPvPSI::FillInitialWorldStates(WorldPacket& data) +void OutdoorPvPSI::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << SI_GATHERED_A << m_Gathered_A; - data << SI_GATHERED_H << m_Gathered_H; - data << SI_SILITHYST_MAX << SI_MAX_RESOURCES; + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(SI_GATHERED_A, m_Gathered_A); + packet.Worldstates.emplace_back(SI_GATHERED_H, m_Gathered_H); + packet.Worldstates.emplace_back(SI_SILITHYST_MAX, SI_MAX_RESOURCES); } void OutdoorPvPSI::SendRemoveWorldStates(Player* player) diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.h b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.h index ff8735fb4..1ae673954 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.h @@ -63,7 +63,7 @@ public: bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void SendRemoveWorldStates(Player* player) override; @@ -78,7 +78,6 @@ public: private: uint32 m_Gathered_A; uint32 m_Gathered_H; - TeamId m_LastController; }; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp index d312b6abc..cf0e239a8 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp @@ -27,6 +27,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSessionMgr.h" +#include "WorldStatePackets.h" OutdoorPvPTF::OutdoorPvPTF() { @@ -51,34 +52,34 @@ OPvPCapturePointTF::OPvPCapturePointTF(OutdoorPvP* pvp, OutdoorPvPTF_TowerType t SetCapturePointData(TFCapturePoints[type].entry, TFCapturePoints[type].map, TFCapturePoints[type].x, TFCapturePoints[type].y, TFCapturePoints[type].z, TFCapturePoints[type].o, TFCapturePoints[type].rot0, TFCapturePoints[type].rot1, TFCapturePoints[type].rot2, TFCapturePoints[type].rot3); } -void OPvPCapturePointTF::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointTF::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(TFTowerWorldStates[m_TowerType].n) << uint32(bool(m_TowerState & TF_TOWERSTATE_N)); - data << uint32(TFTowerWorldStates[m_TowerType].h) << uint32(bool(m_TowerState & TF_TOWERSTATE_H)); - data << uint32(TFTowerWorldStates[m_TowerType].a) << uint32(bool(m_TowerState & TF_TOWERSTATE_A)); + packet.Worldstates.reserve(3); + packet.Worldstates.emplace_back(TFTowerWorldStates[m_TowerType].n, (m_TowerState & TF_TOWERSTATE_N) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(TFTowerWorldStates[m_TowerType].h, (m_TowerState & TF_TOWERSTATE_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(TFTowerWorldStates[m_TowerType].a, (m_TowerState & TF_TOWERSTATE_A) != 0 ? 1 : 0); } -void OutdoorPvPTF::FillInitialWorldStates(WorldPacket& data) +void OutdoorPvPTF::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << TF_UI_TOWER_SLIDER_POS << uint32(50); - data << TF_UI_TOWER_SLIDER_N << uint32(100); - data << TF_UI_TOWER_SLIDER_DISPLAY << uint32(0); + packet.Worldstates.reserve(12); + packet.Worldstates.emplace_back(TF_UI_TOWER_SLIDER_POS, 50); + packet.Worldstates.emplace_back(TF_UI_TOWER_SLIDER_N, 100); + packet.Worldstates.emplace_back(TF_UI_TOWER_SLIDER_DISPLAY, 0); - data << TF_UI_TOWER_COUNT_H << m_HordeTowersControlled; - data << TF_UI_TOWER_COUNT_A << m_AllianceTowersControlled; - data << TF_UI_TOWERS_CONTROLLED_DISPLAY << uint32(!m_IsLocked); - - data << TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT << first_digit; - data << TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT << second_digit; - data << TF_UI_LOCKED_TIME_HOURS << hours_left; - - data << TF_UI_LOCKED_DISPLAY_NEUTRAL << uint32(m_IsLocked && !m_HordeTowersControlled && !m_AllianceTowersControlled); - data << TF_UI_LOCKED_DISPLAY_HORDE << uint32(m_IsLocked && (m_HordeTowersControlled > m_AllianceTowersControlled)); - data << TF_UI_LOCKED_DISPLAY_ALLIANCE << uint32(m_IsLocked && (m_HordeTowersControlled < m_AllianceTowersControlled)); + packet.Worldstates.emplace_back(TF_UI_TOWER_COUNT_H, m_HordeTowersControlled); + packet.Worldstates.emplace_back(TF_UI_TOWER_COUNT_A, m_AllianceTowersControlled); + packet.Worldstates.emplace_back(TF_UI_TOWERS_CONTROLLED_DISPLAY, !m_IsLocked); + packet.Worldstates.emplace_back(TF_UI_LOCKED_TIME_MINUTES_FIRST_DIGIT, first_digit); + packet.Worldstates.emplace_back(TF_UI_LOCKED_TIME_MINUTES_SECOND_DIGIT, second_digit); + packet.Worldstates.emplace_back(TF_UI_LOCKED_TIME_HOURS, hours_left); + packet.Worldstates.emplace_back(TF_UI_LOCKED_DISPLAY_NEUTRAL, (m_IsLocked && !m_HordeTowersControlled && !m_AllianceTowersControlled) ? 1 : 0); + packet.Worldstates.emplace_back(TF_UI_LOCKED_DISPLAY_HORDE, (m_IsLocked && (m_HordeTowersControlled > m_AllianceTowersControlled)) ? 1 : 0); + packet.Worldstates.emplace_back(TF_UI_LOCKED_DISPLAY_ALLIANCE, (m_IsLocked && (m_HordeTowersControlled < m_AllianceTowersControlled)) ? 1 : 0); for (OPvPCapturePointMap::iterator itr = _capturePoints.begin(); itr != _capturePoints.end(); ++itr) { - itr->second->FillInitialWorldStates(data); + itr->second->FillInitialWorldStates(packet); } } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.h b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.h index 9900c644b..aa9dfef43 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.h @@ -132,7 +132,7 @@ public: void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; // used when player is activated/inactivated in the area bool HandlePlayerEnter(Player* player) override; @@ -144,7 +144,6 @@ public: protected: OutdoorPvPTF_TowerType m_TowerType; - uint32 m_TowerState; }; @@ -160,7 +159,7 @@ public: bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void SendRemoveWorldStates(Player* player) override; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp index b681c1604..0e9c36759 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp @@ -26,6 +26,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSessionMgr.h" +#include "WorldStatePackets.h" OPvPCapturePointZM_Beacon::OPvPCapturePointZM_Beacon(OutdoorPvP* pvp, ZM_BeaconType type) : OPvPCapturePoint(pvp), m_TowerType(type), m_TowerState(ZM_TOWERSTATE_N) @@ -33,14 +34,15 @@ OPvPCapturePointZM_Beacon::OPvPCapturePointZM_Beacon(OutdoorPvP* pvp, ZM_BeaconT SetCapturePointData(ZMCapturePoints[type].entry, ZMCapturePoints[type].map, ZMCapturePoints[type].x, ZMCapturePoints[type].y, ZMCapturePoints[type].z, ZMCapturePoints[type].o, ZMCapturePoints[type].rot0, ZMCapturePoints[type].rot1, ZMCapturePoints[type].rot2, ZMCapturePoints[type].rot3); } -void OPvPCapturePointZM_Beacon::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointZM_Beacon::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_n) << uint32(bool(m_TowerState & ZM_TOWERSTATE_N)); - data << uint32(ZMBeaconInfo[m_TowerType].map_tower_n) << uint32(bool(m_TowerState & ZM_TOWERSTATE_N)); - data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_a) << uint32(bool(m_TowerState & ZM_TOWERSTATE_A)); - data << uint32(ZMBeaconInfo[m_TowerType].map_tower_a) << uint32(bool(m_TowerState & ZM_TOWERSTATE_A)); - data << uint32(ZMBeaconInfo[m_TowerType].ui_tower_h) << uint32(bool(m_TowerState & ZM_TOWERSTATE_H)); - data << uint32(ZMBeaconInfo[m_TowerType].map_tower_h) << uint32(bool(m_TowerState & ZM_TOWERSTATE_H)); + packet.Worldstates.reserve(6); + packet.Worldstates.emplace_back(ZMBeaconInfo[m_TowerType].ui_tower_n, (m_TowerState & ZM_TOWERSTATE_N) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(ZMBeaconInfo[m_TowerType].map_tower_n, (m_TowerState & ZM_TOWERSTATE_N) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(ZMBeaconInfo[m_TowerType].ui_tower_a, (m_TowerState & ZM_TOWERSTATE_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(ZMBeaconInfo[m_TowerType].map_tower_a, (m_TowerState & ZM_TOWERSTATE_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(ZMBeaconInfo[m_TowerType].ui_tower_h, (m_TowerState & ZM_TOWERSTATE_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(ZMBeaconInfo[m_TowerType].map_tower_h, (m_TowerState & ZM_TOWERSTATE_H) != 0 ? 1 : 0); } void OPvPCapturePointZM_Beacon::UpdateTowerState() @@ -137,11 +139,11 @@ bool OutdoorPvPZM::Update(uint32 diff) if (changed) { if (m_AllianceTowersControlled == ZM_NUM_BEACONS) - m_GraveYard->SetBeaconState(TEAM_ALLIANCE); + m_Graveyard->SetBeaconState(TEAM_ALLIANCE); else if (m_HordeTowersControlled == ZM_NUM_BEACONS) - m_GraveYard->SetBeaconState(TEAM_HORDE); + m_Graveyard->SetBeaconState(TEAM_HORDE); else - m_GraveYard->SetBeaconState(TEAM_NEUTRAL); + m_Graveyard->SetBeaconState(TEAM_NEUTRAL); } return changed; } @@ -150,12 +152,12 @@ void OutdoorPvPZM::HandlePlayerEnterZone(Player* player, uint32 zone) { if (player->GetTeamId() == TEAM_ALLIANCE) { - if (m_GraveYard->GetGraveYardState() & ZM_GRAVEYARD_A) + if (m_Graveyard->GetGraveyardState() & ZM_GRAVEYARD_A) player->CastSpell(player, ZM_CAPTURE_BUFF, true); } else { - if (m_GraveYard->GetGraveYardState() & ZM_GRAVEYARD_H) + if (m_Graveyard->GetGraveyardState() & ZM_GRAVEYARD_H) player->CastSpell(player, ZM_CAPTURE_BUFF, true); } OutdoorPvP::HandlePlayerEnterZone(player, zone); @@ -174,7 +176,7 @@ void OutdoorPvPZM::HandlePlayerLeaveZone(Player* player, uint32 zone) OutdoorPvPZM::OutdoorPvPZM() { _typeId = OUTDOOR_PVP_ZM; - m_GraveYard = nullptr; + m_Graveyard = nullptr; m_AllianceTowersControlled = 0; m_HordeTowersControlled = 0; } @@ -192,8 +194,8 @@ bool OutdoorPvPZM::SetupOutdoorPvP() AddCapturePoint(new OPvPCapturePointZM_Beacon(this, ZM_BEACON_WEST)); AddCapturePoint(new OPvPCapturePointZM_Beacon(this, ZM_BEACON_EAST)); - m_GraveYard = new OPvPCapturePointZM_GraveYard(this); - AddCapturePoint(m_GraveYard); // though the update function isn't used, the handleusego is! + m_Graveyard = new OPvPCapturePointZM_Graveyard(this); + AddCapturePoint(m_Graveyard); // though the update function isn't used, the handleusego is! return true; } @@ -209,23 +211,23 @@ void OutdoorPvPZM::HandleKillImpl(Player* player, Unit* killed) player->CastSpell(player, ZM_HordePlayerKillReward, true); } -bool OPvPCapturePointZM_GraveYard::Update(uint32 /*diff*/) +bool OPvPCapturePointZM_Graveyard::Update(uint32 /*diff*/) { bool retval = _state != _oldState; _state = _oldState; return retval; } -int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) +int32 OPvPCapturePointZM_Graveyard::HandleOpenGo(Player* player, GameObject* go) { int32 retval = OPvPCapturePoint::HandleOpenGo(player, go); if (retval >= 0) { - if (player->HasAura(ZM_BATTLE_STANDARD_A) && m_GraveYardState != ZM_GRAVEYARD_A) + if (player->HasAura(ZM_BATTLE_STANDARD_A) && m_GraveyardState != ZM_GRAVEYARD_A) { - if (m_GraveYardState == ZM_GRAVEYARD_H) + if (m_GraveyardState == ZM_GRAVEYARD_H) sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_H)); - m_GraveYardState = ZM_GRAVEYARD_A; + m_GraveyardState = ZM_GRAVEYARD_A; DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant AddObject(0, ZM_Banner_A.entry, ZM_Banner_A.map, ZM_Banner_A.x, ZM_Banner_A.y, ZM_Banner_A.z, ZM_Banner_A.o, ZM_Banner_A.rot0, ZM_Banner_A.rot1, ZM_Banner_A.rot2, ZM_Banner_A.rot3); sGraveyard->RemoveGraveyardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, TEAM_HORDE); // rem gy @@ -234,11 +236,11 @@ int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) player->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_A)); } - else if (player->HasAura(ZM_BATTLE_STANDARD_H) && m_GraveYardState != ZM_GRAVEYARD_H) + else if (player->HasAura(ZM_BATTLE_STANDARD_H) && m_GraveyardState != ZM_GRAVEYARD_H) { - if (m_GraveYardState == ZM_GRAVEYARD_A) + if (m_GraveyardState == ZM_GRAVEYARD_A) sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_A)); - m_GraveYardState = ZM_GRAVEYARD_H; + m_GraveyardState = ZM_GRAVEYARD_H; DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant AddObject(0, ZM_Banner_H.entry, ZM_Banner_H.map, ZM_Banner_H.x, ZM_Banner_H.y, ZM_Banner_H.z, ZM_Banner_H.o, ZM_Banner_H.rot0, ZM_Banner_H.rot1, ZM_Banner_H.rot2, ZM_Banner_H.rot3); sGraveyard->RemoveGraveyardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, TEAM_ALLIANCE); // rem gy @@ -252,11 +254,11 @@ int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) return retval; } -OPvPCapturePointZM_GraveYard::OPvPCapturePointZM_GraveYard(OutdoorPvP* pvp) +OPvPCapturePointZM_Graveyard::OPvPCapturePointZM_Graveyard(OutdoorPvP* pvp) : OPvPCapturePoint(pvp) { m_BothControllingFactionId = TEAM_NEUTRAL; - m_GraveYardState = ZM_GRAVEYARD_N; + m_GraveyardState = ZM_GRAVEYARD_N; m_FlagCarrierGUID.Clear(); // add field scouts here AddCreature(ZM_ALLIANCE_FIELD_SCOUT, ZM_AllianceFieldScout.entry, ZM_AllianceFieldScout.map, ZM_AllianceFieldScout.x, ZM_AllianceFieldScout.y, ZM_AllianceFieldScout.z, ZM_AllianceFieldScout.o); @@ -265,11 +267,11 @@ OPvPCapturePointZM_GraveYard::OPvPCapturePointZM_GraveYard(OutdoorPvP* pvp) AddObject(0, ZM_Banner_N.entry, ZM_Banner_N.map, ZM_Banner_N.x, ZM_Banner_N.y, ZM_Banner_N.z, ZM_Banner_N.o, ZM_Banner_N.rot0, ZM_Banner_N.rot1, ZM_Banner_N.rot2, ZM_Banner_N.rot3); } -void OPvPCapturePointZM_GraveYard::UpdateTowerState() +void OPvPCapturePointZM_Graveyard::UpdateTowerState() { - _pvp->SendUpdateWorldState(ZM_MAP_GRAVEYARD_N, uint32(bool(m_GraveYardState & ZM_GRAVEYARD_N))); - _pvp->SendUpdateWorldState(ZM_MAP_GRAVEYARD_H, uint32(bool(m_GraveYardState & ZM_GRAVEYARD_H))); - _pvp->SendUpdateWorldState(ZM_MAP_GRAVEYARD_A, uint32(bool(m_GraveYardState & ZM_GRAVEYARD_A))); + _pvp->SendUpdateWorldState(ZM_MAP_GRAVEYARD_N, uint32(bool(m_GraveyardState & ZM_GRAVEYARD_N))); + _pvp->SendUpdateWorldState(ZM_MAP_GRAVEYARD_H, uint32(bool(m_GraveyardState & ZM_GRAVEYARD_H))); + _pvp->SendUpdateWorldState(ZM_MAP_GRAVEYARD_A, uint32(bool(m_GraveyardState & ZM_GRAVEYARD_A))); _pvp->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_READY, uint32(m_BothControllingFactionId == TEAM_ALLIANCE)); _pvp->SendUpdateWorldState(ZM_MAP_ALLIANCE_FLAG_NOT_READY, uint32(m_BothControllingFactionId != TEAM_ALLIANCE)); @@ -277,19 +279,19 @@ void OPvPCapturePointZM_GraveYard::UpdateTowerState() _pvp->SendUpdateWorldState(ZM_MAP_HORDE_FLAG_NOT_READY, uint32(m_BothControllingFactionId != TEAM_HORDE)); } -void OPvPCapturePointZM_GraveYard::FillInitialWorldStates(WorldPacket& data) +void OPvPCapturePointZM_Graveyard::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << ZM_MAP_GRAVEYARD_N << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_N)); - data << ZM_MAP_GRAVEYARD_H << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_H)); - data << ZM_MAP_GRAVEYARD_A << uint32(bool(m_GraveYardState & ZM_GRAVEYARD_A)); - - data << ZM_MAP_ALLIANCE_FLAG_READY << uint32(m_BothControllingFactionId == TEAM_ALLIANCE); - data << ZM_MAP_ALLIANCE_FLAG_NOT_READY << uint32(m_BothControllingFactionId != TEAM_ALLIANCE); - data << ZM_MAP_HORDE_FLAG_READY << uint32(m_BothControllingFactionId == TEAM_HORDE); - data << ZM_MAP_HORDE_FLAG_NOT_READY << uint32(m_BothControllingFactionId != TEAM_HORDE); + packet.Worldstates.reserve(7); + packet.Worldstates.emplace_back(ZM_MAP_GRAVEYARD_N, (m_GraveyardState & ZM_GRAVEYARD_N) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(ZM_MAP_GRAVEYARD_H, (m_GraveyardState & ZM_GRAVEYARD_H) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(ZM_MAP_GRAVEYARD_A, (m_GraveyardState & ZM_GRAVEYARD_A) != 0 ? 1 : 0); + packet.Worldstates.emplace_back(ZM_MAP_ALLIANCE_FLAG_READY, m_BothControllingFactionId == TEAM_ALLIANCE ? 1 : 0); + packet.Worldstates.emplace_back(ZM_MAP_ALLIANCE_FLAG_NOT_READY, m_BothControllingFactionId != TEAM_ALLIANCE ? 1 : 0); + packet.Worldstates.emplace_back(ZM_MAP_HORDE_FLAG_READY, m_BothControllingFactionId == TEAM_HORDE ? 1 : 0); + packet.Worldstates.emplace_back(ZM_MAP_HORDE_FLAG_NOT_READY, m_BothControllingFactionId != TEAM_HORDE ? 1 : 0); } -void OPvPCapturePointZM_GraveYard::SetBeaconState(TeamId controlling_factionId) +void OPvPCapturePointZM_Graveyard::SetBeaconState(TeamId controlling_factionId) { // nothing to do here if (m_BothControllingFactionId == controlling_factionId) @@ -300,20 +302,20 @@ void OPvPCapturePointZM_GraveYard::SetBeaconState(TeamId controlling_factionId) { case TEAM_ALLIANCE: // if ally already controls the gy and taken back both beacons, return, nothing to do for us - if (m_GraveYardState & ZM_GRAVEYARD_A) + if (m_GraveyardState & ZM_GRAVEYARD_A) return; // ally doesn't control the gy, but controls the side beacons -> add gossip option, add neutral banner break; case TEAM_HORDE: // if horde already controls the gy and taken back both beacons, return, nothing to do for us - if (m_GraveYardState & ZM_GRAVEYARD_H) + if (m_GraveyardState & ZM_GRAVEYARD_H) return; // horde doesn't control the gy, but controls the side beacons -> add gossip option, add neutral banner break; default: // if the graveyard is not neutral, then leave it that way // if the graveyard is neutral, then we have to dispel the buff from the flag carrier - if (m_GraveYardState & ZM_GRAVEYARD_N) + if (m_GraveyardState & ZM_GRAVEYARD_N) { // gy was neutral, thus neutral banner was spawned, it is possible that someone was taking the flag to the gy if (m_FlagCarrierGUID) @@ -334,21 +336,21 @@ void OPvPCapturePointZM_GraveYard::SetBeaconState(TeamId controlling_factionId) UpdateTowerState(); } -bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player* player, Creature* c, GossipMenuItems const& /*gso*/) +bool OPvPCapturePointZM_Graveyard::CanTalkTo(Player* player, Creature* c, GossipMenuItems const& /*gso*/) { ObjectGuid guid = c->GetGUID(); auto itr = _creatureTypes.find(guid.GetCounter()); if (itr != _creatureTypes.end()) { - if (itr->second == ZM_ALLIANCE_FIELD_SCOUT && player->GetTeamId() == TEAM_ALLIANCE && m_BothControllingFactionId == TEAM_ALLIANCE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_A) + if (itr->second == ZM_ALLIANCE_FIELD_SCOUT && player->GetTeamId() == TEAM_ALLIANCE && m_BothControllingFactionId == TEAM_ALLIANCE && !m_FlagCarrierGUID && m_GraveyardState != ZM_GRAVEYARD_A) return true; - else if (itr->second == ZM_HORDE_FIELD_SCOUT && player->GetTeamId() == TEAM_HORDE && m_BothControllingFactionId == TEAM_HORDE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_H) + else if (itr->second == ZM_HORDE_FIELD_SCOUT && player->GetTeamId() == TEAM_HORDE && m_BothControllingFactionId == TEAM_HORDE && !m_FlagCarrierGUID && m_GraveyardState != ZM_GRAVEYARD_H) return true; } return false; } -bool OPvPCapturePointZM_GraveYard::HandleGossipOption(Player* player, Creature* creature, uint32 /*gossipid*/) +bool OPvPCapturePointZM_Graveyard::HandleGossipOption(Player* player, Creature* creature, uint32 /*gossipid*/) { auto itr = _creatureTypes.find(creature->GetSpawnId()); if (itr != _creatureTypes.end()) @@ -375,7 +377,7 @@ bool OPvPCapturePointZM_GraveYard::HandleGossipOption(Player* player, Creature* return false; } -bool OPvPCapturePointZM_GraveYard::HandleDropFlag(Player* /*player*/, uint32 spellId) +bool OPvPCapturePointZM_Graveyard::HandleDropFlag(Player* /*player*/, uint32 spellId) { switch (spellId) { @@ -389,9 +391,9 @@ bool OPvPCapturePointZM_GraveYard::HandleDropFlag(Player* /*player*/, uint32 spe return false; } -uint32 OPvPCapturePointZM_GraveYard::GetGraveYardState() const +uint32 OPvPCapturePointZM_Graveyard::GetGraveyardState() const { - return m_GraveYardState; + return m_GraveyardState; } uint32 OutdoorPvPZM::GetAllianceTowersControlled() const @@ -414,12 +416,12 @@ void OutdoorPvPZM::SetHordeTowersControlled(uint32 count) m_HordeTowersControlled = count; } -void OutdoorPvPZM::FillInitialWorldStates(WorldPacket& data) +void OutdoorPvPZM::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { - data << ZM_WORLDSTATE_UNK_1 << uint32(1); + packet.Worldstates.emplace_back(ZM_WORLDSTATE_UNK_1, 1); for (OPvPCapturePointMap::iterator itr = _capturePoints.begin(); itr != _capturePoints.end(); ++itr) { - itr->second->FillInitialWorldStates(data); + itr->second->FillInitialWorldStates(packet); } } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h index efbb8201a..ef31a4ea2 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h @@ -175,7 +175,7 @@ public: void SendChangePhase() override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; // used when player is activated/inactivated in the area bool HandlePlayerEnter(Player* player) override; @@ -188,23 +188,23 @@ protected: uint32 m_TowerState; }; -enum ZM_GraveYardState +enum Zm_GraveyardState { ZM_GRAVEYARD_N = 1, ZM_GRAVEYARD_A = 2, ZM_GRAVEYARD_H = 4 }; -class OPvPCapturePointZM_GraveYard : public OPvPCapturePoint +class OPvPCapturePointZM_Graveyard : public OPvPCapturePoint { public: - OPvPCapturePointZM_GraveYard(OutdoorPvP* pvp); + OPvPCapturePointZM_Graveyard(OutdoorPvP* pvp); bool Update(uint32 diff) override; void ChangeState() override {} - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void UpdateTowerState(); @@ -218,10 +218,10 @@ public: bool CanTalkTo(Player* player, Creature* creature, GossipMenuItems const& gso) override; - uint32 GetGraveYardState() const; + uint32 GetGraveyardState() const; private: - uint32 m_GraveYardState; + uint32 m_GraveyardState; protected: TeamId m_BothControllingFactionId; @@ -240,7 +240,7 @@ public: bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket& data) override; + void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; void SendRemoveWorldStates(Player* player) override; @@ -253,7 +253,7 @@ public: void SetHordeTowersControlled(uint32 count); private: - OPvPCapturePointZM_GraveYard* m_GraveYard; + OPvPCapturePointZM_Graveyard* m_Graveyard; uint32 m_AllianceTowersControlled; uint32 m_HordeTowersControlled; From 862690ecc0d8d415f529f8c78b1317ae94fa5ca0 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Wed, 19 Feb 2025 09:38:59 -0300 Subject: [PATCH 80/97] chore(CI): Add mod-arena-3v3-solo-queue.git (#21530) Co-authored-by: sudlud --- apps/ci/ci-install-modules.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/ci/ci-install-modules.sh b/apps/ci/ci-install-modules.sh index 92ea145e3..5e98469c7 100755 --- a/apps/ci/ci-install-modules.sh +++ b/apps/ci/ci-install-modules.sh @@ -27,3 +27,4 @@ git clone --depth=1 --branch=main https://github.com/azerothcore/mod-queue-lis git clone --depth=1 --branch=master https://github.com/azerothcore/mod-server-auto-shutdown.git modules/mod-server-auto-shutdown git clone --depth=1 --branch=master https://github.com/azerothcore/mod-transmog.git modules/mod-transmog git clone --depth=1 --branch=main https://github.com/azerothcore/mod-progression-system.git modules/mod-progression-system +git clone --depth=1 --branch=master https://github.com/azerothcore/mod-arena-3v3-solo-queue.git modules/mod-arena-3v3-solo-queue From 04bf98fa6ec79753fb2563637336ef534900a7ee Mon Sep 17 00:00:00 2001 From: Smirnov Sergey Date: Wed, 19 Feb 2025 16:55:11 +0300 Subject: [PATCH 81/97] fix (DB/SAI) [Howling Fjord] Bjorn Halgurdsson behavior (#21474) Co-authored-by: Rocco Silipo <108557877+Rorschach91@users.noreply.github.com> --- .../updates/pending_db_world/fix-npc24238.sql | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 data/sql/updates/pending_db_world/fix-npc24238.sql diff --git a/data/sql/updates/pending_db_world/fix-npc24238.sql b/data/sql/updates/pending_db_world/fix-npc24238.sql new file mode 100644 index 000000000..b23a7cde7 --- /dev/null +++ b/data/sql/updates/pending_db_world/fix-npc24238.sql @@ -0,0 +1,35 @@ +-- Bjorn Halgurdsson - Set position +UPDATE `creature` SET `position_x` = 1518.61, `position_y` = -5249.85, `position_z` = 215.38, `orientation` = 5.41052, `VerifiedBuild` = 59069 WHERE `guid` = 112513 AND `id1` = 24238; + +-- Bjorn Halgurdsson - Set speed_run +UPDATE `creature_template` SET `speed_run` = 1.7435 WHERE (`entry` = 24238); + +-- Bjorn Halgurdsson - Set mount +DELETE FROM `creature_addon` WHERE (`guid` IN (112513)); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES +(112513, 0, 22657, 0, 0, 0, 0, NULL); + +-- Bjorn Halgurdsson - Set movement +UPDATE `creature_template_movement` SET `Swim` = 0, `Flight` = 0 WHERE (`CreatureId` = 24238); + +-- Bjorn Halgurdsson - SmartAI +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 24238; + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 24238); +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 +(24238, 0, 0, 0, 1, 0, 100, 0, 10000, 15000, 45000, 60000, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - Out of Combat - Say Line 2'), +(24238, 0, 1, 2, 8, 0, 100, 0, 43315, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Spellhit \'Vrykul Insult\' - Say Line 0'), +(24238, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Spellhit \'Vrykul Insult\' - Say Line 1'), +(24238, 0, 3, 4, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Spellhit \'Vrykul Insult\' - Dismount'), +(24238, 0, 4, 5, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 207, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Spellhit \'Vrykul Insult\' - Set hover 0'), +(24238, 0, 5, 6, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Spellhit \'Vrykul Insult\' - Set Fly Off'), +(24238, 0, 6, 7, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Spellhit \'Vrykul Insult\' - Set Reactstate Aggressive'), +(24238, 0, 7, 8, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 19, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Spellhit \'Vrykul Insult\' - Remove Flags Not Attackable'), +(24238, 0, 8, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Spellhit \'Vrykul Insult\' - Start Attacking'), +(24238, 0, 9, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 43371, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Just Died - Cast \'Bjorn Kill Credit\''), +(24238, 0, 10, 0, 0, 0, 100, 0, 5000, 10000, 10000, 15000, 0, 0, 11, 32736, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - In Combat - Cast \'Mortal Strike\''), +(24238, 0, 11, 0, 0, 0, 100, 0, 0, 5000, 10000, 15000, 0, 0, 11, 33661, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - In Combat - Cast \'Crush Armor\''), +(24238, 0, 12, 13, 25, 0, 100, 512, 0, 0, 0, 0, 0, 0, 60, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Reset - Set Fly On'), +(24238, 0, 13, 14, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 207, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Reset - Set hover 1'), +(24238, 0, 14, 15, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Reset - Set Reactstate Passive'), +(24238, 0, 15, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 18, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Bjorn Halgurdsson - On Reset - Set Flags Not Attackable'); From 28f5ead7f308a6a301d3dd8798c5031e8a52dcb1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 19 Feb 2025 13:56:13 +0000 Subject: [PATCH 82/97] chore(DB): import pending files Referenced commit(s): 04bf98fa6ec79753fb2563637336ef534900a7ee --- .../fix-npc24238.sql => db_world/2025_02_19_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/fix-npc24238.sql => db_world/2025_02_19_01.sql} (98%) diff --git a/data/sql/updates/pending_db_world/fix-npc24238.sql b/data/sql/updates/db_world/2025_02_19_01.sql similarity index 98% rename from data/sql/updates/pending_db_world/fix-npc24238.sql rename to data/sql/updates/db_world/2025_02_19_01.sql index b23a7cde7..6e2dfd8f9 100644 --- a/data/sql/updates/pending_db_world/fix-npc24238.sql +++ b/data/sql/updates/db_world/2025_02_19_01.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_19_00 -> 2025_02_19_01 -- Bjorn Halgurdsson - Set position UPDATE `creature` SET `position_x` = 1518.61, `position_y` = -5249.85, `position_z` = 215.38, `orientation` = 5.41052, `VerifiedBuild` = 59069 WHERE `guid` = 112513 AND `id1` = 24238; From f6c4164765afe447476114e632ee3d70b04a1777 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Thu, 20 Feb 2025 02:29:46 -0300 Subject: [PATCH 83/97] chore(CI): Add mod-costumes (#21548) --- apps/ci/ci-install-modules.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/ci/ci-install-modules.sh b/apps/ci/ci-install-modules.sh index 5e98469c7..b3271de3c 100755 --- a/apps/ci/ci-install-modules.sh +++ b/apps/ci/ci-install-modules.sh @@ -28,3 +28,4 @@ git clone --depth=1 --branch=master https://github.com/azerothcore/mod-server-au git clone --depth=1 --branch=master https://github.com/azerothcore/mod-transmog.git modules/mod-transmog git clone --depth=1 --branch=main https://github.com/azerothcore/mod-progression-system.git modules/mod-progression-system git clone --depth=1 --branch=master https://github.com/azerothcore/mod-arena-3v3-solo-queue.git modules/mod-arena-3v3-solo-queue +git clone --depth=1 --branch=master https://github.com/azerothcore/mod-costumes.git modules/mod-costumes From 4cd1ed218147905532d3c43c524db716420367fc Mon Sep 17 00:00:00 2001 From: Takenbacon Date: Thu, 20 Feb 2025 22:17:34 -0800 Subject: [PATCH 84/97] refactor(Core/Server): Improvements to antidos opcode handling (#21502) --- .../rev_1739897580268046640.sql | 111 ++++ .../apps/worldserver/worldserver.conf.dist | 11 - src/server/game/Globals/WorldGlobals.cpp | 76 +++ src/server/game/Globals/WorldGlobals.h | 44 ++ src/server/game/Server/WorldSession.cpp | 551 +++++------------- src/server/game/Server/WorldSession.h | 23 +- src/server/game/World/IWorld.h | 1 - src/server/game/World/World.cpp | 5 +- src/server/scripts/Commands/cs_reload.cpp | 10 + 9 files changed, 413 insertions(+), 419 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1739897580268046640.sql create mode 100644 src/server/game/Globals/WorldGlobals.cpp create mode 100644 src/server/game/Globals/WorldGlobals.h diff --git a/data/sql/updates/pending_db_world/rev_1739897580268046640.sql b/data/sql/updates/pending_db_world/rev_1739897580268046640.sql new file mode 100644 index 000000000..edccc5777 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1739897580268046640.sql @@ -0,0 +1,111 @@ +DROP TABLE IF EXISTS `antidos_opcode_policies`; +CREATE TABLE `antidos_opcode_policies` ( + `Opcode` smallint unsigned NOT NULL, + `Policy` tinyint unsigned NOT NULL, + `MaxAllowedCount` smallint unsigned NOT NULL, + PRIMARY KEY (`Opcode`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +INSERT INTO `antidos_opcode_policies` (`Opcode`, `Policy`, `MaxAllowedCount`) VALUES + (393, 1, 200), + (404, 1, 200), + (398, 1, 200), + (102, 1, 200), + (1217, 1, 200), + (643, 1, 200), + (642, 1, 200), + (98, 1, 200), + (1192, 1, 200), + (1218, 1, 200), + (238, 1, 200), + (564, 1, 50), + (565, 1, 50), + (107, 1, 50), + (1065, 1, 50), + (999, 1, 50), + (1131, 1, 50), + (1153, 1, 50), + (177, 1, 50), + (450, 1, 50), + (483, 1, 25), + (1282, 1, 20), + (1016, 1, 20), + (1162, 1, 20), + (1133, 1, 20), + (448, 1, 10), + (452, 1, 10), + (638, 1, 10), + (454, 1, 10), + (1272, 1, 10), + (1139, 1, 10), + (1241, 1, 10), + (56, 1, 10), + (106, 1, 10), + (105, 1, 10), + (711, 1, 10), + (810, 1, 10), + (458, 1, 10), + (120, 1, 10), + (654, 1, 10), + (655, 1, 10), + (445, 1, 10), + (1179, 1, 10), + (1143, 1, 10), + (1144, 1, 10), + (1145, 1, 10), + (1142, 1, 10), + (1193, 1, 10), + (1204, 1, 10), + (839, 1, 10), + (467, 1, 10), + (996, 1, 10), + (600, 4, 5), + (612, 4, 5), + (601, 4, 5), + (54, 1, 3), + (55, 1, 3), + (517, 1, 3), + (519, 1, 3), + (535, 1, 3), + (1264, 1, 3), + (1069, 1, 3), + (1070, 1, 3), + (1071, 1, 3), + (1072, 1, 3), + (1073, 1, 3), + (1210, 1, 3), + (1074, 1, 3), + (1075, 1, 3), + (1077, 1, 3), + (847, 1, 3), + (849, 1, 3), + (850, 1, 3), + (851, 1, 3), + (853, 1, 3), + (852, 1, 3), + (854, 1, 3), + (122, 1, 3), + (130, 1, 3), + (132, 1, 3), + (133, 1, 3), + (141, 1, 3), + (143, 1, 3), + (144, 1, 3), + (145, 1, 3), + (561, 1, 3), + (562, 1, 3), + (563, 1, 3), + (764, 1, 3), + (1004, 1, 3), + (1005, 1, 3), + (1002, 1, 3), + (1003, 1, 3), + (1035, 1, 3), + (497, 1, 3), + (705, 1, 3), + (682, 1, 3), + (809, 1, 3), + (1259, 1, 3), + (910, 1, 3), + (802, 1, 3), + (1203, 1, 150); diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index d0597bfc2..484c4736e 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -1118,17 +1118,6 @@ PreventAFKLogout = 0 ################################################################################################### # PACKET SPOOF PROTECTION SETTINGS -# -# These settings determine which action to take when harmful packet spoofing is detected. -# -# PacketSpoof.Policy -# Description: Determines the course of action when packet spoofing is detected. -# Values: 0 - Log only -# 1 - Log + kick -# 2 - Log + kick + ban - -PacketSpoof.Policy = 1 - # # PacketSpoof.BanMode # Description: If PacketSpoof.Policy equals 2, this will determine the ban mode. diff --git a/src/server/game/Globals/WorldGlobals.cpp b/src/server/game/Globals/WorldGlobals.cpp new file mode 100644 index 000000000..fcfb3369e --- /dev/null +++ b/src/server/game/Globals/WorldGlobals.cpp @@ -0,0 +1,76 @@ +/* + * 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 "DatabaseEnv.h" +#include "Log.h" +#include "QueryResult.h" +#include "Timer.h" +#include "WorldGlobals.h" + +WorldGlobals* WorldGlobals::instance() +{ + static WorldGlobals instance; + return &instance; +} + +void WorldGlobals::LoadAntiDosOpcodePolicies() +{ + uint32 oldMSTime = getMSTime(); + + _antiDosOpcodePolicies = {}; + + QueryResult result = WorldDatabase.Query("SELECT Opcode, Policy, MaxAllowedCount FROM antidos_opcode_policies"); + if (!result) + { + LOG_WARN("server.loading", ">> Loaded 0 AntiDos Opcode Policies. DB table `antidos_opcode_policies` is empty!"); + LOG_INFO("server.loading", " "); + return; + } + + uint32 count = 0; + + do + { + Field* fields = result->Fetch(); + + uint16 opcode = fields[0].Get(); + if (opcode >= NUM_OPCODE_HANDLERS) + { + LOG_ERROR("server.loading", "Unkown opcode {} in table `antidos_opcode_policies`, skipping.", opcode); + continue; + } + + std::unique_ptr policy = std::make_unique(); + policy->Policy = fields[1].Get(); + policy->MaxAllowedCount = fields[2].Get(); + + _antiDosOpcodePolicies[opcode] = std::move(policy); + + ++count; + } while (result->NextRow()); + + LOG_INFO("server.loading", ">> Loaded {} AntiDos Opcode Policies in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", " "); +} + +AntiDosOpcodePolicy const* WorldGlobals::GetAntiDosPolicyForOpcode(uint16 opcode) +{ + if (opcode >= NUM_OPCODE_HANDLERS) + return nullptr; + + return _antiDosOpcodePolicies[opcode].get(); +} diff --git a/src/server/game/Globals/WorldGlobals.h b/src/server/game/Globals/WorldGlobals.h new file mode 100644 index 000000000..e8695d02b --- /dev/null +++ b/src/server/game/Globals/WorldGlobals.h @@ -0,0 +1,44 @@ +/* + * 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 . + */ + +#ifndef __WORLDGLOBALS_H +#define __WORLDGLOBALS_H + +#include "Common.h" +#include "Opcodes.h" + +struct AntiDosOpcodePolicy +{ + uint8 Policy; + uint16 MaxAllowedCount; +}; + +class WorldGlobals +{ +public: + static WorldGlobals* instance(); + + void LoadAntiDosOpcodePolicies(); + AntiDosOpcodePolicy const* GetAntiDosPolicyForOpcode(uint16 opcode); + +private: + std::array, NUM_OPCODE_HANDLERS> _antiDosOpcodePolicies; +}; + +#define sWorldGlobals WorldGlobals::instance() + +#endif diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 4d193306c..4a414d23d 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -49,6 +49,7 @@ #include "Vehicle.h" #include "WardenWin.h" #include "World.h" +#include "WorldGlobals.h" #include "WorldPacket.h" #include "WorldSocket.h" #include "WorldState.h" @@ -330,138 +331,138 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) METRIC_DETAILED_TIMER("worldsession_update_opcode_time", METRIC_TAG("opcode", opHandle->Name)); LOG_DEBUG("network", "message id {} ({}) under READ", opcode, opHandle->Name); - try + WorldSession::DosProtection::Policy const evaluationPolicy = AntiDOS.EvaluateOpcode(*packet, currentTime); + switch (evaluationPolicy) { - switch (opHandle->Status) - { - case STATUS_LOGGEDIN: - if (!_player) - { - // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets - //! If player didn't log out a while ago, it means packets are being sent while the server does not recognize - //! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later. - if (!m_playerRecentlyLogout) - { - requeuePackets.push_back(packet); - deletePacket = false; + case WorldSession::DosProtection::Policy::Kick: + case WorldSession::DosProtection::Policy::Ban: + processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; + break; + case WorldSession::DosProtection::Policy::BlockingThrottle: + requeuePackets.push_back(packet); + deletePacket = false; + processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; + break; + default: + break; + } - LOG_DEBUG("network", "Delaying processing of message with status STATUS_LOGGEDIN: No players in the world for account id {}", GetAccountId()); - } - } - else if (_player->IsInWorld()) + if (evaluationPolicy == WorldSession::DosProtection::Policy::Process + || evaluationPolicy == WorldSession::DosProtection::Policy::Log) + { + try + { + switch (opHandle->Status) { - if (AntiDOS.EvaluateOpcode(*packet, currentTime)) + case STATUS_LOGGEDIN: + if (!_player) + { + // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets + //! If player didn't log out a while ago, it means packets are being sent while the server does not recognize + //! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later. + if (!m_playerRecentlyLogout) + { + requeuePackets.push_back(packet); + deletePacket = false; + + LOG_DEBUG("network", "Delaying processing of message with status STATUS_LOGGEDIN: No players in the world for account id {}", GetAccountId()); + } + } + else if (_player->IsInWorld()) { if (!sScriptMgr->CanPacketReceive(this, *packet)) - { break; - } opHandle->Call(this, *packet); LogUnprocessedTail(packet); } - else - processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; // break out of packet processing loop - } - // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer - break; - case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT: - if (!_player && !m_playerRecentlyLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout - { - LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT", - "the player has not logged in yet and not recently logout"); - } - else if (AntiDOS.EvaluateOpcode(*packet, currentTime)) - { - // not expected _player or must checked in packet hanlder - if (!sScriptMgr->CanPacketReceive(this, *packet)) - break; - - opHandle->Call(this, *packet); - LogUnprocessedTail(packet); - } - else - processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; // break out of packet processing loop - break; - case STATUS_TRANSFER: - if (_player && !_player->IsInWorld() && AntiDOS.EvaluateOpcode(*packet, currentTime)) - { - if (!sScriptMgr->CanPacketReceive(this, *packet)) - { - break; - } - - opHandle->Call(this, *packet); - LogUnprocessedTail(packet); - } - else - processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; // break out of packet processing loop - break; - case STATUS_AUTHED: - if (m_inQueue) // prevent cheating + // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; - - // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes - // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process. - if (packet->GetOpcode() == CMSG_CHAR_ENUM) - m_playerRecentlyLogout = false; - - if (AntiDOS.EvaluateOpcode(*packet, currentTime)) - { - if (!sScriptMgr->CanPacketReceive(this, *packet)) + case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT: + if (!_player && !m_playerRecentlyLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout { - break; + LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT", + "the player has not logged in yet and not recently logout"); } + else + { + // not expected _player or must checked in packet hanlder + if (!sScriptMgr->CanPacketReceive(this, *packet)) + break; + + opHandle->Call(this, *packet); + LogUnprocessedTail(packet); + } + break; + case STATUS_TRANSFER: + if (_player && !_player->IsInWorld()) + { + if (!sScriptMgr->CanPacketReceive(this, *packet)) + break; + + opHandle->Call(this, *packet); + LogUnprocessedTail(packet); + } + break; + case STATUS_AUTHED: + if (m_inQueue) // prevent cheating + break; + + // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes + // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process. + if (packet->GetOpcode() == CMSG_CHAR_ENUM) + m_playerRecentlyLogout = false; + + if (!sScriptMgr->CanPacketReceive(this, *packet)) + break; opHandle->Call(this, *packet); LogUnprocessedTail(packet); + break; + case STATUS_NEVER: + LOG_ERROR("network.opcode", "Received not allowed opcode {} from {}", + GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), GetPlayerInfo()); + break; + case STATUS_UNHANDLED: + LOG_DEBUG("network.opcode", "Received not handled opcode {} from {}", + GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), GetPlayerInfo()); + break; } - else - processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; // break out of packet processing loop - break; - case STATUS_NEVER: - LOG_ERROR("network.opcode", "Received not allowed opcode {} from {}", - GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), GetPlayerInfo()); - break; - case STATUS_UNHANDLED: - LOG_DEBUG("network.opcode", "Received not handled opcode {} from {}", - GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), GetPlayerInfo()); - break; } - } - catch (WorldPackets::InvalidHyperlinkException const& ihe) - { - LOG_ERROR("network", "{} sent {} with an invalid link:\n{}", GetPlayerInfo(), - GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), ihe.GetInvalidValue()); + catch (WorldPackets::InvalidHyperlinkException const& ihe) + { + LOG_ERROR("network", "{} sent {} with an invalid link:\n{}", GetPlayerInfo(), + GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), ihe.GetInvalidValue()); - if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK)) - { - KickPlayer("WorldSession::Update Invalid chat link"); + if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK)) + { + KickPlayer("WorldSession::Update Invalid chat link"); + } } - } - catch (WorldPackets::IllegalHyperlinkException const& ihe) - { - LOG_ERROR("network", "{} sent {} which illegally contained a hyperlink:\n{}", GetPlayerInfo(), - GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), ihe.GetInvalidValue()); + catch (WorldPackets::IllegalHyperlinkException const& ihe) + { + LOG_ERROR("network", "{} sent {} which illegally contained a hyperlink:\n{}", GetPlayerInfo(), + GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), ihe.GetInvalidValue()); - if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK)) - { - KickPlayer("WorldSession::Update Illegal chat link"); + if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK)) + { + KickPlayer("WorldSession::Update Illegal chat link"); + } } - } - catch (WorldPackets::PacketArrayMaxCapacityException const& pamce) - { - LOG_ERROR("network", "PacketArrayMaxCapacityException: {} while parsing {} from {}.", - pamce.what(), GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), GetPlayerInfo()); - } - catch (ByteBufferException const&) - { - LOG_ERROR("network", "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: {}) from client {}, accountid={}. Skipped packet.", packet->GetOpcode(), GetRemoteAddress(), GetAccountId()); - if (sLog->ShouldLog("network", LogLevel::LOG_LEVEL_DEBUG)) + catch (WorldPackets::PacketArrayMaxCapacityException const& pamce) { - LOG_DEBUG("network", "Dumping error causing packet:"); - packet->hexlike(); + LOG_ERROR("network", "PacketArrayMaxCapacityException: {} while parsing {} from {}.", + pamce.what(), GetOpcodeNameForLogging(static_cast(packet->GetOpcode())), GetPlayerInfo()); + } + catch (ByteBufferException const&) + { + LOG_ERROR("network", "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: {}) from client {}, accountid={}. Skipped packet.", packet->GetOpcode(), GetRemoteAddress(), GetAccountId()); + if (sLog->ShouldLog("network", LogLevel::LOG_LEVEL_DEBUG)) + { + LOG_DEBUG("network", "Dumping error causing packet:"); + packet->hexlike(); + } } } @@ -1324,14 +1325,17 @@ Warden* WorldSession::GetWarden() return &(*_warden); } -bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) const +WorldSession::DosProtection::Policy WorldSession::DosProtection::EvaluateOpcode(WorldPacket const& p, time_t const time) const { - uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode()); + AntiDosOpcodePolicy const* policy = sWorldGlobals->GetAntiDosPolicyForOpcode(p.GetOpcode()); + if (!policy) + return WorldSession::DosProtection::Policy::Process; // Return true if there is no policy for the opcode - // Return true if there no limit for the opcode + uint32 const maxPacketCounterAllowed = policy->MaxAllowedCount; if (!maxPacketCounterAllowed) - return true; + return WorldSession::DosProtection::Policy::Process; // Return true if there no limit for the opcode + // packetCounter is opcodes handled in the same world second, so MaxAllowedCount is per second PacketCounter& packetCounter = _PacketThrottlingMap[p.GetOpcode()]; if (packetCounter.lastReceiveTime != time) { @@ -1341,298 +1345,57 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co // Check if player is flooding some packets if (++packetCounter.amountCounter <= maxPacketCounterAllowed) - return true; + return WorldSession::DosProtection::Policy::Process; - LOG_WARN("network", "AntiDOS: Account {}, IP: {}, Ping: {}, Character: {}, flooding packet (opc: {} (0x{:X}), count: {})", - Session->GetAccountId(), Session->GetRemoteAddress(), Session->GetLatency(), Session->GetPlayerName(), - opcodeTable[static_cast(p.GetOpcode())]->Name, p.GetOpcode(), packetCounter.amountCounter); - - switch (_policy) + if (WorldSession::DosProtection::Policy(policy->Policy) != WorldSession::DosProtection::Policy::BlockingThrottle) { - case POLICY_LOG: - return true; - case POLICY_KICK: - { - LOG_INFO("network", "AntiDOS: Player {} kicked!", Session->GetPlayerName()); - Session->KickPlayer(); - return false; - } - case POLICY_BAN: - { - uint32 bm = sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANMODE); - uint32 duration = sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANDURATION); // in seconds - std::string nameOrIp = ""; - switch (bm) - { - case 0: // Ban account - (void)AccountMgr::GetName(Session->GetAccountId(), nameOrIp); - sBan->BanAccount(nameOrIp, std::to_string(duration), "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); - break; - case 1: // Ban ip - nameOrIp = Session->GetRemoteAddress(); - sBan->BanIP(nameOrIp, std::to_string(duration), "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); - break; - } + LOG_WARN("network", "AntiDOS: Account {}, IP: {}, Ping: {}, Character: {}, flooding packet (opc: {} (0x{:X}), count: {})", + Session->GetAccountId(), Session->GetRemoteAddress(), Session->GetLatency(), Session->GetPlayerName(), + opcodeTable[static_cast(p.GetOpcode())]->Name, p.GetOpcode(), packetCounter.amountCounter); + } - LOG_INFO("network", "AntiDOS: Player automatically banned for {} seconds.", duration); - return false; + switch (WorldSession::DosProtection::Policy(policy->Policy)) + { + case WorldSession::DosProtection::Policy::Kick: + { + LOG_INFO("network", "AntiDOS: Player {} kicked!", Session->GetPlayerName()); + Session->KickPlayer(); + break; + } + case WorldSession::DosProtection::Policy::Ban: + { + uint32 bm = sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANMODE); + uint32 duration = sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANDURATION); // in seconds + std::string nameOrIp = ""; + switch (bm) + { + case 0: // Ban account + (void)AccountMgr::GetName(Session->GetAccountId(), nameOrIp); + sBan->BanAccount(nameOrIp, std::to_string(duration), "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); + break; + case 1: // Ban ip + nameOrIp = Session->GetRemoteAddress(); + sBan->BanIP(nameOrIp, std::to_string(duration), "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); + break; } + + LOG_INFO("network", "AntiDOS: Player automatically banned for {} seconds.", duration); + break; + } + case WorldSession::DosProtection::Policy::DropPacket: + { + LOG_INFO("network", "AntiDOS: Opcode packet {} from player {} will be dropped.", p.GetOpcode(), Session->GetPlayerName()); + break; + } default: // invalid policy - return true; - } -} - -uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) const -{ - uint32 maxPacketCounterAllowed; - switch (opcode) - { - // CPU usage sending 2000 packets/second on a 3.70 GHz 4 cores on Win x64 - // [% CPU mysqld] [%CPU worldserver RelWithDebInfo] - case CMSG_PLAYER_LOGIN: // 0 0.5 - case CMSG_NAME_QUERY: // 0 1 - case CMSG_PET_NAME_QUERY: // 0 1 - case CMSG_NPC_TEXT_QUERY: // 0 1 - case CMSG_ATTACKSTOP: // 0 1 - case CMSG_QUERY_QUESTS_COMPLETED: // 0 1 - case CMSG_QUERY_TIME: // 0 1 - case CMSG_CORPSE_MAP_POSITION_QUERY: // 0 1 - case CMSG_MOVE_TIME_SKIPPED: // 0 1 - case MSG_QUERY_NEXT_MAIL_TIME: // 0 1 - case CMSG_SET_SHEATHED: // 0 1 - case MSG_RAID_TARGET_UPDATE: // 0 1 - case CMSG_PLAYER_LOGOUT: // 0 1 - case CMSG_LOGOUT_REQUEST: // 0 1 - case CMSG_PET_RENAME: // 0 1 - case CMSG_QUESTGIVER_CANCEL: // 0 1 - case CMSG_QUESTGIVER_REQUEST_REWARD: // 0 1 - case CMSG_COMPLETE_CINEMATIC: // 0 1 - case CMSG_BANKER_ACTIVATE: // 0 1 - case CMSG_BUY_BANK_SLOT: // 0 1 - case CMSG_OPT_OUT_OF_LOOT: // 0 1 - case CMSG_DUEL_ACCEPTED: // 0 1 - case CMSG_DUEL_CANCELLED: // 0 1 - case CMSG_CALENDAR_COMPLAIN: // 0 1 - case CMSG_QUEST_QUERY: // 0 1.5 - case CMSG_ITEM_QUERY_SINGLE: // 0 1.5 - case CMSG_ITEM_NAME_QUERY: // 0 1.5 - case CMSG_GAMEOBJECT_QUERY: // 0 1.5 - case CMSG_CREATURE_QUERY: // 0 1.5 - case CMSG_QUESTGIVER_STATUS_QUERY: // 0 1.5 - case CMSG_GUILD_QUERY: // 0 1.5 - case CMSG_ARENA_TEAM_QUERY: // 0 1.5 - case CMSG_TAXINODE_STATUS_QUERY: // 0 1.5 - case CMSG_TAXIQUERYAVAILABLENODES: // 0 1.5 - case CMSG_QUESTGIVER_QUERY_QUEST: // 0 1.5 - case CMSG_PAGE_TEXT_QUERY: // 0 1.5 - case MSG_QUERY_GUILD_BANK_TEXT: // 0 1.5 - case MSG_CORPSE_QUERY: // 0 1.5 - case MSG_MOVE_SET_FACING: // 0 1.5 - case CMSG_REQUEST_PARTY_MEMBER_STATS: // 0 1.5 - case CMSG_QUESTGIVER_COMPLETE_QUEST: // 0 1.5 - case CMSG_SET_ACTION_BUTTON: // 0 1.5 - case CMSG_RESET_INSTANCES: // 0 1.5 - case CMSG_HEARTH_AND_RESURRECT: // 0 1.5 - case CMSG_TOGGLE_PVP: // 0 1.5 - case CMSG_PET_ABANDON: // 0 1.5 - case CMSG_ACTIVATETAXIEXPRESS: // 0 1.5 - case CMSG_ACTIVATETAXI: // 0 1.5 - case CMSG_SELF_RES: // 0 1.5 - case CMSG_UNLEARN_SKILL: // 0 1.5 - case CMSG_EQUIPMENT_SET_SAVE: // 0 1.5 - case CMSG_DELETEEQUIPMENT_SET: // 0 1.5 - case CMSG_DISMISS_CRITTER: // 0 1.5 - case CMSG_REPOP_REQUEST: // 0 1.5 - case CMSG_GROUP_INVITE: // 0 1.5 - case CMSG_GROUP_DECLINE: // 0 1.5 - case CMSG_GROUP_ACCEPT: // 0 1.5 - case CMSG_GROUP_UNINVITE_GUID: // 0 1.5 - case CMSG_GROUP_UNINVITE: // 0 1.5 - case CMSG_GROUP_DISBAND: // 0 1.5 - case CMSG_BATTLEMASTER_JOIN_ARENA: // 0 1.5 - case CMSG_LEAVE_BATTLEFIELD: // 0 1.5 - case MSG_GUILD_BANK_LOG_QUERY: // 0 2 - case CMSG_LOGOUT_CANCEL: // 0 2 - case CMSG_REALM_SPLIT: // 0 2 - case CMSG_ALTER_APPEARANCE: // 0 2 - case CMSG_QUEST_CONFIRM_ACCEPT: // 0 2 - case MSG_GUILD_EVENT_LOG_QUERY: // 0 2.5 - case CMSG_READY_FOR_ACCOUNT_DATA_TIMES: // 0 2.5 - case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY: // 0 2.5 - case CMSG_BEGIN_TRADE: // 0 2.5 - case CMSG_INITIATE_TRADE: // 0 3 - case CMSG_MESSAGECHAT: // 0 3.5 - case CMSG_INSPECT: // 0 3.5 - case CMSG_AREA_SPIRIT_HEALER_QUERY: // not profiled - case CMSG_STANDSTATECHANGE: // not profiled - case MSG_RANDOM_ROLL: // not profiled - case CMSG_TIME_SYNC_RESP: // not profiled - case CMSG_TRAINER_BUY_SPELL: // not profiled - case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: // not profiled - case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: // not profiled - case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: // not profiled - case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: // not profiled - case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: // not profiled - case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: // not profiled - case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: // not profiled - case CMSG_FORCE_TURN_RATE_CHANGE_ACK: // not profiled - case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: // not profiled - { - // "0" is a magic number meaning there's no limit for the opcode. - // All the opcodes above must cause little CPU usage and no sync/async database queries at all - maxPacketCounterAllowed = 0; - break; - } - - case CMSG_QUESTGIVER_ACCEPT_QUEST: // 0 4 - case CMSG_QUESTLOG_REMOVE_QUEST: // 0 4 - case CMSG_QUESTGIVER_CHOOSE_REWARD: // 0 4 - case CMSG_CONTACT_LIST: // 0 5 - case CMSG_LEARN_PREVIEW_TALENTS: // 0 6 - case CMSG_AUTOBANK_ITEM: // 0 6 - case CMSG_AUTOSTORE_BANK_ITEM: // 0 6 - case CMSG_WHO: // 0 7 - case CMSG_PLAYER_VEHICLE_ENTER: // 0 8 - case CMSG_LEARN_PREVIEW_TALENTS_PET: // not profiled - case MSG_MOVE_HEARTBEAT: - { - maxPacketCounterAllowed = 200; - break; - } - - case CMSG_GUILD_SET_PUBLIC_NOTE: // 1 2 1 async db query - case CMSG_GUILD_SET_OFFICER_NOTE: // 1 2 1 async db query - case CMSG_SET_CONTACT_NOTES: // 1 2.5 1 async db query - case CMSG_CALENDAR_GET_CALENDAR: // 0 1.5 medium upload bandwidth usage - case CMSG_GUILD_BANK_QUERY_TAB: // 0 3.5 medium upload bandwidth usage - case CMSG_QUERY_INSPECT_ACHIEVEMENTS: // 0 13 high upload bandwidth usage - case CMSG_GAMEOBJ_REPORT_USE: // not profiled - case CMSG_GAMEOBJ_USE: // not profiled - case MSG_PETITION_DECLINE: // not profiled - { - maxPacketCounterAllowed = 50; - break; - } - - case CMSG_QUEST_POI_QUERY: // 0 25 very high upload bandwidth usage - { - maxPacketCounterAllowed = MAX_QUEST_LOG_SIZE; - break; - } - - case CMSG_GM_REPORT_LAG: // 1 3 1 async db query - case CMSG_SPELLCLICK: // not profiled - case CMSG_REMOVE_GLYPH: // not profiled - case CMSG_DISMISS_CONTROLLED_VEHICLE: // not profiled - { - maxPacketCounterAllowed = 20; - break; - } - - case CMSG_PETITION_SIGN: // 9 4 2 sync 1 async db queries - case CMSG_TURN_IN_PETITION: // 8 5.5 2 sync db query - case CMSG_GROUP_CHANGE_SUB_GROUP: // 6 5 1 sync 1 async db queries - case CMSG_PETITION_QUERY: // 4 3.5 1 sync db query - case CMSG_CHAR_RACE_CHANGE: // 5 4 1 sync db query - case CMSG_CHAR_CUSTOMIZE: // 5 5 1 sync db query - case CMSG_CHAR_FACTION_CHANGE: // 5 5 1 sync db query - case CMSG_CHAR_DELETE: // 4 4 1 sync db query - case CMSG_DEL_FRIEND: // 7 5 1 async db query - case CMSG_ADD_FRIEND: // 6 4 1 async db query - case CMSG_CHAR_RENAME: // 5 3 1 async db query - case CMSG_GMSURVEY_SUBMIT: // 2 3 1 async db query - case CMSG_BUG: // 1 1 1 async db query - case CMSG_GROUP_SET_LEADER: // 1 2 1 async db query - case CMSG_GROUP_RAID_CONVERT: // 1 5 1 async db query - case CMSG_GROUP_ASSISTANT_LEADER: // 1 2 1 async db query - case CMSG_PETITION_BUY: // not profiled 1 sync 1 async db queries - case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: // not profiled - case CMSG_REQUEST_VEHICLE_PREV_SEAT: // not profiled - case CMSG_REQUEST_VEHICLE_NEXT_SEAT: // not profiled - case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: // not profiled - case CMSG_REQUEST_VEHICLE_EXIT: // not profiled - case CMSG_CONTROLLER_EJECT_PASSENGER: // not profiled - case CMSG_ITEM_REFUND: // not profiled - case CMSG_SOCKET_GEMS: // not profiled - case CMSG_WRAP_ITEM: // not profiled - case CMSG_REPORT_PVP_AFK: // not profiled - case CMSG_AUCTION_LIST_ITEMS: // not profiled - case CMSG_AUCTION_LIST_BIDDER_ITEMS: // not profiled - case CMSG_AUCTION_LIST_OWNER_ITEMS: // not profiled - { - maxPacketCounterAllowed = 10; - break; - } - - case CMSG_CHAR_CREATE: // 7 5 3 async db queries - case CMSG_CHAR_ENUM: // 22 3 2 async db queries - case CMSG_GMTICKET_CREATE: // 1 25 1 async db query - case CMSG_GMTICKET_UPDATETEXT: // 0 15 1 async db query - case CMSG_GMTICKET_DELETETICKET: // 1 25 1 async db query - case CMSG_GMRESPONSE_RESOLVE: // 1 25 1 async db query - case CMSG_CALENDAR_ADD_EVENT: // 21 10 2 async db query - case CMSG_CALENDAR_UPDATE_EVENT: // not profiled - case CMSG_CALENDAR_REMOVE_EVENT: // not profiled - case CMSG_CALENDAR_COPY_EVENT: // not profiled - case CMSG_CALENDAR_EVENT_INVITE: // not profiled - case CMSG_CALENDAR_EVENT_SIGNUP: // not profiled - case CMSG_CALENDAR_EVENT_RSVP: // not profiled - case CMSG_CALENDAR_EVENT_REMOVE_INVITE: // not profiled - case CMSG_CALENDAR_EVENT_MODERATOR_STATUS: // not profiled - case CMSG_ARENA_TEAM_INVITE: // not profiled - case CMSG_ARENA_TEAM_ACCEPT: // not profiled - case CMSG_ARENA_TEAM_DECLINE: // not profiled - case CMSG_ARENA_TEAM_LEAVE: // not profiled - case CMSG_ARENA_TEAM_DISBAND: // not profiled - case CMSG_ARENA_TEAM_REMOVE: // not profiled - case CMSG_ARENA_TEAM_LEADER: // not profiled - case CMSG_LOOT_METHOD: // not profiled - case CMSG_GUILD_INVITE: // not profiled - case CMSG_GUILD_ACCEPT: // not profiled - case CMSG_GUILD_DECLINE: // not profiled - case CMSG_GUILD_LEAVE: // not profiled - case CMSG_GUILD_DISBAND: // not profiled - case CMSG_GUILD_LEADER: // not profiled - case CMSG_GUILD_MOTD: // not profiled - case CMSG_GUILD_RANK: // not profiled - case CMSG_GUILD_ADD_RANK: // not profiled - case CMSG_GUILD_DEL_RANK: // not profiled - case CMSG_GUILD_INFO_TEXT: // not profiled - case CMSG_GUILD_BANK_DEPOSIT_MONEY: // not profiled - case CMSG_GUILD_BANK_WITHDRAW_MONEY: // not profiled - case CMSG_GUILD_BANK_BUY_TAB: // not profiled - case CMSG_GUILD_BANK_UPDATE_TAB: // not profiled - case CMSG_SET_GUILD_BANK_TEXT: // not profiled - case MSG_SAVE_GUILD_EMBLEM: // not profiled - case MSG_PETITION_RENAME: // not profiled - case MSG_TALENT_WIPE_CONFIRM: // not profiled - case MSG_SET_DUNGEON_DIFFICULTY: // not profiled - case MSG_SET_RAID_DIFFICULTY: // not profiled - case MSG_PARTY_ASSIGNMENT: // not profiled - case MSG_RAID_READY_CHECK: // not profiled - { - maxPacketCounterAllowed = 3; - break; - } - - case CMSG_ITEM_REFUND_INFO: // not profiled - { - maxPacketCounterAllowed = PLAYER_SLOTS_COUNT; - break; - } - - default: - { - maxPacketCounterAllowed = 100; - break; - } + break; } - return maxPacketCounterAllowed; + return WorldSession::DosProtection::Policy(policy->Policy); } WorldSession::DosProtection::DosProtection(WorldSession* s) : - Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY)) { } + Session(s) { } void WorldSession::ResetTimeSync() { diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index dca054f15..73ec2b542 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -322,7 +322,7 @@ protected: struct PacketCounter { time_t lastReceiveTime; - uint32 amountCounter; + uint16 amountCounter; }; /// Player session in the World @@ -1104,22 +1104,21 @@ protected: { friend class World; public: - DosProtection(WorldSession* s); - bool EvaluateOpcode(WorldPacket& p, time_t time) const; - protected: - enum Policy + enum class Policy { - POLICY_LOG, - POLICY_KICK, - POLICY_BAN + Process, + Kick, + Ban, + Log, + BlockingThrottle, + DropPacket }; - uint32 GetMaxPacketCounterAllowed(uint16 opcode) const; - + DosProtection(WorldSession* s); + Policy EvaluateOpcode(WorldPacket const& p, time_t const time) const; + protected: WorldSession* Session; - private: - Policy _policy; typedef std::unordered_map PacketThrottlingMap; // mark this member as "mutable" so it can be modified even in const functions mutable PacketThrottlingMap _PacketThrottlingMap; diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 10f69f30b..a8afd153e 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -366,7 +366,6 @@ enum WorldIntConfigs CONFIG_WINTERGRASP_BATTLETIME, CONFIG_WINTERGRASP_NOBATTLETIME, CONFIG_WINTERGRASP_RESTART_AFTER_CRASH, - CONFIG_PACKET_SPOOF_POLICY, CONFIG_PACKET_SPOOF_BANMODE, CONFIG_PACKET_SPOOF_BANDURATION, CONFIG_WARDEN_CLIENT_RESPONSE_DELAY, diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 298184eb4..e62ae480f 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -90,6 +90,7 @@ #include "WaypointMovementGenerator.h" #include "WeatherMgr.h" #include "WhoListCacheMgr.h" +#include "WorldGlobals.h" #include "WorldPacket.h" #include "WorldSession.h" #include "WorldSessionMgr.h" @@ -1196,7 +1197,6 @@ void World::LoadConfigSettings(bool reload) _bool_configs[CONFIG_SET_ALL_CREATURES_WITH_WAYPOINT_MOVEMENT_ACTIVE] = sConfigMgr->GetOption("SetAllCreaturesWithWaypointMovementActive", false); // packet spoof punishment - _int_configs[CONFIG_PACKET_SPOOF_POLICY] = sConfigMgr->GetOption("PacketSpoof.Policy", (uint32)WorldSession::DosProtection::POLICY_KICK); _int_configs[CONFIG_PACKET_SPOOF_BANMODE] = sConfigMgr->GetOption("PacketSpoof.BanMode", (uint32)0); if (_int_configs[CONFIG_PACKET_SPOOF_BANMODE] > 1) _int_configs[CONFIG_PACKET_SPOOF_BANMODE] = (uint32)0; @@ -1952,6 +1952,9 @@ void World::SetInitialWorldSettings() LOG_INFO("server.loading", "Load Channels..."); ChannelMgr::LoadChannels(); + LOG_INFO("server.loading", "Loading AntiDos opcode policies"); + sWorldGlobals->LoadAntiDosOpcodePolicies(); + sScriptMgr->OnBeforeWorldInitialized(); if (sWorld->getBoolConfig(CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS)) diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 62bfe7712..45434d502 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -47,6 +47,7 @@ EndScriptData */ #include "Tokenize.h" #include "WardenCheckMgr.h" #include "WaypointMgr.h" +#include "WorldGlobals.h" using namespace Acore::ChatCommands; @@ -73,6 +74,7 @@ public: }; static ChatCommandTable reloadCommandTable = { + { "antidos_opcode_policies", HandleReloadAntiDosOpcodePoliciesCommand, SEC_ADMINISTRATOR, Console::Yes }, { "auctions", HandleReloadAuctionsCommand, SEC_ADMINISTRATOR, Console::Yes }, { "dungeon_access_template", HandleReloadDungeonAccessCommand, SEC_ADMINISTRATOR, Console::Yes }, { "dungeon_access_requirements", HandleReloadDungeonAccessCommand, SEC_ADMINISTRATOR, Console::Yes }, @@ -1199,6 +1201,14 @@ public: return true; } + static bool HandleReloadAntiDosOpcodePoliciesCommand(ChatHandler* handler) + { + LOG_INFO("server.loading", "Reloading AntiDos opcode policies..."); + sWorldGlobals->LoadAntiDosOpcodePolicies(); + handler->SendGlobalGMSysMessage("AntiDos opcode policies reloaded."); + return true; + } + static bool HandleReloadAuctionsCommand(ChatHandler* handler) { ///- Reload dynamic data tables from the database From 880804d6fab7b0f9375810891279cc64a61f91dd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Feb 2025 06:18:37 +0000 Subject: [PATCH 85/97] chore(DB): import pending files Referenced commit(s): 4cd1ed218147905532d3c43c524db716420367fc --- .../rev_1739897580268046640.sql => db_world/2025_02_21_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1739897580268046640.sql => db_world/2025_02_21_00.sql} (98%) diff --git a/data/sql/updates/pending_db_world/rev_1739897580268046640.sql b/data/sql/updates/db_world/2025_02_21_00.sql similarity index 98% rename from data/sql/updates/pending_db_world/rev_1739897580268046640.sql rename to data/sql/updates/db_world/2025_02_21_00.sql index edccc5777..86fb9a021 100644 --- a/data/sql/updates/pending_db_world/rev_1739897580268046640.sql +++ b/data/sql/updates/db_world/2025_02_21_00.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_19_01 -> 2025_02_21_00 DROP TABLE IF EXISTS `antidos_opcode_policies`; CREATE TABLE `antidos_opcode_policies` ( `Opcode` smallint unsigned NOT NULL, From 609b1b731a01010817f9d82ddfa1bf7159132e57 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Fri, 21 Feb 2025 16:26:41 -0300 Subject: [PATCH 86/97] fix(Scripts/SunwellPlateau): Fix twin marks not applying from dots (#21415) --- .../rev_1740009727651918300.sql | 7 ++++ .../SunwellPlateau/boss_eredar_twins.cpp | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1740009727651918300.sql diff --git a/data/sql/updates/pending_db_world/rev_1740009727651918300.sql b/data/sql/updates/pending_db_world/rev_1740009727651918300.sql new file mode 100644 index 000000000..d8ebb16dc --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1740009727651918300.sql @@ -0,0 +1,7 @@ +-- +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_eredar_twins_handle_dark_touched_periodic', 'spell_eredar_twins_handle_flame_touched_periodic', 'spell_eredar_twins_handle_flame_touched_flame_sear'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(45342, 'spell_eredar_twins_handle_flame_touched_periodic'), +(45271, 'spell_eredar_twins_handle_dark_touched_periodic'), +(46771, 'spell_eredar_twins_handle_flame_touched_flame_sear'); diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp index a47d16bda..75de3d41c 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp @@ -377,6 +377,35 @@ class spell_eredar_twins_blaze : public SpellScript } }; +class spell_eredar_twins_handle_touch_periodic : public AuraScript +{ + PrepareAuraScript(spell_eredar_twins_handle_touch_periodic); + +public: + spell_eredar_twins_handle_touch_periodic(uint32 touchSpell, uint8 effIndex, uint8 aura) : AuraScript(), _touchSpell(touchSpell), _effectIndex(effIndex), _aura(aura) {} + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ _touchSpell }); + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + if (Unit* owner = GetOwner()->ToUnit()) + owner->CastSpell(owner, _touchSpell, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_eredar_twins_handle_touch_periodic::OnPeriodic, _effectIndex, _aura); + } + +private: + uint32 _touchSpell; + uint8 _effectIndex; + uint8 _aura; +}; + class at_sunwell_eredar_twins : public OnlyOnceAreaTriggerScript { public: @@ -404,5 +433,8 @@ void AddSC_boss_eredar_twins() RegisterSpellScriptWithArgs(spell_eredar_twins_apply_touch, "spell_eredar_twins_apply_flame_touched", SPELL_FLAME_TOUCHED); RegisterSpellScript(spell_eredar_twins_handle_touch); RegisterSpellScript(spell_eredar_twins_blaze); + RegisterSpellScriptWithArgs(spell_eredar_twins_handle_touch_periodic, "spell_eredar_twins_handle_dark_touched_periodic", SPELL_DARK_TOUCHED, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE); + RegisterSpellScriptWithArgs(spell_eredar_twins_handle_touch_periodic, "spell_eredar_twins_handle_flame_touched_periodic", SPELL_FLAME_TOUCHED, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + RegisterSpellScriptWithArgs(spell_eredar_twins_handle_touch_periodic, "spell_eredar_twins_handle_flame_touched_flame_sear", SPELL_FLAME_TOUCHED, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE); new at_sunwell_eredar_twins(); } From 0161a611efcc72f323088c92f36ed258f5a05f89 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Feb 2025 19:27:42 +0000 Subject: [PATCH 87/97] chore(DB): import pending files Referenced commit(s): 609b1b731a01010817f9d82ddfa1bf7159132e57 --- .../rev_1740009727651918300.sql => db_world/2025_02_21_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1740009727651918300.sql => db_world/2025_02_21_01.sql} (91%) diff --git a/data/sql/updates/pending_db_world/rev_1740009727651918300.sql b/data/sql/updates/db_world/2025_02_21_01.sql similarity index 91% rename from data/sql/updates/pending_db_world/rev_1740009727651918300.sql rename to data/sql/updates/db_world/2025_02_21_01.sql index d8ebb16dc..808e316c7 100644 --- a/data/sql/updates/pending_db_world/rev_1740009727651918300.sql +++ b/data/sql/updates/db_world/2025_02_21_01.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_21_00 -> 2025_02_21_01 -- DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_eredar_twins_handle_dark_touched_periodic', 'spell_eredar_twins_handle_flame_touched_periodic', 'spell_eredar_twins_handle_flame_touched_flame_sear'); From d145b866a5fcbf12618a0fe0ba9f7797e85eaa63 Mon Sep 17 00:00:00 2001 From: Takenbacon Date: Fri, 21 Feb 2025 11:49:39 -0800 Subject: [PATCH 88/97] fix(Core/Maps): Fix instance factions (#21577) --- src/server/game/Maps/Map.cpp | 9 ---- src/server/game/Maps/MapInstanced.cpp | 18 +++++-- src/server/game/Maps/MapInstanced.h | 2 +- .../ForgeOfSouls/instance_forge_of_souls.cpp | 53 ++++--------------- 4 files changed, 26 insertions(+), 56 deletions(-) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 38f501bb3..5e04e0ba6 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2206,15 +2206,6 @@ bool InstanceMap::AddPlayerToMap(Player* player) m_resetAfterUnload = false; m_unloadWhenEmpty = false; - if (instance_data && instance_data->IsTwoFactionInstance() - && instance_data->GetTeamIdInInstance() == TEAM_NEUTRAL) - { - instance_data->SetTeamIdInInstance(player->GetTeamId()); - if (Group* group = player->GetGroup()) - if (Player* leader = ObjectAccessor::FindConnectedPlayer(group->GetLeaderGUID())) - instance_data->SetTeamIdInInstance(leader->GetTeamId()); - } - // this will acquire the same mutex so it cannot be in the previous block Map::AddPlayerToMap(player); diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 8b42389e3..9d8172a73 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -147,7 +147,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) map = FindInstanceMap(destInstId); if (!map) - map = CreateInstance(destInstId, pSave, realdiff); + map = CreateInstance(destInstId, pSave, realdiff, player); else if (IsSharedDifficultyMap(mapId) && !map->HavePlayers() && map->GetDifficulty() != realdiff) { if (player->isBeingLoaded()) // pussywizard: crashfix (assert(passengers.empty) fail in ~transport), could be added to a transport during loading from db @@ -160,7 +160,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) if (i->first == destInstId) { DestroyInstance(i); - map = CreateInstance(destInstId, pSave, realdiff); + map = CreateInstance(destInstId, pSave, realdiff, player); break; } } @@ -170,14 +170,14 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) uint32 newInstanceId = sMapMgr->GenerateInstanceId(); ASSERT(!FindInstanceMap(newInstanceId)); // pussywizard: instance with new id can't exist Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); - map = CreateInstance(newInstanceId, nullptr, diff); + map = CreateInstance(newInstanceId, nullptr, diff, player); } } return map; } -InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty) +InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty, Player* player) { // load/create a map std::lock_guard guard(Lock); @@ -213,6 +213,16 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, else map->CreateInstanceScript(false, "", 0); + if (map->GetInstanceScript() && map->GetInstanceScript()->IsTwoFactionInstance() + && map->GetInstanceScript()->GetTeamIdInInstance() == TEAM_NEUTRAL) + { + ASSERT(player); // Player should exist, as checked by in MapInstanced::CreateInstanceForPlayer + map->GetInstanceScript()->SetTeamIdInInstance(player->GetTeamId()); + if (Group* group = player->GetGroup()) + if (Player* leader = ObjectAccessor::FindConnectedPlayer(group->GetLeaderGUID())) + map->GetInstanceScript()->SetTeamIdInInstance(leader->GetTeamId()); + } + map->OnCreateMap(); if (!save) // this is for sure a dungeon (assert above), no need to check here diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h index f08c5687a..e50057c9e 100644 --- a/src/server/game/Maps/MapInstanced.h +++ b/src/server/game/Maps/MapInstanced.h @@ -50,7 +50,7 @@ public: void InitVisibilityDistance() override; private: - InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty); + InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty, Player* player); BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg); InstancedMaps m_InstancedMaps; diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp index c39c3a5e6..812e2f3e5 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp @@ -46,7 +46,6 @@ public: } uint32 m_auiEncounter[MAX_ENCOUNTER]; - TeamId teamIdInInstance; std::string str_data; ObjectGuid NPC_BronjahmGUID; ObjectGuid NPC_DevourerGUID; @@ -59,7 +58,6 @@ public: void Initialize() override { memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - teamIdInInstance = TEAM_NEUTRAL; } bool IsEncounterInProgress() const override @@ -72,21 +70,7 @@ public: void OnPlayerEnter(Player* player) override { - if (teamIdInInstance == TEAM_NEUTRAL) - { - if (Group* group = player->GetGroup()) - { - if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID())) - teamIdInInstance = Player::TeamIdForRace(gLeader->getRace()); - else - teamIdInInstance = player->GetTeamId(); - } - else - teamIdInInstance = player->GetTeamId(); - } - - if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) - player->SetFaction((teamIdInInstance == TEAM_HORDE) ? 1610 : 1); + InstanceScript::OnPlayerEnter(player); // this will happen only after crash and loading the instance from db if (m_auiEncounter[0] == DONE && m_auiEncounter[1] == DONE && (!NPC_LeaderSecondGUID || !instance->GetCreature(NPC_LeaderSecondGUID))) @@ -98,24 +82,6 @@ public: void OnCreatureCreate(Creature* creature) override { - if (teamIdInInstance == TEAM_NEUTRAL) - { - Map::PlayerList const& players = instance->GetPlayers(); - if (!players.IsEmpty()) - if (Player* player = players.begin()->GetSource()) - { - if (Group* group = player->GetGroup()) - { - if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID())) - teamIdInInstance = Player::TeamIdForRace(gLeader->getRace()); - else - teamIdInInstance = player->GetTeamId(); - } - else - teamIdInInstance = player->GetTeamId(); - } - } - switch (creature->GetEntry()) { case NPC_BRONJAHM: @@ -125,7 +91,7 @@ public: NPC_DevourerGUID = creature->GetGUID(); break; case NPC_SYLVANAS_PART1: - if (teamIdInInstance == TEAM_ALLIANCE) + if (GetTeamIdInInstance() == TEAM_ALLIANCE) creature->UpdateEntry(NPC_JAINA_PART1); NPC_LeaderFirstGUID = creature->GetGUID(); @@ -133,12 +99,12 @@ public: creature->SetVisible(false); break; case NPC_SYLVANAS_PART2: - if (teamIdInInstance == TEAM_ALLIANCE) + if (GetTeamIdInInstance() == TEAM_ALLIANCE) creature->UpdateEntry(NPC_JAINA_PART2); NPC_LeaderSecondGUID = creature->GetGUID(); break; case NPC_LORALEN: - if (teamIdInInstance == TEAM_ALLIANCE) + if (GetTeamIdInInstance() == TEAM_ALLIANCE) creature->UpdateEntry(NPC_ELANDRA); if (!NPC_GuardFirstGUID) { @@ -148,7 +114,7 @@ public: } break; case NPC_KALIRA: - if (teamIdInInstance == TEAM_ALLIANCE) + if (GetTeamIdInInstance() == TEAM_ALLIANCE) creature->UpdateEntry(NPC_KORELN); if (!NPC_GuardSecondGUID) { @@ -170,9 +136,12 @@ public: leader->GetMotionMaster()->MovePoint(1, boss->GetPositionX() + 10.0f * cos(angle), boss->GetPositionY() + 10.0f * std::sin(angle), boss->GetPositionZ()); } - for (int8 i = 0; outroPositions[i].entry[teamIdInInstance] != 0; ++i) - if (Creature* summon = instance->SummonCreature(outroPositions[i].entry[teamIdInInstance], outroPositions[i].startPosition)) - summon->GetMotionMaster()->MovePath(outroPositions[i].pathId, false); + if (GetTeamIdInInstance() < TEAM_NEUTRAL) // Shouldn't happen, but just in case. + { + for (int8 i = 0; outroPositions[i].entry[GetTeamIdInInstance()] != 0; ++i) + if (Creature* summon = instance->SummonCreature(outroPositions[i].entry[GetTeamIdInInstance()], outroPositions[i].startPosition)) + summon->GetMotionMaster()->MovePath(outroPositions[i].pathId, false); + } } void SetData(uint32 type, uint32 data) override From 8166664da45794c27a74e9932d41daeb8bc7b807 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Fri, 21 Feb 2025 19:38:20 -0300 Subject: [PATCH 89/97] fix(DB/SAI): Fix Kael Flamestrikes chasing players (#21579) --- data/sql/updates/pending_db_world/rev_1740172521802548800.sql | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1740172521802548800.sql diff --git a/data/sql/updates/pending_db_world/rev_1740172521802548800.sql b/data/sql/updates/pending_db_world/rev_1740172521802548800.sql new file mode 100644 index 000000000..bd7d4ddaa --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1740172521802548800.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `smart_scripts` WHERE (`entryorguid` = 24666) AND (`source_type` = 0) AND (`id` IN (4)); +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 +(24666, 0, 4, 0, 37, 0, 100, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flame Strike Trigger (Kael - 5Man) - On Initialize - Set Reactstate Passive'); From 5aed1624c89740d397a90942ed965ae5d0c7991f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Feb 2025 22:39:25 +0000 Subject: [PATCH 90/97] chore(DB): import pending files Referenced commit(s): 8166664da45794c27a74e9932d41daeb8bc7b807 --- .../rev_1740172521802548800.sql => db_world/2025_02_21_02.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1740172521802548800.sql => db_world/2025_02_21_02.sql} (94%) diff --git a/data/sql/updates/pending_db_world/rev_1740172521802548800.sql b/data/sql/updates/db_world/2025_02_21_02.sql similarity index 94% rename from data/sql/updates/pending_db_world/rev_1740172521802548800.sql rename to data/sql/updates/db_world/2025_02_21_02.sql index bd7d4ddaa..d71febcdd 100644 --- a/data/sql/updates/pending_db_world/rev_1740172521802548800.sql +++ b/data/sql/updates/db_world/2025_02_21_02.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_21_01 -> 2025_02_21_02 -- DELETE FROM `smart_scripts` WHERE (`entryorguid` = 24666) AND (`source_type` = 0) AND (`id` IN (4)); INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES From 4216d196c247fbdbf12487f8214727c22f5bf530 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Fri, 21 Feb 2025 23:43:21 +0100 Subject: [PATCH 91/97] fix(Scripts/ZulAman): scout drum and hard CC interaction (#21281) --- .../EasternKingdoms/ZulAman/zulaman.cpp | 51 +++++++++++-------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp index 7e1f7465c..aaaaf409c 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp @@ -710,7 +710,6 @@ private: enum AmanishiScout { NPC_WORLD_TRIGGER = 22515, - POINT_DRUM = 0, SAY_AGGRO = 0, SPELL_ALERT_DRUMS = 42177, SPELL_MULTI_SHOT = 43205, @@ -737,6 +736,8 @@ struct npc_amanishi_scout : public ScriptedAI { scheduler.CancelAll(); me->SetCombatMovement(false); + me->SetReactState(REACT_AGGRESSIVE); + _drumGUID.Clear(); } void JustEngagedWith(Unit* /*who*/) override @@ -748,30 +749,38 @@ struct npc_amanishi_scout : public ScriptedAI GetCreatureListWithEntryInGrid(triggers, me, NPC_WORLD_TRIGGER, 50.0f); triggers.remove_if([](Creature* trigger) {return !IsDrum(trigger);}); triggers.sort(Acore::ObjectDistanceOrderPred(me)); - if (!triggers.empty()) - { - me->ClearTarget(); - Creature* closestDrum = triggers.front(); - me->GetMotionMaster()->MovePoint(POINT_DRUM, closestDrum->GetPositionX(), closestDrum->GetPositionY(), closestDrum->GetPositionZ()); - } - else + if (triggers.empty()) ScheduleCombat(); - } - - void MovementInform(uint32 type, uint32 id) override - { - if (type == POINT_MOTION_TYPE && id == POINT_DRUM) + Creature* closestDrum = triggers.front(); + me->GetMotionMaster()->MoveFollow(closestDrum, 0.0f, 0.0f); + _drumGUID = closestDrum->GetGUID(); + me->ClearTarget(); + me->SetReactState(REACT_PASSIVE); + scheduler.Schedule(1s, [this](TaskContext context) { - DoCastSelf(SPELL_ALERT_DRUMS); - scheduler.Schedule(5s, [this](TaskContext /*context*/) - { - ScheduleCombat(); - }); - } + if (_drumGUID) + if (Creature* drum = ObjectAccessor::GetCreature(*me, _drumGUID)) + { + if (me->IsWithinRange(drum, INTERACTION_DISTANCE)) + { + me->SetFacingToObject(drum); + DoCastSelf(SPELL_ALERT_DRUMS); + scheduler.Schedule(5s, [this](TaskContext /*context*/) + { + ScheduleCombat(); + }); + return; + } + context.Repeat(1s); + return; + } + ScheduleCombat(); + }); } void ScheduleCombat() { + me->SetReactState(REACT_AGGRESSIVE); me->SetCombatMovement(true); if (Unit* victim = me->GetVictim()) me->GetMotionMaster()->MoveChase(victim); @@ -790,11 +799,13 @@ struct npc_amanishi_scout : public ScriptedAI { scheduler.Update(diff); - if (!UpdateVictim()) + if (!me->IsCombatMovementAllowed() || !UpdateVictim()) return; DoMeleeAttackIfReady(); } +private: + ObjectGuid _drumGUID; }; enum SpellAlertDrums From 4987e83232084cf9b6850129d8bfab8a345f93c0 Mon Sep 17 00:00:00 2001 From: Tereneckla Date: Fri, 21 Feb 2025 22:47:09 +0000 Subject: [PATCH 92/97] fix(DB/Creature): let Magister's Terrace Normal bosses give reputation until exalted and reduce Kael'thas reputation gain (#21532) --- data/sql/updates/pending_db_world/rev_1739972100933255718.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1739972100933255718.sql diff --git a/data/sql/updates/pending_db_world/rev_1739972100933255718.sql b/data/sql/updates/pending_db_world/rev_1739972100933255718.sql new file mode 100644 index 000000000..2ab0f9fc5 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1739972100933255718.sql @@ -0,0 +1,3 @@ +-- +UPDATE `creature_onkill_reputation` SET `RewOnKillRepValue1` = 120 WHERE (`creature_id` = 24664); +UPDATE `creature_onkill_reputation` SET `MaxStanding1` = 7 WHERE `creature_id` IN (24723, 24560, 24664, 24744); From eed4c3515d81d154c66157cea0c338db49cfc231 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Feb 2025 22:48:08 +0000 Subject: [PATCH 93/97] chore(DB): import pending files Referenced commit(s): 4987e83232084cf9b6850129d8bfab8a345f93c0 --- .../rev_1739972100933255718.sql => db_world/2025_02_21_03.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1739972100933255718.sql => db_world/2025_02_21_03.sql} (82%) diff --git a/data/sql/updates/pending_db_world/rev_1739972100933255718.sql b/data/sql/updates/db_world/2025_02_21_03.sql similarity index 82% rename from data/sql/updates/pending_db_world/rev_1739972100933255718.sql rename to data/sql/updates/db_world/2025_02_21_03.sql index 2ab0f9fc5..f0152a476 100644 --- a/data/sql/updates/pending_db_world/rev_1739972100933255718.sql +++ b/data/sql/updates/db_world/2025_02_21_03.sql @@ -1,3 +1,4 @@ +-- DB update 2025_02_21_02 -> 2025_02_21_03 -- UPDATE `creature_onkill_reputation` SET `RewOnKillRepValue1` = 120 WHERE (`creature_id` = 24664); UPDATE `creature_onkill_reputation` SET `MaxStanding1` = 7 WHERE `creature_id` IN (24723, 24560, 24664, 24744); From 3fcccf2a2e294ab45f93b485d0b0404581e9b679 Mon Sep 17 00:00:00 2001 From: Paul <60552737+demetrzz@users.noreply.github.com> Date: Sat, 22 Feb 2025 01:50:33 +0300 Subject: [PATCH 94/97] fix(Core/Spells): Fixed misdirection triggering from mend pet (#21526) Co-authored-by: pavel_k --- src/server/scripts/Spells/spell_hunter.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 637b355ab..ba7a82768 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -887,8 +887,11 @@ class spell_hun_misdirection : public AuraScript GetTarget()->ResetRedirectThreat(); } - bool CheckProc(ProcEventInfo& /*eventInfo*/) + bool CheckProc(ProcEventInfo& eventInfo) { + // Do not trigger from Mend Pet + if (eventInfo.GetProcSpell() && (eventInfo.GetProcSpell()->GetSpellInfo()->SpellFamilyFlags[0] & 0x800000)) + return false; return GetTarget()->GetRedirectThreatTarget(); } From dc646e8304849cba9b5a73f243503ba276479099 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Fri, 21 Feb 2025 22:10:19 -0300 Subject: [PATCH 95/97] fix(DB/Creature): Fix Steel Gate Flying Machine inhabit type (#21582) --- data/sql/updates/pending_db_world/rev_1740180429215360500.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1740180429215360500.sql diff --git a/data/sql/updates/pending_db_world/rev_1740180429215360500.sql b/data/sql/updates/pending_db_world/rev_1740180429215360500.sql new file mode 100644 index 000000000..32d91557f --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1740180429215360500.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template_movement` SET `Flight` = 2 WHERE `CreatureId` = 24418; From 490686722093c0bb21c8e1d96d7e62ef5c538d52 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Fri, 21 Feb 2025 22:10:39 -0300 Subject: [PATCH 96/97] fix(Core/Spells): Ingvar Smash and Dark Smash should not ignore LOS (#21581) --- src/server/game/Spells/SpellInfoCorrections.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index dc2ecf080..35092327e 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4884,6 +4884,13 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_1].RealPointsPerLevel = 0.25; }); + // Smash + // Dark Smash + ApplySpellFix({ 42669, 59706, 42723, 59709 }, [](SpellInfo* spellInfo) + { + spellInfo->AttributesEx2 &= ~SPELL_ATTR2_IGNORE_LINE_OF_SIGHT; + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; From 29db247503b7cf04b0a3b7ba77ab9a9d5a6c8bb9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 22 Feb 2025 01:11:18 +0000 Subject: [PATCH 97/97] chore(DB): import pending files Referenced commit(s): dc646e8304849cba9b5a73f243503ba276479099 --- .../rev_1740180429215360500.sql => db_world/2025_02_22_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1740180429215360500.sql => db_world/2025_02_22_00.sql} (65%) diff --git a/data/sql/updates/pending_db_world/rev_1740180429215360500.sql b/data/sql/updates/db_world/2025_02_22_00.sql similarity index 65% rename from data/sql/updates/pending_db_world/rev_1740180429215360500.sql rename to data/sql/updates/db_world/2025_02_22_00.sql index 32d91557f..754270606 100644 --- a/data/sql/updates/pending_db_world/rev_1740180429215360500.sql +++ b/data/sql/updates/db_world/2025_02_22_00.sql @@ -1,2 +1,3 @@ +-- DB update 2025_02_21_03 -> 2025_02_22_00 -- UPDATE `creature_template_movement` SET `Flight` = 2 WHERE `CreatureId` = 24418;