From 7d431dc796b14e5eaeb1b28733d3826a5be1a1ca Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 19 Feb 2025 22:29:36 +0800 Subject: [PATCH] Merge branch 'master' into Playerbot --- .../{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 + .github/README.md | 2 +- .github/actions/linux-build/action.yml | 9 +- .github/workflows/core_modules_build.yml | 1 + apps/ci/ci-install-modules.sh | 1 + apps/codestyle/codestyle-sql.py | 2 +- apps/installer/includes/os_configs/windows.sh | 2 +- data/sql/updates/db_auth/2025_02_16_00.sql | 5 + data/sql/updates/db_auth/2025_02_16_01.sql | 11 + .../updates/db_characters/2025_02_12_00.sql | 11 + .../updates/db_characters/2025_02_16_00.sql | 11 + data/sql/updates/db_world/2025_02_12_00.sql | 96 ++ data/sql/updates/db_world/2025_02_12_01.sql | 3 + data/sql/updates/db_world/2025_02_13_00.sql | 7 + data/sql/updates/db_world/2025_02_13_01.sql | 25 + data/sql/updates/db_world/2025_02_14_00.sql | 23 + data/sql/updates/db_world/2025_02_15_00.sql | 239 ++++ data/sql/updates/db_world/2025_02_15_01.sql | 10 + data/sql/updates/db_world/2025_02_15_02.sql | 17 + data/sql/updates/db_world/2025_02_16_00.sql | 77 ++ data/sql/updates/db_world/2025_02_16_01.sql | 11 + data/sql/updates/db_world/2025_02_16_02.sql | 2 + data/sql/updates/db_world/2025_02_16_03.sql | 14 + data/sql/updates/db_world/2025_02_18_00.sql | 21 + data/sql/updates/db_world/2025_02_19_00.sql | 7 + src/common/Collision/Maps/MapDefines.h | 1 + src/common/Utilities/Containers.h | 24 +- src/common/Utilities/Random.h | 3 +- src/server/apps/worldserver/Main.cpp | 8 +- .../apps/worldserver/worldserver.conf.dist | 64 +- src/server/database/Database/Field.cpp | 6 +- src/server/database/Updater/UpdateFetcher.cpp | 10 +- src/server/database/Updater/UpdateFetcher.h | 5 + src/server/game/AI/CoreAI/UnitAI.h | 2 +- src/server/game/AI/SmartScripts/SmartAI.cpp | 2 +- src/server/game/AI/SmartScripts/SmartAI.h | 2 +- .../game/Achievements/AchievementMgr.cpp | 24 +- src/server/game/Battlefield/Battlefield.cpp | 3 +- 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 | 12 +- src/server/game/Battlegrounds/Arena.h | 2 +- .../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 + src/server/game/Battlegrounds/Battleground.h | 3 +- .../game/Battlegrounds/BattlegroundMgr.cpp | 12 + .../game/Battlegrounds/BattlegroundMgr.h | 1 + .../game/Battlegrounds/BattlegroundQueue.cpp | 4 +- .../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/Cache/WhoListCacheMgr.cpp | 3 +- src/server/game/Chat/Chat.cpp | 11 +- src/server/game/Combat/ThreatMgr.cpp | 4 +- src/server/game/Conditions/DisableMgr.cpp | 10 +- src/server/game/Conditions/DisableMgr.h | 9 +- src/server/game/DungeonFinding/LFGMgr.cpp | 2 +- src/server/game/DungeonFinding/LFGScripts.cpp | 10 +- src/server/game/DungeonFinding/LFGScripts.h | 10 +- .../game/Entities/Creature/Creature.cpp | 12 +- .../game/Entities/Creature/CreatureGroups.cpp | 1 + .../game/Entities/Creature/GossipDef.cpp | 14 +- .../Entities/Creature/TemporarySummon.cpp | 2 +- .../game/Entities/GameObject/GameObject.cpp | 5 +- .../game/Entities/Item/ItemEnchantmentMgr.cpp | 1 + src/server/game/Entities/Object/Object.cpp | 11 +- src/server/game/Entities/Object/Position.h | 5 + src/server/game/Entities/Pet/Pet.cpp | 22 +- src/server/game/Entities/Pet/Pet.h | 2 +- .../game/Entities/Player/KillRewarder.cpp | 4 +- src/server/game/Entities/Player/Player.cpp | 1193 ++++++++-------- src/server/game/Entities/Player/Player.h | 4 +- .../game/Entities/Player/PlayerMisc.cpp | 2 +- .../game/Entities/Player/PlayerQuest.cpp | 14 +- .../game/Entities/Player/PlayerStorage.cpp | 28 +- .../game/Entities/Player/PlayerUpdates.cpp | 53 +- .../game/Entities/Transport/Transport.h | 1 + src/server/game/Entities/Unit/StatSystem.cpp | 8 +- src/server/game/Entities/Unit/Unit.cpp | 10 +- src/server/game/Events/GameEventMgr.cpp | 31 +- src/server/game/Events/GameEventMgr.h | 9 +- 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 | 65 +- src/server/game/Grids/Grid.h | 131 -- src/server/game/Grids/GridCell.h | 75 + src/server/game/Grids/GridDefines.h | 43 +- 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 | 157 +++ .../GridTerrainLoader.h} | 45 +- 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/Groups/Group.cpp | 4 +- src/server/game/Guilds/Guild.cpp | 5 +- .../game/Handlers/AuctionHouseHandler.cpp | 2 +- src/server/game/Handlers/AuthHandler.cpp | 7 +- .../game/Handlers/BattleGroundHandler.cpp | 13 +- src/server/game/Handlers/CharacterHandler.cpp | 19 +- src/server/game/Handlers/ChatHandler.cpp | 34 +- 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/PetHandler.cpp | 13 +- src/server/game/Handlers/PetitionsHandler.cpp | 10 +- src/server/game/Handlers/QuestHandler.cpp | 2 +- src/server/game/Handlers/SpellHandler.cpp | 12 +- src/server/game/Handlers/TicketHandler.cpp | 2 +- src/server/game/Handlers/TradeHandler.cpp | 4 +- src/server/game/Instances/InstanceSaveMgr.cpp | 5 +- src/server/game/Instances/InstanceScript.h | 3 +- src/server/game/Loot/LootItemStorage.cpp | 3 +- src/server/game/Loot/LootMgr.cpp | 2 +- src/server/game/Maps/Map.cpp | 1206 +++-------------- src/server/game/Maps/Map.h | 259 +--- src/server/game/Maps/MapInstanced.cpp | 9 +- src/server/game/Maps/MapMgr.cpp | 17 +- src/server/game/Maps/MapMgr.h | 1 + src/server/game/Misc/BanMgr.cpp | 13 +- src/server/game/Misc/GameGraveyard.cpp | 2 +- .../game/Movement/Waypoints/WaypointMgr.cpp | 1 + src/server/game/OutdoorPvP/OutdoorPvP.h | 5 +- .../Scripting/ScriptDefines/AllMapScript.cpp | 7 +- .../ScriptDefines/AllScriptsObjects.h | 1 + .../ScriptDefines/InstanceMapScript.h | 10 + .../Scripting/ScriptDefines/PlayerScript.cpp | 565 ++++---- .../Scripting/ScriptDefines/PlayerScript.h | 319 ++--- .../Scripting/ScriptDefines/TicketScript.cpp | 58 + .../Scripting/ScriptDefines/TicketScript.h | 50 + src/server/game/Scripting/ScriptMgr.cpp | 13 +- src/server/game/Scripting/ScriptMgr.h | 276 ++-- src/server/game/Scripting/ScriptObject.h | 4 +- src/server/game/Scripting/ScriptObjectFwd.h | 3 +- src/server/game/Server/WorldSession.cpp | 104 +- src/server/game/Server/WorldSessionMgr.cpp | 466 +++++++ src/server/game/Server/WorldSessionMgr.h | 112 ++ src/server/game/Server/WorldSocket.cpp | 3 +- src/server/game/Spells/Spell.cpp | 37 +- src/server/game/Spells/SpellEffects.cpp | 6 +- src/server/game/Spells/SpellInfo.cpp | 4 + .../game/Spells/SpellInfoCorrections.cpp | 14 + src/server/game/Texts/CreatureTextMgr.cpp | 4 +- src/server/game/Texts/CreatureTextMgr.h | 5 +- src/server/game/Tickets/TicketMgr.cpp | 11 +- src/server/game/Tickets/TicketMgr.h | 2 +- src/server/game/Weather/Weather.cpp | 3 +- src/server/game/World/IWorld.h | 40 +- src/server/game/World/World.cpp | 519 +------ src/server/game/World/World.h | 68 - src/server/game/World/WorldState.cpp | 26 +- src/server/game/World/WorldState.h | 2 +- src/server/scripts/Commands/cs_arena.cpp | 90 ++ src/server/scripts/Commands/cs_debug.cpp | 17 +- src/server/scripts/Commands/cs_message.cpp | 7 +- src/server/scripts/Commands/cs_misc.cpp | 25 +- src/server/scripts/Commands/cs_mmaps.cpp | 7 +- src/server/scripts/Commands/cs_reset.cpp | 3 +- src/server/scripts/Commands/cs_server.cpp | 9 +- src/server/scripts/Commands/cs_ticket.cpp | 18 +- .../instance_blackrock_spire.cpp | 3 +- .../BlackwingLair/boss_razorgore.cpp | 20 +- .../BlackwingLair/instance_blackwing_lair.cpp | 5 +- .../Karazhan/boss_nightbane.cpp | 1 - .../instance_magisters_terrace.cpp | 3 + .../MagistersTerrace/magisters_terrace.h | 5 + .../Stratholme/instance_stratholme.cpp | 6 - .../SunkenTemple/instance_sunken_temple.cpp | 1 - .../SunwellPlateau/boss_brutallus.cpp | 4 +- .../SunwellPlateau/boss_felmyst.cpp | 20 +- .../SunwellPlateau/boss_kalecgos.cpp | 43 +- .../instance_sunwell_plateau.cpp | 2 - .../EasternKingdoms/ZulAman/boss_janalai.cpp | 2 +- .../EasternKingdoms/ZulGurub/boss_hakkar.cpp | 20 - .../EasternKingdoms/ZulGurub/boss_jindo.cpp | 18 - .../ZulGurub/boss_mandokir.cpp | 2 +- .../Events/firework_show/firework_show.cpp | 1 + src/server/scripts/Events/midsummer.cpp | 2 +- .../instance_culling_of_stratholme.cpp | 27 +- .../instance_old_hillsbrad.cpp | 16 - .../instance_the_black_morass.cpp | 5 +- .../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 | 13 +- .../instance_halls_of_reflection.cpp | 7 +- .../PitOfSaron/instance_pit_of_saron.cpp | 1 - .../boss_blood_prince_council.cpp | 8 +- .../boss_lady_deathwhisper.cpp | 27 +- .../IcecrownCitadel/boss_sindragosa.cpp | 1 - .../IcecrownCitadel/icecrown_citadel.cpp | 2 - .../instance_icecrown_citadel.cpp | 18 +- .../Northrend/Naxxramas/boss_faerlina.cpp | 1 - .../Northrend/Naxxramas/boss_faerlina.h | 166 +-- .../Northrend/Naxxramas/boss_maexxna.h | 7 +- .../Naxxramas/instance_naxxramas.cpp | 54 +- .../scripts/Northrend/Naxxramas/naxxramas.h | 7 +- .../Northrend/Nexus/Oculus/boss_urom.cpp | 8 +- .../Nexus/Oculus/instance_oculus.cpp | 1 + .../Northrend/Ulduar/Ulduar/boss_kologarn.cpp | 2 +- .../Ulduar/Ulduar/instance_ulduar.cpp | 14 +- src/server/scripts/Northrend/zone_zuldrak.cpp | 83 -- .../scripts/OutdoorPvP/OutdoorPvPEP.cpp | 106 +- src/server/scripts/OutdoorPvP/OutdoorPvPEP.h | 14 +- .../scripts/OutdoorPvP/OutdoorPvPGH.cpp | 9 +- src/server/scripts/OutdoorPvP/OutdoorPvPGH.h | 2 +- .../scripts/OutdoorPvP/OutdoorPvPHP.cpp | 53 +- src/server/scripts/OutdoorPvP/OutdoorPvPHP.h | 4 +- .../scripts/OutdoorPvP/OutdoorPvPNA.cpp | 88 +- src/server/scripts/OutdoorPvP/OutdoorPvPNA.h | 4 +- .../scripts/OutdoorPvP/OutdoorPvPSI.cpp | 15 +- src/server/scripts/OutdoorPvP/OutdoorPvPSI.h | 3 +- .../scripts/OutdoorPvP/OutdoorPvPTF.cpp | 50 +- src/server/scripts/OutdoorPvP/OutdoorPvPTF.h | 5 +- .../scripts/OutdoorPvP/OutdoorPvPZM.cpp | 123 +- src/server/scripts/OutdoorPvP/OutdoorPvPZM.h | 18 +- .../Outland/BlackTemple/boss_illidan.cpp | 12 +- .../GruulsLair/instance_gruuls_lair.cpp | 3 +- .../BloodFurnace/boss_kelidan_the_breaker.cpp | 1 - .../instance_magtheridons_lair.cpp | 3 +- .../instance_shattered_halls.cpp | 1 - .../Mechanar/boss_nethermancer_sepethrea.cpp | 18 - .../Outland/TempestKeep/botanica/boss_laj.cpp | 5 +- .../Outland/zone_shadowmoon_valley.cpp | 9 +- src/server/scripts/Pet/pet_priest.cpp | 29 +- src/server/scripts/Spells/spell_priest.cpp | 35 + src/server/scripts/Spells/spell_shaman.cpp | 5 +- src/server/scripts/Spells/spell_warrior.cpp | 7 +- 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 +- src/test/common/Configuration/Config.cpp | 13 +- src/test/mocks/WorldMock.h | 32 - .../ArenaSeasonRewardDistributorTest.cpp | 207 +++ .../ArenaSeason/ArenaTeamFilterTest.cpp | 113 ++ 277 files changed, 7092 insertions(+), 5050 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 create mode 100644 data/sql/updates/db_auth/2025_02_16_00.sql create mode 100644 data/sql/updates/db_auth/2025_02_16_01.sql create mode 100644 data/sql/updates/db_characters/2025_02_12_00.sql create mode 100644 data/sql/updates/db_characters/2025_02_16_00.sql create mode 100644 data/sql/updates/db_world/2025_02_12_00.sql create mode 100644 data/sql/updates/db_world/2025_02_12_01.sql create mode 100644 data/sql/updates/db_world/2025_02_13_00.sql create mode 100644 data/sql/updates/db_world/2025_02_13_01.sql create mode 100644 data/sql/updates/db_world/2025_02_14_00.sql create mode 100644 data/sql/updates/db_world/2025_02_15_00.sql create mode 100644 data/sql/updates/db_world/2025_02_15_01.sql create mode 100644 data/sql/updates/db_world/2025_02_15_02.sql create mode 100644 data/sql/updates/db_world/2025_02_16_00.sql create mode 100644 data/sql/updates/db_world/2025_02_16_01.sql create mode 100644 data/sql/updates/db_world/2025_02_16_02.sql create mode 100644 data/sql/updates/db_world/2025_02_16_03.sql create mode 100644 data/sql/updates/db_world/2025_02_18_00.sql create mode 100644 data/sql/updates/db_world/2025_02_19_00.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 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 rename src/server/game/{Scripting/ScriptDefines/MetricScript.cpp => Grids/GridTerrainLoader.h} (52%) 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 create mode 100644 src/server/game/Scripting/ScriptDefines/TicketScript.cpp create mode 100644 src/server/game/Scripting/ScriptDefines/TicketScript.h create mode 100644 src/server/game/Server/WorldSessionMgr.cpp create mode 100644 src/server/game/Server/WorldSessionMgr.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/.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 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) 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 6857c26f0..ef5332797 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 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 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) 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 diff --git a/data/sql/updates/db_auth/2025_02_16_00.sql b/data/sql/updates/db_auth/2025_02_16_00.sql new file mode 100644 index 000000000..8f68f2670 --- /dev/null +++ b/data/sql/updates/db_auth/2025_02_16_00.sql @@ -0,0 +1,5 @@ +-- DB update 2025_01_26_00 -> 2025_02_16_00 +-- +ALTER TABLE `autobroadcast_locale` +DROP PRIMARY KEY, +ADD PRIMARY KEY (`realmid`, `id`, `locale`); diff --git a/data/sql/updates/db_auth/2025_02_16_01.sql b/data/sql/updates/db_auth/2025_02_16_01.sql new file mode 100644 index 000000000..87911ccba --- /dev/null +++ b/data/sql/updates/db_auth/2025_02_16_01.sql @@ -0,0 +1,11 @@ +-- 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`; + +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/db_characters/2025_02_12_00.sql b/data/sql/updates/db_characters/2025_02_12_00.sql new file mode 100644 index 000000000..142fbc78c --- /dev/null +++ b/data/sql/updates/db_characters/2025_02_12_00.sql @@ -0,0 +1,11 @@ +-- 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, + `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/db_characters/2025_02_16_00.sql b/data/sql/updates/db_characters/2025_02_16_00.sql new file mode 100644 index 000000000..0f4f14721 --- /dev/null +++ b/data/sql/updates/db_characters/2025_02_16_00.sql @@ -0,0 +1,11 @@ +-- 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`; + +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/db_world/2025_02_12_00.sql b/data/sql/updates/db_world/2025_02_12_00.sql new file mode 100644 index 000000000..2903ec2c3 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_12_00.sql @@ -0,0 +1,96 @@ +-- 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, + `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/data/sql/updates/db_world/2025_02_12_01.sql b/data/sql/updates/db_world/2025_02_12_01.sql new file mode 100644 index 000000000..bcb8ae37a --- /dev/null +++ b/data/sql/updates/db_world/2025_02_12_01.sql @@ -0,0 +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); diff --git a/data/sql/updates/db_world/2025_02_13_00.sql b/data/sql/updates/db_world/2025_02_13_00.sql new file mode 100644 index 000000000..93c8c0dd8 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_13_00.sql @@ -0,0 +1,7 @@ +-- 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 +(28796, 28796, 54098, 0, 0), +(28794, 28794, 54099, 0, 0), +(28798, 28798, 54100, 0, 0); diff --git a/data/sql/updates/db_world/2025_02_13_01.sql b/data/sql/updates/db_world/2025_02_13_01.sql new file mode 100644 index 000000000..fd4398508 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_13_01.sql @@ -0,0 +1,25 @@ +-- 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 +(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/data/sql/updates/db_world/2025_02_14_00.sql b/data/sql/updates/db_world/2025_02_14_00.sql new file mode 100644 index 000000000..ce6e14524 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_14_00.sql @@ -0,0 +1,23 @@ +-- 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)) +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)); diff --git a/data/sql/updates/db_world/2025_02_15_00.sql b/data/sql/updates/db_world/2025_02_15_00.sql new file mode 100644 index 000000000..5196f5299 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_15_00.sql @@ -0,0 +1,239 @@ +-- 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); + +-- 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)'); diff --git a/data/sql/updates/db_world/2025_02_15_01.sql b/data/sql/updates/db_world/2025_02_15_01.sql new file mode 100644 index 000000000..7a0da52ec --- /dev/null +++ b/data/sql/updates/db_world/2025_02_15_01.sql @@ -0,0 +1,10 @@ +-- DB update 2025_02_15_00 -> 2025_02_15_01 + +-- 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)'); diff --git a/data/sql/updates/db_world/2025_02_15_02.sql b/data/sql/updates/db_world/2025_02_15_02.sql new file mode 100644 index 000000000..030fd5373 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_15_02.sql @@ -0,0 +1,17 @@ +-- 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); +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/data/sql/updates/db_world/2025_02_16_00.sql b/data/sql/updates/db_world/2025_02_16_00.sql new file mode 100644 index 000000000..024d56356 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_16_00.sql @@ -0,0 +1,77 @@ +-- DB update 2025_02_15_02 -> 2025_02_16_00 + +-- 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\''); diff --git a/data/sql/updates/db_world/2025_02_16_01.sql b/data/sql/updates/db_world/2025_02_16_01.sql new file mode 100644 index 000000000..75a41744f --- /dev/null +++ b/data/sql/updates/db_world/2025_02_16_01.sql @@ -0,0 +1,11 @@ +-- 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`; + +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/data/sql/updates/db_world/2025_02_16_02.sql b/data/sql/updates/db_world/2025_02_16_02.sql new file mode 100644 index 000000000..28f34728d --- /dev/null +++ b/data/sql/updates/db_world/2025_02_16_02.sql @@ -0,0 +1,2 @@ +-- DB update 2025_02_16_01 -> 2025_02_16_02 +UPDATE `quest_template` SET `AllowableRaces` = 0 WHERE (`ID` = 11880); diff --git a/data/sql/updates/db_world/2025_02_16_03.sql b/data/sql/updates/db_world/2025_02_16_03.sql new file mode 100644 index 000000000..1de131016 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_16_03.sql @@ -0,0 +1,14 @@ +-- 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); +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/data/sql/updates/db_world/2025_02_18_00.sql b/data/sql/updates/db_world/2025_02_18_00.sql new file mode 100644 index 000000000..2b96544f9 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_18_00.sql @@ -0,0 +1,21 @@ +-- DB update 2025_02_16_03 -> 2025_02_18_00 + +-- 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'); diff --git a/data/sql/updates/db_world/2025_02_19_00.sql b/data/sql/updates/db_world/2025_02_19_00.sql new file mode 100644 index 000000000..c8e7a5cb7 --- /dev/null +++ b/data/sql/updates/db_world/2025_02_19_00.sql @@ -0,0 +1,7 @@ +-- 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'; +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/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/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/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/server/apps/worldserver/Main.cpp b/src/server/apps/worldserver/Main.cpp index 1a3842d07..d259f0220 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,11 +286,10 @@ 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())); - sScriptMgr->OnMetricLogging(); }); METRIC_EVENT("events", "Worldserver started", ""); @@ -358,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/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index e55caf9a5..98cbc3970 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 # ################################################################################################### @@ -290,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) @@ -3791,21 +3792,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. @@ -4484,6 +4470,52 @@ Debug.Arena = 0 # ################################################################################################### +################################################################################################### +# DYNAMIC RESPAWN SETTINGS +# +# +# Respawn.DynamicRateCreature +# 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 + +# +# Respawn.DynamicMinimumCreature +# Description: The minimum respawn time for a creature under dynamic scaling. +# Default: 10 - (10 seconds) + +Respawn.DynamicMinimumCreature = 10 + +# +# Respawn.DynamicRateGameObject +# 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. +# Formula: adjustFactor = rate / playerCount +# RespawnTime = RespawnTime * adjustFactor +# 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/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") { diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index 07876f386..24ef9c6dd 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: 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/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 13d989385..e679c271e 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) { @@ -580,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); } } @@ -609,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); } } } @@ -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,20 +742,15 @@ 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 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); @@ -2103,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; } @@ -2169,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) @@ -2277,7 +2273,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) return; } - if (!sScriptMgr->OnBeforeAchievementComplete(GetPlayer(), achievement)) + if (!sScriptMgr->OnPlayerBeforeAchievementComplete(GetPlayer(), achievement)) { return; } @@ -2292,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/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/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 b0ecc3ab5..2fd0f863d 100644 --- a/src/server/game/Battlegrounds/Arena.cpp +++ b/src/server/game/Battlegrounds/Arena.cpp @@ -25,7 +25,8 @@ #include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" -//#include "WorldStatePackets.h" +#include "WorldSessionMgr.h" +#include "WorldStatePackets.h" void ArenaScore::AppendToPacket(WorldPacket& data) { @@ -146,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() @@ -224,7 +226,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/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/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 f0532ee5b..3be5f3a8d 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/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 54dc97afd..04da6d40f 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; @@ -458,7 +459,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/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/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/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 6933f0944..67880529a 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h @@ -316,7 +316,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 0dddb21b7..74dc4ae76 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h @@ -1940,7 +1940,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 41ac26f1c..647a55244 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}; @@ -421,7 +421,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 e8ec81bf0..f7af4ff60 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/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 505249350..d6abeaeb1 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 @@ -81,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) @@ -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); } } @@ -514,8 +515,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/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/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; }; 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/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index bc83a2361..d22cf66eb 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 @@ -1975,7 +1976,8 @@ void Creature::setDeathState(DeathState state, bool despawn) if (state == DeathState::JustDied) { m_corpseRemoveTime = GameTime::GetGameTime().count() + m_corpseDelay; - 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) @@ -2818,7 +2820,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)); } /** @@ -3180,7 +3182,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 @@ -3188,7 +3191,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 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/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 91778e42c..298edcde8 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -897,7 +897,8 @@ void GameObject::Update(uint32 diff) return; } - 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()) @@ -1758,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/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/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/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 58d7be70e..5302a9878 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) @@ -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; @@ -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; @@ -1031,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()) { @@ -1425,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; } @@ -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/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 1a0dbd402..1a9c3246b 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" @@ -83,7 +84,9 @@ #include "World.h" #include "WorldPacket.h" #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 @@ -362,7 +365,7 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this) m_ControlledByPlayer = true; - sWorld->IncreasePlayerCount(); + sWorldSessionMgr->IncreasePlayerCount(); m_ChampioningFaction = 0; @@ -446,7 +449,7 @@ Player::~Player() delete m_reputationMgr; delete _cinematicMgr; - sWorld->DecreasePlayerCount(); + sWorldSessionMgr->DecreasePlayerCount(); if (!m_isInSharedVisionOf.empty()) { @@ -1428,7 +1431,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) @@ -2245,7 +2248,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(); @@ -2282,7 +2285,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 @@ -2546,7 +2549,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(); @@ -2604,7 +2607,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())); @@ -2736,7 +2739,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 +4305,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 +4496,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 +4949,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 @@ -5508,7 +5511,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; @@ -5525,7 +5528,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; } @@ -5804,7 +5807,7 @@ void Player::CheckAreaExploreAndOutdoor() } } - if (!sScriptMgr->CanAreaExploreAndOutdoor(this)) + if (!sScriptMgr->OnPlayerCanAreaExploreAndOutdoor(this)) return; if (!areaId) @@ -5863,7 +5866,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); } @@ -6174,7 +6177,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] @@ -6201,7 +6204,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 { @@ -6253,7 +6256,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); } } @@ -6647,7 +6650,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; @@ -6679,7 +6682,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 @@ -6690,7 +6693,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) @@ -6881,7 +6884,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) @@ -6923,7 +6926,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); } @@ -6933,7 +6936,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; @@ -6979,7 +6982,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) { @@ -7061,7 +7064,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; @@ -7195,7 +7198,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 @@ -7291,7 +7294,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 @@ -7423,7 +7426,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(); @@ -7688,7 +7691,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; @@ -8230,643 +8233,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(sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)); + packet.Worldstates.emplace_back(0xc77, sArenaSeasonMgr->GetSeasonState() == ARENA_SEASON_STATE_IN_PROGRESS); // 8 Arena season id - data << uint32(0xF3D) << uint32(sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID)); + 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(); } @@ -9386,7 +9413,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; } @@ -9407,7 +9434,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; } @@ -9428,7 +9455,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; } @@ -9457,7 +9484,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; } @@ -10721,7 +10748,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) @@ -10750,7 +10777,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; } @@ -10758,7 +10785,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) @@ -10950,7 +10977,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; } @@ -11384,11 +11411,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(); @@ -11548,7 +11575,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 @@ -11677,7 +11704,7 @@ void Player::SendInitialPacketsBeforeAddToMap() SetMover(this); - sScriptMgr->OnSendInitialPacketsBeforeAddToMap(this, data); + sScriptMgr->OnPlayerSendInitialPacketsBeforeAddToMap(this, data); } void Player::SendInitialPacketsAfterAddToMap() @@ -13569,7 +13596,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); } @@ -13651,7 +13678,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 { @@ -13682,13 +13709,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; } @@ -15309,7 +15336,7 @@ void Player::ActivateSpec(uint8 spec) ++iter; } - sScriptMgr->OnAfterSpecSlotChanged(this, GetActiveSpec()); + sScriptMgr->OnPlayerAfterSpecSlotChanged(this, GetActiveSpec()); } void Player::LoadActions(PreparedQueryResult result) @@ -15406,7 +15433,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); @@ -15431,7 +15458,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); } } @@ -16236,7 +16263,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); } @@ -16244,7 +16271,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; } @@ -16253,7 +16280,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; } @@ -16262,7 +16289,7 @@ bool Player::IsFFAPvP() { bool result = Unit::IsFFAPvP(); - sScriptMgr->OnIsFFAPvP(this, result); + sScriptMgr->OnPlayerIsFFAPvP(this, result); return result; } @@ -16271,7 +16298,7 @@ bool Player::IsPvP() { bool result = Unit::IsPvP(); - sScriptMgr->OnIsPvP(this, result); + sScriptMgr->OnPlayerIsPvP(this, result); return result; } @@ -16280,7 +16307,7 @@ uint16 Player::GetMaxSkillValueForLevel() const { uint16 result = Unit::GetMaxSkillValueForLevel(); - sScriptMgr->OnGetMaxSkillValueForLevel(const_cast(this), result); + sScriptMgr->OnPlayerGetMaxSkillValueForLevel(const_cast(this), result); return result; } @@ -16289,21 +16316,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/Player.h b/src/server/game/Entities/Player/Player.h index 35aece6e6..d4ba1aff5 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 @@ -2227,7 +2227,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/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 862113798..3ef88ebef 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()) @@ -424,7 +424,7 @@ void Player::Update(uint32 p_time) m_delayed_unit_relocation_timer = 0; RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED); } - sScriptMgr->OnAfterPlayerUpdate(this, p_time); + sScriptMgr->OnPlayerAfterUpdate(this, p_time); } void Player::UpdateMirrorTimers() @@ -551,17 +551,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); @@ -710,7 +709,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->OnPlayerCanUpdateSkill(this, skill_id)) return false; SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); @@ -722,6 +721,8 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) uint32 value = SKILL_VALUE(data); uint32 max = SKILL_MAX(data); + sScriptMgr->OnPlayerBeforeUpdateSkill(this, skill_id, value, max, step); + if ((!max) || (!value) || (value >= max)) return false; @@ -738,6 +739,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; } @@ -766,7 +769,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 @@ -844,7 +847,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, @@ -913,7 +916,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->OnPlayerCanUpdateSkill(this, SkillId)) return false; if (Chance <= 0) // speedup in 0 chance case @@ -931,8 +934,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->OnPlayerBeforeUpdateSkill(this, SkillId, SkillValue, MaxValue, step); if (!MaxValue || !SkillValue || SkillValue >= MaxValue) return false; @@ -964,6 +969,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; } @@ -1246,9 +1253,7 @@ void Player::UpdateArea(uint32 newArea) void Player::UpdateZone(uint32 newZone, uint32 newArea) { if (!newZone) - { return; - } if (m_zoneUpdateId != newZone) { @@ -1265,6 +1270,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); @@ -1377,7 +1384,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 @@ -1455,7 +1462,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) @@ -1477,7 +1484,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) @@ -2379,7 +2386,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; 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/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 c2501d1e5..a394f0f10 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 @@ -17897,7 +17897,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) @@ -18099,9 +18099,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()) { @@ -20566,6 +20566,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/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index ce529ff24..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 @@ -1163,34 +1164,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(); @@ -1714,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/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/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 7ecbeb49d..3d2b4cb63 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1151,12 +1151,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..ede2817b2 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) @@ -51,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); } @@ -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,16 @@ 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) { CellCoord cellCoord(x, y); - //lets skip standing cell since we already visited it - if (cellCoord != standing_cell) - { - Cell r_zone(cellCoord); - r_zone.data.Part.nocreate = this->data.Part.nocreate; - map.Visit(r_zone, visitor); - } + Cell r_zone(cellCoord); + map.Visit(r_zone, visitor); } } } @@ -138,7 +128,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 +151,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 +194,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..7eabee5cd 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; @@ -171,37 +170,29 @@ 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) + { + 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); - } - - 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/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..ecf9b0941 --- /dev/null +++ b/src/server/game/Grids/GridTerrainLoader.cpp @@ -0,0 +1,157 @@ +#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(), _grid.GetX(), _grid.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(), _grid.GetX(), _grid.GetY()); +} + +void GridTerrainLoader::LoadVMap() +{ + 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(), _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(), _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(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.GetY()); + break; + } +} + +void GridTerrainLoader::LoadMMap() +{ + if (!DisableMgr::IsPathfindingEnabled(_map)) + return; + + 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(), _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(), _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(), _grid.GetX(), _grid.GetY(), _grid.GetX(), _grid.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; + + 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/Scripting/ScriptDefines/MetricScript.cpp b/src/server/game/Grids/GridTerrainLoader.h similarity index 52% rename from src/server/game/Scripting/ScriptDefines/MetricScript.cpp rename to src/server/game/Grids/GridTerrainLoader.h index a9de340a0..39cbc0d62 100644 --- a/src/server/game/Scripting/ScriptDefines/MetricScript.cpp +++ b/src/server/game/Grids/GridTerrainLoader.h @@ -15,13 +15,42 @@ * with this program. If not, see . */ -#include "ScriptMgr.h" -#include "ScriptMgrMacros.h" +#ifndef ACORE_GRID_TERRAIN_LOADER_H +#define ACORE_GRID_TERRAIN_LOADER_H -void ScriptMgr::OnMetricLogging() +#include "GridDefines.h" + +class GridTerrainLoader { - ExecuteScript([&](MetricScript* script) - { - script->OnMetricLogging(); - }); -} +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(); + + 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/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/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index d9f0cd968..ba3376bb9 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1585,11 +1585,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()); } } } 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/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) { diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index c2aafae81..d8ae919de 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" @@ -139,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); @@ -423,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 @@ -578,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); } } @@ -747,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); @@ -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/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 7ca43cd4b..0956ad682 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" LoginQueryHolder::LoginQueryHolder(uint32 accountId, ObjectGuid guid) : m_accountId(accountId), m_guid(guid) { @@ -607,7 +608,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; @@ -693,14 +694,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()) @@ -956,7 +957,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); } @@ -1096,7 +1097,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; @@ -1118,7 +1119,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()); @@ -1385,7 +1386,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; @@ -1621,7 +1622,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); @@ -1923,7 +1924,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/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index 7c97d16af..c37e4ea3c 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -352,7 +352,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) ++_addonMessageReceiveCount; } - sScriptMgr->OnBeforeSendChatMessage(_player, type, lang, msg); + sScriptMgr->OnPlayerBeforeSendChatMessage(_player, type, lang, msg); switch (type) { @@ -420,7 +420,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) if (!senderIsPlayer && !sender->isAcceptWhispers() && !sender->IsInWhisperWhiteList(receiver->GetGUID())) sender->AddWhisperWhiteList(receiver->GetGUID()); - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, receiver)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, receiver)) { return; } @@ -445,7 +445,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; } @@ -463,7 +463,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; } @@ -485,7 +485,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; } @@ -508,7 +508,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) return; } - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, group)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) { return; } @@ -531,7 +531,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) return; } - if (!sScriptMgr->CanPlayerUseChat(GetPlayer(), type, lang, msg, group)) + if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) { return; } @@ -549,7 +549,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; } @@ -569,7 +569,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; } @@ -588,7 +588,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; } @@ -615,7 +615,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; } @@ -648,7 +648,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sender->ToggleAFK(); } - if (!sScriptMgr->CanPlayerUseChat(sender, type, lang, msg)) + if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg)) { return; } @@ -676,7 +676,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sender->ToggleDND(); } - if (!sScriptMgr->CanPlayerUseChat(sender, type, lang, msg)) + if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg)) { return; } @@ -793,16 +793,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/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/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 16d7a5458..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)) { @@ -441,7 +447,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) diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index 41d553ed0..571390966 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) { @@ -842,7 +842,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 @@ -861,7 +861,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 @@ -875,7 +875,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 @@ -889,7 +889,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 7f11d413f..01a81b097 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; @@ -267,7 +268,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) } } - if (sScriptMgr->OnBeforeOpenItem(pUser, item)) + if (sScriptMgr->OnPlayerBeforeOpenItem(pUser, item)) { if (item->IsWrapped())// wrapped? { @@ -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; } 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/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/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/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/Loot/LootItemStorage.cpp b/src/server/game/Loot/LootItemStorage.cpp index d453e08cd..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() { @@ -249,7 +250,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); } 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/Map.cpp b/src/server/game/Maps/Map.cpp index 90e70694c..c54bcab8d 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,20 +44,7 @@ #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), WeatherGrade(0.0f), OverrideLightId(0), LightFadeInTime(0) { } @@ -81,179 +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); } @@ -278,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); } @@ -300,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); } @@ -309,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); } @@ -321,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); } } @@ -359,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); } @@ -397,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); } } @@ -432,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()); @@ -515,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 @@ -656,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, @@ -721,7 +552,6 @@ void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitorUpdateZone(MAP_INVALID_ZONE, 0); player->getHostileRefMgr().deleteReferences(true); // pussywizard: multithreading crashfix bool inWorld = player->IsInWorld(); @@ -1211,50 +1060,12 @@ void Map::MoveAllDynamicObjectsInMoveList() _dynamicObjectsToMove.clear(); } -bool Map::UnloadGrid(NGridType& ngrid) +bool Map::UnloadGrid(MapGridType& grid) { - // pussywizard: UnloadGrid only done when whole map is unloaded, no need to worry about moving npcs between grids, etc. - - const uint32 x = ngrid.getX(); - const uint32 y = ngrid.getY(); - - { - ObjectGridCleaner worker; - 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; } @@ -1281,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 } @@ -1318,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; @@ -2079,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) @@ -2133,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... @@ -2156,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); @@ -2267,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: @@ -2289,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; @@ -2432,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 @@ -2602,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; @@ -2641,6 +1791,42 @@ void Map::SendObjectUpdates() } } +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 respawnDelay; + + // No instanced maps (dungeons, battlegrounds, arenas etc.) + if (obj->GetMap()->Instanceable()) + return respawnDelay; + + // No quest givers or world bosses + if (Creature const* creature = obj->ToCreature()) + 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 respawnDelay; + uint32 const playerCount = it->second; + if (!playerCount) + return respawnDelay; + double const adjustFactor = rate / playerCount; + if (adjustFactor >= 1.0) // nothing to do here + return respawnDelay; + uint32 const timeMinimum = sWorld->getIntConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE); + if (respawnDelay <= timeMinimum) + return respawnDelay; + + return std::max(std::ceil(respawnDelay * adjustFactor), timeMinimum); +} + void Map::DelayedUpdate(const uint32 t_diff) { for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();) @@ -3664,7 +2850,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(); @@ -4086,6 +3272,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 e6e10c26d..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; } @@ -594,6 +443,9 @@ public: void DeleteRespawnTimes(); [[nodiscard]] time_t GetInstanceResetPeriod() const { return _instanceResetPeriod; } + void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone); + [[nodiscard]] uint32 ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32 respawnDelay) const; + TaskScheduler _creatureRespawnScheduler; void ScheduleCreatureRespawn(ObjectGuid /*creatureGuid*/, Milliseconds /*respawnTimer*/, Position pos = Position()); @@ -624,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; } @@ -656,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); @@ -676,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; @@ -736,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; @@ -749,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*); @@ -780,6 +613,8 @@ private: std::unordered_map _creatureRespawnTimes; std::unordered_map _goRespawnTimes; + std::unordered_map _zonePlayerCountMap; + ZoneDynamicInfoMap _zoneDynamicInfo; uint32 _defaultLight; @@ -870,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..34f371a67 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(); } } @@ -156,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(); @@ -299,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 Map::ExistMap(mapid, gx, gy) && Map::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/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/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/Misc/GameGraveyard.cpp b/src/server/game/Misc/GameGraveyard.cpp index 5cfe564ab..3fe1d72d3 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/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/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/Scripting/ScriptDefines/AllMapScript.cpp b/src/server/game/Scripting/ScriptDefines/AllMapScript.cpp index a43907365..a02ae745c 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); @@ -191,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/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/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 diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 4855b25bc..422a397df 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,265 +96,265 @@ 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::OnAfterPlayerUpdate(Player* player, uint32 diff) +void ScriptMgr::OnPlayerAfterUpdate(Player* player, uint32 diff) { ExecuteScript([&](PlayerScript* script) { - script->OnAfterUpdate(player, diff); + script->OnPlayerAfterUpdate(player, diff); }); } 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) @@ -367,214 +367,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) @@ -592,9 +592,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) @@ -602,214 +602,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) @@ -817,34 +817,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) @@ -862,9 +862,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 @@ -903,9 +903,24 @@ bool ScriptMgr::AnticheatCheckMovementInfo(Player* player, MovementInfo const& m CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ANTICHEAT_CHECK_MOVEMENT_INFO, !script->AnticheatCheckMovementInfo(player, movementInfo, mover, jump)); } -bool ScriptMgr::CanPlayerResurrect(Player* player) +bool ScriptMgr::OnPlayerCanUpdateSkill(Player* player, uint32 skillId) { - CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_CAN_RESURRECT, !script->CanPlayerResurrect(player)); + CALL_ENABLED_BOOLEAN_HOOKS(PlayerScript, PLAYERHOOK_ON_CAN_UPDATE_SKILL, !script->OnPlayerCanUpdateSkill(player, skillId)); +} + +void ScriptMgr::OnPlayerBeforeUpdateSkill(Player* player, uint32 skillId, uint32& value, uint32 max, uint32 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) +{ + CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_UPDATE_SKILL, script->OnPlayerUpdateSkill(player, skillId, value, max, step, newValue)); +} + +bool ScriptMgr::OnPlayerCanResurrect(Player* 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 59c3c4b56..c640e5e6e 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 }; @@ -218,189 +221,189 @@ 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 OnAfterUpdate(Player* /*player*/, uint32 /*diff*/) {} + virtual void OnPlayerBeforeUpdate(Player* /*player*/, uint32 /*p_time*/) { } + virtual void OnPlayerAfterUpdate(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*/) { } @@ -409,105 +412,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; } @@ -522,7 +525,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. @@ -532,82 +535,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 @@ -617,16 +620,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 @@ -638,7 +641,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 @@ -651,7 +654,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 @@ -664,7 +667,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 @@ -677,7 +680,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 @@ -690,7 +693,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 @@ -723,7 +726,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 @@ -733,7 +736,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*/) { } @@ -751,7 +754,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. @@ -759,14 +762,18 @@ 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 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*/) { } /** * @brief This hook is called, to avoid player resurrect @@ -775,7 +782,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/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 ab032fc73..b3e97be1c 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -58,12 +58,6 @@ ScriptMgr* ScriptMgr::instance() return &instance; } -// Yunfan: refactor -MetricScript::MetricScript(const char* name) : ScriptObject(name) -{ - ScriptRegistry::AddScript(this); -} - PlayerbotScript::PlayerbotScript(const char* name) : ScriptObject(name) { ScriptRegistry::AddScript(this); @@ -109,6 +103,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); @@ -148,7 +143,6 @@ void ScriptMgr::Unload() SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); - SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); @@ -158,6 +152,7 @@ void ScriptMgr::Unload() SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); + SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); SCR_CLEAR(); @@ -238,8 +233,8 @@ void ScriptMgr::CheckIfScriptsInDatabaseExist() !ScriptRegistry::GetScriptById(sid) && !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 ade190eb0..4dd0004bf 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -105,18 +105,6 @@ namespace Acore::ChatCommands */ -// Yunfan: refactor -class MetricScript : public ScriptObject -{ -protected: - MetricScript(const char* name); - -public: - bool IsDatabaseBound() const { return false; } - - virtual void OnMetricLogging() { } -}; - class PlayerbotScript : public ScriptObject { protected: @@ -221,8 +209,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); @@ -325,25 +313,25 @@ 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 OnAfterPlayerUpdate(Player* player, uint32 diff); - 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 OnPlayerAfterUpdate(Player* player, uint32 diff); + 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); @@ -352,7 +340,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); @@ -362,7 +350,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); @@ -371,128 +359,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 CanPlayerResurrect(Player* player); + 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 OnPlayerCanResurrect(Player* player); // Anti cheat void AnticheatSetCanFlybyServer(Player* player, bool apply); @@ -740,11 +731,9 @@ public: /* LootScript */ void OnLootMoney(Player* player, uint32 gold); -public: /* MetricScript */ - - void OnMetricLogging(); - +#ifdef MOD_PLAYERBOTS public: /* PlayerbotScript */ + bool OnPlayerbotCheckLFGQueue(lfg::Lfg5Guids const& guidsList); void OnPlayerbotCheckKillTask(Player* player, Unit* victim); void OnPlayerbotCheckPetitionAccount(Player* player, bool& found); @@ -754,6 +743,15 @@ public: /* PlayerbotScript */ void OnPlayerbotUpdateSessions(Player* player); void OnPlayerbotLogout(Player* player); void OnPlayerbotLogoutBots(); +#endif + +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/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..03494cbb8 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; @@ -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/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index c6032243f..fd7c86713 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -615,7 +615,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); @@ -670,11 +670,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); @@ -691,9 +691,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 @@ -704,7 +705,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(); @@ -1174,57 +1175,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!"); diff --git a/src/server/game/Server/WorldSessionMgr.cpp b/src/server/game/Server/WorldSessionMgr.cpp new file mode 100644 index 000000000..210269479 --- /dev/null +++ b/src/server/game/Server/WorldSessionMgr.cpp @@ -0,0 +1,466 @@ +/* + * 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 "ScriptMgr.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"); + +#ifdef MOD_PLAYERBOTS + sScriptMgr->OnPlayerbotLogoutBots(); +#endif +} + +/// 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/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 0559b5583..e20def2cb 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) @@ -2260,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; @@ -7465,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) @@ -7535,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()->RequiredLevel < 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()->RequiredLevel > 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/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index e34918ac1..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) @@ -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) 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) { diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index c59c4fdf8..dc2ecf080 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4870,6 +4870,20 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].RealPointsPerLevel = 0; }); + // Mangle (Nalorakk) + ApplySpellFix({ 42389 }, [](SpellInfo* spellInfo) + { + 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]; 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/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/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 5bace8fe0..f8359ce7a 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -49,8 +49,6 @@ private: CliCommandHolder& operator=(CliCommandHolder const& right) = delete; }; -typedef std::unordered_map SessionMap; - // ServerMessages.dbc enum ServerMessageType { @@ -117,7 +115,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, @@ -203,6 +200,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 }; @@ -326,7 +325,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, @@ -423,6 +421,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 }; @@ -530,34 +530,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; @@ -570,18 +547,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; @@ -595,8 +566,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; @@ -616,7 +585,6 @@ public: virtual void SetRealmName(std::string name) = 0; virtual void RemoveOldCorpses() = 0; virtual SQLQueryHolderCallback& AddQueryHolderCallback(SQLQueryHolderCallback&& callback) = 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 c3ed6acd6..b25d733b5 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" @@ -92,6 +93,7 @@ #include "WhoListCacheMgr.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include "WorldState.h" #include #include @@ -109,15 +111,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 +135,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 +149,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 +162,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) { @@ -416,11 +172,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); @@ -431,9 +187,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); @@ -1179,12 +933,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); @@ -1297,6 +1049,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) != '\\')) @@ -2124,9 +1883,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(); @@ -2210,7 +1970,7 @@ void World::SetInitialWorldSettings() if (map) { LOG_INFO("server.loading", ">> Loading All Grids For Map {}", map->GetId()); - map->LoadAllCells(); + map->LoadAllGrids(); } } } @@ -2287,9 +2047,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) @@ -2372,8 +2132,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()) @@ -2459,7 +2221,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); @@ -2532,41 +2294,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 @@ -2612,63 +2339,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"); -#ifdef MOD_PLAYERBOTS - sScriptMgr->OnPlayerbotLogoutBots(); -#endif -} - -/// 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 +2354,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 @@ -2716,7 +2386,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 @@ -2768,7 +2438,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); } } @@ -2785,100 +2455,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() { @@ -2996,7 +2579,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(); @@ -3023,7 +2607,7 @@ void World::SetPlayerSecurityLimit(AccountTypes _sec) bool update = sec > _allowedSecurityLevel; _allowedSecurityLevel = sec; if (update) - KickAllLess(_allowedSecurityLevel); + sWorldSessionMgr->KickAllLess(_allowedSecurityLevel); } void World::ResetWeeklyQuests() @@ -3031,7 +2615,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(); @@ -3049,7 +2634,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(); @@ -3063,7 +2649,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); } @@ -3075,7 +2662,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); @@ -3102,12 +2690,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"); @@ -3127,8 +2709,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()); @@ -3203,23 +2785,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 3593ee1bf..31fea1a1a 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; } @@ -345,8 +296,6 @@ public: void RemoveOldCorpses() override; - void DoForAllOnlinePlayers(std::function exec) override; - protected: void _UpdateGameTime(); // callback for UpdateRealmCharacters @@ -381,15 +330,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]; @@ -398,7 +338,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 @@ -424,13 +363,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; #ifdef MOD_PLAYERBOTS diff --git a/src/server/game/World/WorldState.cpp b/src/server/game/World/WorldState.cpp index 2d7d56b55..dcec3b958 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: @@ -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/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/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_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 3e6a56e50..3dccc82c4 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" @@ -45,6 +46,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 @@ -565,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); @@ -582,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 = Map::ExistMap(object->GetMapId(), gridX, gridY) ? 1 : 0; - uint32 haveVMap = Map::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) @@ -2403,10 +2400,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()); @@ -2451,7 +2444,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 +2550,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 +2939,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_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()); 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 94f46f7d3..872e639ef 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 @@ -267,10 +268,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/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"); 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/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/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/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/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/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/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); 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, [&] { 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/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_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/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/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/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/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/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp index 9c3779987..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 @@ -67,8 +69,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 +224,6 @@ public: { if (!arthas->IsAlive()) { - EnsureGridLoaded(); arthas->setDeathState(DeathState::Dead); arthas->Respawn(); } @@ -352,16 +351,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..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 @@ -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(); @@ -206,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/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..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 = { @@ -63,7 +64,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); } @@ -218,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 7669ed17a..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 { @@ -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_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/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 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..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 @@ -651,7 +649,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 +1187,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/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index 0b35acde0..612bcaae5 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -21,7 +21,6 @@ #include "SpellInfo.h" #include "naxxramas.h" - using namespace Faerlina; void AddSC_boss_faerlina() diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.h b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.h index bcd9e2b36..b9acd4f5f 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.h +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.h @@ -21,21 +21,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 @@ -56,16 +51,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() { @@ -80,24 +66,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 @@ -106,25 +81,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); } @@ -135,83 +123,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 @@ -219,18 +141,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; }; }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.h b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.h index a275eedbd..fae1da4be 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.h +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.h @@ -121,12 +121,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 diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index f9b1357e1..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 @@ -821,8 +822,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) { @@ -945,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); @@ -1061,8 +1061,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); @@ -1075,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 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 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/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()) { diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index a987a7c82..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,16 +170,16 @@ 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 { // mimiron tram: - instance->LoadGrid(2307.0f, 284.632f); if (GameObject* MimironTram = instance->GetGameObject(m_mimironTramGUID)) { player->UpdateVisibilityOf(MimironTram); @@ -537,10 +538,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 +750,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/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(); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp index 474f7306a..e2c7d86e5 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp @@ -27,6 +27,8 @@ #include "Player.h" #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) @@ -40,12 +42,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 +60,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; @@ -107,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() @@ -172,12 +175,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 +193,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; @@ -249,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() @@ -314,12 +318,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 +336,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; @@ -381,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() @@ -422,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; } } @@ -441,12 +446,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 +464,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; @@ -518,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() @@ -711,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 efb85af37..9e32988d3 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}; @@ -153,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); } } @@ -180,13 +184,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 +227,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 +238,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: @@ -273,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 23036977c..05930308a 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp @@ -28,6 +28,8 @@ #include "ScriptedCreature.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" +#include "WorldStatePackets.h" OutdoorPvPNA::OutdoorPvPNA() { @@ -88,7 +90,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)) @@ -193,9 +195,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 +219,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 +231,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); @@ -299,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) @@ -641,7 +635,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/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 357f810ea..2e01c38e8 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp @@ -28,6 +28,8 @@ #include "Transport.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" +#include "WorldStatePackets.h" OutdoorPvPSI::OutdoorPvPSI() { @@ -37,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) @@ -102,7 +105,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 +131,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/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 075ef17d8..cf0e239a8 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp @@ -26,6 +26,8 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" +#include "WorldStatePackets.h" OutdoorPvPTF::OutdoorPvPTF() { @@ -50,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); } } @@ -397,14 +399,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 +421,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 +436,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/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 3ecf6d9e7..0e9c36759 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp @@ -25,6 +25,8 @@ #include "Player.h" #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) @@ -32,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() @@ -78,14 +81,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 +99,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 +108,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: @@ -136,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; } @@ -149,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); @@ -173,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; } @@ -191,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; } @@ -208,54 +211,54 @@ 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) - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_H)); - m_GraveYardState = ZM_GRAVEYARD_A; + if (m_GraveyardState == ZM_GRAVEYARD_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); sGraveyard->RemoveGraveyardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, TEAM_HORDE); // rem gy 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) + 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)); - m_GraveYardState = ZM_GRAVEYARD_H; + if (m_GraveyardState == ZM_GRAVEYARD_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); sGraveyard->RemoveGraveyardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, TEAM_ALLIANCE); // rem gy 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(); } 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); @@ -264,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)); @@ -276,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) @@ -299,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) @@ -333,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()) @@ -374,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) { @@ -388,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 @@ -413,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; 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; } }; 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/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/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 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); 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(); 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); 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; + } } /*##### 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); } 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 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 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(); 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 { 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 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 +}