aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md67
-rw-r--r--cmake/compiler/clang/settings.cmake1
-rw-r--r--cmake/macros/CheckPlatform.cmake2
-rw-r--r--cmake/platform/settings.cmake5
-rw-r--r--sql/base/characters_database.sql60
-rw-r--r--sql/updates/characters/2015_05_22_00_characters.sql35
-rw-r--r--sql/updates/world/2015_05_19_00_world.sql4
-rw-r--r--sql/updates/world/2015_05_19_01_world_2015_04_24_00.sql42
-rw-r--r--sql/updates/world/2015_05_19_02_world_2015_04_18_00.sql1
-rw-r--r--sql/updates/world/2015_05_19_03_world_2015_04_18_01.sql6
-rw-r--r--sql/updates/world/2015_05_19_03_world_2015_04_18_02.sql13
-rw-r--r--sql/updates/world/2015_05_19_04_world_2015_04_18_03.sql4
-rw-r--r--sql/updates/world/2015_05_19_04_world_2015_04_18_05.sql9
-rw-r--r--sql/updates/world/2015_05_20_00_world_2015_05_19_01.sql22
-rw-r--r--sql/updates/world/2015_05_20_01_world_2015_05_19_02.sql3
-rw-r--r--sql/updates/world/2015_05_21_00_world_2015_04_18_06.sql5
-rw-r--r--sql/updates/world/2015_05_22_00_world.sql91
-rw-r--r--sql/updates/world/2015_05_27_00_world.sql51
-rw-r--r--sql/updates/world/2015_05_29_00_world.sql1
-rw-r--r--sql/updates/world/2015_06_01_00_world_2015_05_26_05.sql3
-rw-r--r--src/server/bnetserver/Main.cpp6
-rw-r--r--src/server/collision/Management/MMapManager.cpp12
-rw-r--r--src/server/collision/Maps/TileAssembler.cpp1
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h2
-rw-r--r--src/server/game/Accounts/RBAC.h6
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp142
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp4
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.h2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundBFG.h2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundTP.h2
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp44
-rw-r--r--src/server/game/Chat/Channels/Channel.h6
-rw-r--r--src/server/game/Chat/Chat.cpp6
-rw-r--r--src/server/game/DataStores/DBCEnums.h282
-rw-r--r--src/server/game/DataStores/DBCStores.cpp24
-rw-r--r--src/server/game/DataStores/DBCStores.h3
-rw-r--r--src/server/game/DataStores/DBCStructure.h26
-rw-r--r--src/server/game/DataStores/DBCfmt.h1
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp2
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.cpp12
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp12
-rw-r--r--src/server/game/Entities/Object/Object.cpp74
-rw-r--r--src/server/game/Entities/Object/Object.h11
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp24
-rw-r--r--src/server/game/Entities/Pet/Pet.h8
-rw-r--r--src/server/game/Entities/Player/Player.cpp186
-rw-r--r--src/server/game/Entities/Player/Player.h88
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp2
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp20
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp169
-rw-r--r--src/server/game/Entities/Unit/Unit.h37
-rw-r--r--src/server/game/Events/GameEventMgr.h2
-rw-r--r--src/server/game/Garrison/Garrison.cpp115
-rw-r--r--src/server/game/Garrison/Garrison.h10
-rw-r--r--src/server/game/Garrison/GarrisonMap.cpp18
-rw-r--r--src/server/game/Garrison/GarrisonMap.h4
-rw-r--r--src/server/game/Garrison/GarrisonMgr.cpp160
-rw-r--r--src/server/game/Garrison/GarrisonMgr.h11
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp27
-rw-r--r--src/server/game/Globals/ObjectMgr.h3
-rw-r--r--src/server/game/Groups/Group.cpp451
-rw-r--r--src/server/game/Groups/Group.h156
-rw-r--r--src/server/game/Groups/GroupMgr.cpp7
-rw-r--r--src/server/game/Groups/GroupMgr.h2
-rw-r--r--src/server/game/Guilds/Guild.cpp8
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp33
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp16
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp982
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp13
-rw-r--r--src/server/game/Handlers/LFGHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp122
-rw-r--r--src/server/game/Handlers/PetHandler.cpp3
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp4
-rw-r--r--src/server/game/Loot/LootMgr.cpp6
-rw-r--r--src/server/game/Maps/Map.h2
-rw-r--r--src/server/game/Maps/MapInstanced.cpp2
-rw-r--r--src/server/game/Maps/ZoneScript.h4
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h4
-rw-r--r--src/server/game/Movement/MotionMaster.h2
-rw-r--r--src/server/game/Quests/QuestDef.cpp4
-rw-r--r--src/server/game/Quests/QuestDef.h8
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/game/Server/Packets/ChannelPackets.h10
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.cpp37
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.h31
-rw-r--r--src/server/game/Server/Packets/ChatPackets.cpp14
-rw-r--r--src/server/game/Server/Packets/ChatPackets.h20
-rw-r--r--src/server/game/Server/Packets/CombatLogPackets.cpp37
-rw-r--r--src/server/game/Server/Packets/CombatLogPackets.h34
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.cpp4
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.h3
-rw-r--r--src/server/game/Server/Packets/InstancePackets.cpp26
-rw-r--r--src/server/game/Server/Packets/InstancePackets.h24
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp18
-rw-r--r--src/server/game/Server/Packets/ItemPackets.h24
-rw-r--r--src/server/game/Server/Packets/MiscPackets.cpp69
-rw-r--r--src/server/game/Server/Packets/MiscPackets.h21
-rw-r--r--src/server/game/Server/Packets/MovementPackets.h2
-rw-r--r--src/server/game/Server/Packets/PartyPackets.cpp715
-rw-r--r--src/server/game/Server/Packets/PartyPackets.h616
-rw-r--r--src/server/game/Server/Packets/QuestPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/QuestPackets.h3
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp103
-rw-r--r--src/server/game/Server/WorldSession.cpp18
-rw-r--r--src/server/game/Server/WorldSession.h102
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp30
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h1
-rw-r--r--src/server/game/Spells/Spell.cpp25
-rw-r--r--src/server/game/Spells/Spell.h1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp25
-rw-r--r--src/server/game/Spells/SpellInfo.cpp3
-rw-r--r--src/server/game/Spells/SpellMgr.cpp4
-rw-r--r--src/server/game/Spells/SpellScript.cpp8
-rw-r--r--src/server/game/Spells/SpellScript.h2
-rw-r--r--src/server/game/Texts/ChatTextBuilder.h4
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp4
-rw-r--r--src/server/game/World/World.cpp9
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp2
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp4
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp71
-rw-r--r--src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp12
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp6
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h12
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp20
-rw-r--r--src/server/scripts/Northrend/zone_icecrown.cpp48
-rw-r--r--src/server/scripts/OutdoorPvP/OutdoorPvPNA.h8
-rw-r--r--src/server/scripts/Outland/CMakeLists.txt1
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp4
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp5
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp28
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp231
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp255
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h80
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp12
-rw-r--r--src/server/shared/Common.h11
-rw-r--r--src/server/shared/Cryptography/SHA1.h4
-rw-r--r--src/server/shared/Cryptography/SHA256.h4
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp7
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h5
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.cpp2
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.cpp203
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.h3
-rw-r--r--src/server/shared/Logging/Log.h5
-rw-r--r--src/server/shared/PrecompiledHeaders/sharedPCH.h1
-rw-r--r--src/server/shared/Updater/DBUpdater.cpp19
-rw-r--r--src/server/shared/Utilities/TaskScheduler.cpp204
-rw-r--r--src/server/shared/Utilities/TaskScheduler.h591
-rw-r--r--src/server/worldserver/worldserver.conf.dist2
155 files changed, 5612 insertions, 2137 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5dfa9c5113b..01e941cc465 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,33 +1,66 @@
# Contributing
-Want to contribute? Great!
+So, you want to contribute? Great!
+Contributing is not only about creating fixes, but also reporting bugs. Before reporting a bug, please make sure to use the latest core and database revision.
+
+
+Issues
+======
+
+Read [this](http://www.trinitycore.org/f/topic/37-the-trinitycore-issuetracker-and-you/) before creating a ticket.
+If you have problems with TrinityCore instalation, read [this](http://www.trinitycore.org/f/topic/1518-trouble-with-your-trinity-install-readme-1st-faqs/)
+
+Mandatory things when creating a ticket:
+========================================
+
+- Branch
+- commit hash (if you get something like TrinityCore rev. unknown 1970-01-01 00:00:00 +0000 (Archived branch) (Win64, Release), please read this [post](http://www.trinitycore.org/f/topic/345-howto-properly-install-git-on-windows-fix-trinitycore-rev-1970-01-01-000000-0000/) or clone this repository instead downloading the source code.
+- entries of affected creatures / items / quests with a link to the relevant wowhead page.
+- clear title and description of the bug - if your english is very bad, please use google translate or yandex to translate to english and include one text in your native language.
+
+When reporting a crash, you MUST compile in debug mode because release dumps are useless (not enough information) - if you don't know how to compile in debug, read [this](http://www.trinitycore.org/f/topic/1518-trouble-with-your-trinity-install-readme-1st-faqs/#entry47672)
+
+We sugest the title and body to have the next style:
+
+DB/Quest: The Collapse
+
+4.3.4 branch
+hash 63f96a282307
+The quest "The Collapse" http://www.wowhead.com/quest=11706 lacks final event.
+
+Creating Pull Requests:
+=======================
1. Fork it.
-2. Create a branch (`git checkout -b fixes`)
+2. Create a branch (`git checkout -b fixes`) (Note: fixes is an arbitrary name, choose whatever you want here)
3. Commit your changes (`git commit -am "Added Snarkdown"`)
4. Push to the branch (`git push origin fixes`)
5. Open a Pull Request
+
When creating patches read:
- [TrinityCore Development Standards](http://www.trinitycore.org/f/topic/6-trinitycore-developing-standards/)
- [WDB Fields](http://www.trinitycore.org/f/topic/58-wdb-fields/)
- [Git Squash](https://ariejan.net/2011/07/05/git-squash-your-latests-commits-into-one/)
-- [SQL Guidelines](http://collab.kpsn.org/display/tc/SQL+Guidelines)
-We suggest you to create one branch for each `C++` based fix: on that way you can continue creating more fixes without having to wait to get one pull request merged.
-For the `SQL` files of `C++` based fixes the naming schema is: `YYYY_MM_DD_i_database.sql`, where `YYYY_MM_DD` is the date of the fix, `i_database` is the *ith* sql created that day for `database` starting on 00.
+
+We suggest that you create one branch for each C++ based fix: this will allow you to create more fixes without having to wait for your pull request to be merged.
+For the SQL files coming with C++ based fixes the naming schema is `YYYY_MM_DD_i_database.sql`, where `YYYY_MM_DD` is the date of the fix, `i_database` is the *ith* sql created that day for `database`.
When doing changes to `auth` or `characters` database remember to update the base files (`/sql/base/*`).
-For SQL only fixes [create a ticket](https://github.com/TrinityCore/TrinityCore/issues/new).
+For SQL only fixes, please [create a ticket](https://github.com/TrinityCore/TrinityCore/issues/new).
+Since it's very unlikely that your Pull Request will be merged on the day that you open it, please name the files with an impossible date to avoid merging issues ie: 2015_13_32_00_world.sql
+
+Wiki
+====
+
+The wiki is located at [http://trinitycore.info](http://trinitycore.info).
+
+You are welcome to create an account and help us improve and extend the wiki.
-Issues
-======
-Read [this](http://www.trinitycore.org/f/topic/37-the-trinitycore-issuetracker-and-you/) before creating a ticket.
-If you have problems with TrinityCore instalation, read
-http://www.trinitycore.org/f/topic/10656-updating-or-starting-with-trinitycore-issues/
-http://www.trinitycore.org/f/topic/1518-trouble-with-your-trinity-install-readme-1st-faqs/
Requirements
============
+
Platform: Linux, Windows or Mac
Processor with SSE2 support
Boost ≥ 1.4.9
@@ -35,12 +68,6 @@ MySQL ≥ 5.1.0
CMake ≥ 2.8.11.2 / 2.8.9 (Windows / Linux)
OpenSSL ≥ 1.0.0
GCC ≥ 4.7.2 (Linux only)
-MS Visual Studio ≥ 12 (2013) (Windows only) (we recommend Visual Studio 2013 community edition, free for open source developers)
-
-In case you choose Linux, we recommend to use Debian 7, it's the Linux we use to test compilations.
-
-Wiki
-====
-The wiki is located at [http://trinitycore.info](http://trinitycore.info).
-You are welcome to create an account and help us improve and extend the wiki.
+MS Visual Studio ≥ 12 (2013) Update 4 (Windows only)
+If you choose Linux, we recommend to use Debian 8, since it's the Linux that we use to test compilations.
diff --git a/cmake/compiler/clang/settings.cmake b/cmake/compiler/clang/settings.cmake
index 98f893987ec..a449551a357 100644
--- a/cmake/compiler/clang/settings.cmake
+++ b/cmake/compiler/clang/settings.cmake
@@ -17,3 +17,4 @@ endif()
# -Wno-narrowing needed to suppress a warning in g3d
# -Wno-deprecated-register is needed to suppress 185 gsoap warnings on Unix systems.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-narrowing -Wno-deprecated-register")
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1")
diff --git a/cmake/macros/CheckPlatform.cmake b/cmake/macros/CheckPlatform.cmake
index e08aaed8db2..0f41a9c127e 100644
--- a/cmake/macros/CheckPlatform.cmake
+++ b/cmake/macros/CheckPlatform.cmake
@@ -7,8 +7,6 @@ else()
MESSAGE(STATUS "Detected 32-bit platform")
endif()
-include("${CMAKE_SOURCE_DIR}/cmake/platform/settings.cmake")
-
if(WIN32)
include("${CMAKE_SOURCE_DIR}/cmake/platform/win/settings.cmake")
elseif(UNIX)
diff --git a/cmake/platform/settings.cmake b/cmake/platform/settings.cmake
deleted file mode 100644
index 6df5bc2165f..00000000000
--- a/cmake/platform/settings.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-# set installation prefix
-if( PREFIX )
- set(CMAKE_INSTALL_PREFIX "${PREFIX}")
-endif()
-
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 37b84dfc29d..d73924aa76d 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -827,6 +827,66 @@ LOCK TABLES `character_garrison_buildings` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `character_garrison_followers`
+--
+
+DROP TABLE IF EXISTS `character_garrison_followers`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `character_garrison_followers` (
+ `dbId` bigint(20) unsigned NOT NULL,
+ `guid` bigint(20) unsigned NOT NULL,
+ `followerId` int(10) unsigned NOT NULL,
+ `quality` int(10) unsigned NOT NULL DEFAULT '2',
+ `level` int(10) unsigned NOT NULL DEFAULT '90',
+ `itemLevelWeapon` int(10) unsigned NOT NULL DEFAULT '600',
+ `itemLevelArmor` int(10) unsigned NOT NULL DEFAULT '600',
+ `xp` int(10) unsigned NOT NULL DEFAULT '0',
+ `currentBuilding` int(10) unsigned NOT NULL DEFAULT '0',
+ `currentMission` int(10) unsigned NOT NULL DEFAULT '0',
+ `status` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`dbId`),
+ UNIQUE KEY `idx_guid_id` (`guid`,`followerId`),
+ CONSTRAINT `fk_foll_owner` FOREIGN KEY (`guid`) REFERENCES `characters` (`guid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `character_garrison_followers`
+--
+
+LOCK TABLES `character_garrison_followers` WRITE;
+/*!40000 ALTER TABLE `character_garrison_followers` DISABLE KEYS */;
+/*!40000 ALTER TABLE `character_garrison_followers` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `character_garrison_follower_abilities`
+--
+
+DROP TABLE IF EXISTS `character_garrison_follower_abilities`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `character_garrison_follower_abilities` (
+ `dbId` bigint(20) unsigned NOT NULL,
+ `abilityId` int(10) unsigned NOT NULL,
+ `slot` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`dbId`,`abilityId`,`slot`),
+ CONSTRAINT `fk_foll_dbid` FOREIGN KEY (`dbId`) REFERENCES `character_garrison_followers` (`dbId`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `character_garrison_follower_abilities`
+--
+
+LOCK TABLES `character_garrison_follower_abilities` WRITE;
+/*!40000 ALTER TABLE `character_garrison_follower_abilities` DISABLE KEYS */;
+/*!40000 ALTER TABLE `character_garrison_follower_abilities` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+--
-- Table structure for table `character_gifts`
--
diff --git a/sql/updates/characters/2015_05_22_00_characters.sql b/sql/updates/characters/2015_05_22_00_characters.sql
new file mode 100644
index 00000000000..35e72a5aa86
--- /dev/null
+++ b/sql/updates/characters/2015_05_22_00_characters.sql
@@ -0,0 +1,35 @@
+DROP TABLE IF EXISTS `character_garrison_follower_abilities`;
+DROP TABLE IF EXISTS `character_garrison_followers`;
+
+--
+-- Table structure for table `character_garrison_followers`
+--
+
+CREATE TABLE `character_garrison_followers` (
+ `dbId` bigint(20) unsigned NOT NULL,
+ `guid` bigint(20) unsigned NOT NULL,
+ `followerId` int(10) unsigned NOT NULL,
+ `quality` int(10) unsigned NOT NULL DEFAULT '2',
+ `level` int(10) unsigned NOT NULL DEFAULT '90',
+ `itemLevelWeapon` int(10) unsigned NOT NULL DEFAULT '600',
+ `itemLevelArmor` int(10) unsigned NOT NULL DEFAULT '600',
+ `xp` int(10) unsigned NOT NULL DEFAULT '0',
+ `currentBuilding` int(10) unsigned NOT NULL DEFAULT '0',
+ `currentMission` int(10) unsigned NOT NULL DEFAULT '0',
+ `status` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`dbId`),
+ UNIQUE KEY `idx_guid_id` (`guid`,`followerId`),
+ CONSTRAINT `fk_foll_owner` FOREIGN KEY (`guid`) REFERENCES `characters` (`guid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `character_garrison_follower_abilities`
+--
+
+CREATE TABLE `character_garrison_follower_abilities` (
+ `dbId` bigint(20) unsigned NOT NULL,
+ `abilityId` int(10) unsigned NOT NULL,
+ `slot` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`dbId`,`abilityId`,`slot`),
+ CONSTRAINT `fk_foll_dbid` FOREIGN KEY (`dbId`) REFERENCES `character_garrison_followers` (`dbId`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/sql/updates/world/2015_05_19_00_world.sql b/sql/updates/world/2015_05_19_00_world.sql
new file mode 100644
index 00000000000..420a94c7a0c
--- /dev/null
+++ b/sql/updates/world/2015_05_19_00_world.sql
@@ -0,0 +1,4 @@
+ALTER TABLE `terrain_swap_defaults` ENGINE=MyISAM;
+ALTER TABLE `terrain_phase_info` ENGINE=MyISAM;
+ALTER TABLE `terrain_worldmap` ENGINE=MyISAM;
+ALTER TABLE `phase_area` ENGINE=MyISAM;
diff --git a/sql/updates/world/2015_05_19_01_world_2015_04_24_00.sql b/sql/updates/world/2015_05_19_01_world_2015_04_24_00.sql
new file mode 100644
index 00000000000..d8fffb58bf5
--- /dev/null
+++ b/sql/updates/world/2015_05_19_01_world_2015_04_24_00.sql
@@ -0,0 +1,42 @@
+-- Manual Spawn Randy Whizzlesprocket
+SET @GUID := 49056;
+DELETE FROM `creature` WHERE `guid` = @GUID;
+INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`) VALUES
+(@GUID, 17288, 540, 0, 0, 2, 0, 0, 131.106, 254.520, -45.236, 3.951, 7200, 0, 0, 6104, 0, 0, 0, 0, 0);
+
+-- Missing 2xEmblem of Justice from quest 'Imprisoned in the citadel'
+-- UPDATE `quest_template` SET `RewardItemId1` = 29434, `RewardItemCount1` = 2 WHERE `Id` IN (9524,9525);
+
+-- Update Shattered Hand Executioner loot Table
+UPDATE `creature_loot_template` SET `LootMode` = 8, `GroupId` = 1, `Chance` = 0 WHERE `Entry` = 20585;
+DELETE FROM `creature_loot_template` WHERE `Entry` = 20585 AND `Item` IN (31716,29434,22829,22832,24726);
+INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(20585, 31716, 0, 100, 1, 2|4|8, 0, 1, 1, NULL), -- Unused Axe
+(20585, 29434, 0, 100, 0, 8, 0, 1, 1, NULL), -- 1x Emblem of Justice (3 Prisoners Rescued)
+(20585, 22829, 0, 0, 0, 2|4|8, 2, 2, 8, NULL), -- Greater Potions
+(20585, 22832, 0, 0, 0, 2|4|8, 2, 2, 8, NULL),
+(20585, 24726, 24726, 100, 0, 4|8, 0, 1, 1, NULL); -- Scroll of XXXX VI
+
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 17301 AND `source_type` = 0;
+UPDATE `creature_template` SET `AIName` = '', ScriptName = 'boss_shattered_executioner', `flags_extra` = 0 WHERE `entry` = 17301;
+UPDATE `creature_template` SET `unit_flags` = 33088 WHERE `entry` IN (17301,20585);
+UPDATE `creature_template` SET `unit_flags` = 33555200 WHERE `entry` IN (19523,19524,20572,20573);
+UPDATE `creature_template` SET `flags_extra` = 0 WHERE `entry` = 20585;
+
+DELETE FROM `areatrigger_scripts` WHERE `entry` = 4524;
+INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES
+(4524, 'at_nethekurse_exit');
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (39288,39289,39290);
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(39288, 'spell_kargath_executioner'),
+(39289, 'spell_kargath_executioner'),
+(39290, 'spell_kargath_executioner');
+
+UPDATE `gameobject_template` SET `flags` = 34 WHERE `entry` IN (182539,182540); -- Sniffed value
+-- Missing texts
+SET @KARGATH := 16808;
+SET @BROADCAST := 13721;
+DELETE FROM `creature_text` WHERE `entry` = @KARGATH AND `groupid` IN (3,4);
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(@KARGATH, 3, 0, 'The Alliance dares to intrude this far into my fortress? Bring out the Honor Hold prisoners and call for the executioner! They''ll pay with their lives for this trespass!', 14, 0, 100, 0, 0, 0, @BROADCAST+0, 3, 'kargath SAY_CALL_EXECUTIONER_A'),
+(@KARGATH, 4, 0, 'Thrall''s false Horde dares to intrude this far into my fortress? Bring out the Thrallmar prisoners and call for the executioner! They''ll pay with their lives for this trespass!', 14, 0, 100, 0, 0, 0, @BROADCAST+1, 3, 'kargath SAY_CALL_EXECUTIONER_H');
diff --git a/sql/updates/world/2015_05_19_02_world_2015_04_18_00.sql b/sql/updates/world/2015_05_19_02_world_2015_04_18_00.sql
new file mode 100644
index 00000000000..29d67fe0429
--- /dev/null
+++ b/sql/updates/world/2015_05_19_02_world_2015_04_18_00.sql
@@ -0,0 +1 @@
+UPDATE `creature_template` SET `InhabitType`=3 WHERE `entry` IN (5931, 3989, 3988, 3991, 3999, 4004, 4003);
diff --git a/sql/updates/world/2015_05_19_03_world_2015_04_18_01.sql b/sql/updates/world/2015_05_19_03_world_2015_04_18_01.sql
new file mode 100644
index 00000000000..707335c490e
--- /dev/null
+++ b/sql/updates/world/2015_05_19_03_world_2015_04_18_01.sql
@@ -0,0 +1,6 @@
+--
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=40060 AND `ConditionTypeOrReference`=29;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
+(15,40060,0,0,0,29,0,9461,100,0,1,0,0,'','Gor Grimgut cannot be a target for Exhaustion.'),
+(15,40060,0,0,1,29,0,9461,100,0,1,0,0,'','Gor Grimgut cannot be a target for Exhaustion.'),
+(15,40060,0,0,2,29,0,9461,100,0,1,0,0,'','Gor Grimgut cannot be a target for Exhaustion.');
diff --git a/sql/updates/world/2015_05_19_03_world_2015_04_18_02.sql b/sql/updates/world/2015_05_19_03_world_2015_04_18_02.sql
new file mode 100644
index 00000000000..6a299828e26
--- /dev/null
+++ b/sql/updates/world/2015_05_19_03_world_2015_04_18_02.sql
@@ -0,0 +1,13 @@
+--
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=17918;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=17918 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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+
+(17918, 0, 0, 0, 0, 0, 100, 0, 3000, 7000, 8000, 12000, 11, 31478, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,0,'Time Keeper - IC - Cast Sand Breath'),
+(17918, 0, 1, 0, 0, 0, 100, 0, 5000, 10000, 20000, 30000, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,0,'Time Keeper - IC - Cast Sand Breath');
+
+DELETE FROM `creature_text` WHERE `entry` IN (17918);
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(17918, 0, 0, 'Victory will be ours!', 14, 0, 100, 0, 0, 0, 15194, 0, 'Time Keeper'),
+(17918, 0, 1, 'Carry on! Victory at all costs!', 14, 0, 100, 0, 0, 0, 15195, 0, 'Time Keeper'),
+(17918, 0, 2, 'Continue the fight! Do not falter!', 14, 0, 100, 0, 0, 0, 15196, 0, 'Time Keeper');
diff --git a/sql/updates/world/2015_05_19_04_world_2015_04_18_03.sql b/sql/updates/world/2015_05_19_04_world_2015_04_18_03.sql
new file mode 100644
index 00000000000..cc6d3d65dea
--- /dev/null
+++ b/sql/updates/world/2015_05_19_04_world_2015_04_18_03.sql
@@ -0,0 +1,4 @@
+--
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = 54355 AND `spell_effect` = 54402;
+INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES
+(54355, 54402, 0, 'Land Mine');
diff --git a/sql/updates/world/2015_05_19_04_world_2015_04_18_05.sql b/sql/updates/world/2015_05_19_04_world_2015_04_18_05.sql
new file mode 100644
index 00000000000..b61ff01bdfc
--- /dev/null
+++ b/sql/updates/world/2015_05_19_04_world_2015_04_18_05.sql
@@ -0,0 +1,9 @@
+--
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger` IN (-24869, -61874, -71074, -71068, -71073, -71071) AND `spell_effect` = 24870;
+INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES
+(-24869, 24870, 0, 'Bobbing Apple, Bread of the Dead, Winter Veil Cookie'),
+(-61874, 24870, 0, 'Noblegarden Chocolate'),
+(-71074, 24870, 0, 'Buttermilk Delight'),
+(-71068, 24870, 0, 'Sweet Surprise'),
+(-71073, 24870, 0, 'Dark Desire'),
+(-71071, 24870, 0, 'Very Berry Cream');
diff --git a/sql/updates/world/2015_05_20_00_world_2015_05_19_01.sql b/sql/updates/world/2015_05_20_00_world_2015_05_19_01.sql
new file mode 100644
index 00000000000..12ab4d8677b
--- /dev/null
+++ b/sql/updates/world/2015_05_20_00_world_2015_05_19_01.sql
@@ -0,0 +1,22 @@
+-- Gossip Menu Option for Squire David (33447)
+SET @SourceGroup = 10340;
+SET @SourceEntry = 0;
+SET @ConditionTypeOrReference = 9;
+
+DELETE FROM conditions where SourceGroup=@SourceGroup and SourceEntry=@SourceEntry;
+INSERT INTO conditions(SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ErrorTextId, ScriptName, Comment) VALUES
+(15, @SourceGroup, @SourceEntry, 0, 0, @ConditionTypeOrReference, 0, 13679, 0, 0, 0, 0, 0, '', 'Show gossip option if player has quest 13679'),
+(15, @SourceGroup, @SourceEntry, 0, 1, @ConditionTypeOrReference, 0, 13680, 0, 0, 0, 0, 0, '', 'Show gossip option if player has quest 13680');
+
+-- Squire David SAI
+SET @ENTRY := 33447;
+UPDATE creature_template SET ScriptName="" WHERE entry=33447;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,1,62,0,100,0,10340,0,0,0,11,63028,0,0,0,0,0,7,0,0,0,0,0,0,0,"Squire David - On Gossip Option 0 Selected - Cast 'Force Cast'"),
+(@ENTRY,0,1,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,"Squire David - On Gossip Option 0 Selected - Close Gossip");
+
+DELETE FROM `spell_target_position` WHERE `id`=63026;
+INSERT INTO `spell_target_position` (`id`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`) VALUES
+(63026, 0, 571, 8575.38, 921.85, 547.554);
diff --git a/sql/updates/world/2015_05_20_01_world_2015_05_19_02.sql b/sql/updates/world/2015_05_20_01_world_2015_05_19_02.sql
new file mode 100644
index 00000000000..46125437940
--- /dev/null
+++ b/sql/updates/world/2015_05_20_01_world_2015_05_19_02.sql
@@ -0,0 +1,3 @@
+DELETE FROM `spell_target_position` WHERE `id`=63171;
+INSERT INTO `spell_target_position` (`id`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`) VALUES
+(63171, 0, 571, 8533.11, 1069.66, 551.784);
diff --git a/sql/updates/world/2015_05_21_00_world_2015_04_18_06.sql b/sql/updates/world/2015_05_21_00_world_2015_04_18_06.sql
new file mode 100644
index 00000000000..aa532de444b
--- /dev/null
+++ b/sql/updates/world/2015_05_21_00_world_2015_04_18_06.sql
@@ -0,0 +1,5 @@
+DELETE FROM `smart_scripts` WHERE `entryorguid`=26472 AND `source_type`=0 AND `id` IN(4,5,6);
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(26472, 0, 4, 5, 8, 0, 100, 1, 49319, 0, 0, 0, 89, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Highland Mustang - On Spellhit \'Scare Highland Mustang\' - Flee For Assist (No Repeat)'),
+(26472, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 11, 49323, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Highland Mustang - On Spellhit \'Scare Highland Mustang\' - Cast \'Highland Mustang Spooking Credit\' (No Repeat)'),
+(26472, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Highland Mustang - On Spellhit \'Scare Highland Mustang\' - Despawn In 5000 ms (No Repeat)');
diff --git a/sql/updates/world/2015_05_22_00_world.sql b/sql/updates/world/2015_05_22_00_world.sql
new file mode 100644
index 00000000000..f82e738ea20
--- /dev/null
+++ b/sql/updates/world/2015_05_22_00_world.sql
@@ -0,0 +1,91 @@
+DROP TABLE IF EXISTS `garrison_follower_class_spec_abilities`;
+CREATE TABLE `garrison_follower_class_spec_abilities` (
+ `classSpecId` int(10) unsigned NOT NULL DEFAULT '0',
+ `abilityId` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`classSpecId`,`abilityId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO `garrison_follower_class_spec_abilities` (`abilityId`,`classSpecId`) VALUES
+(119,3), -- Anti-Magic Shell
+(158,29),(158,30), -- Ascendance
+(131,22), -- Avenging Wrath
+(132,7),(132,8), -- Barkskin
+(138,7), -- Berserk
+(170,14),(170,15), -- Blink
+(5,15),(5,16), -- Blizzard
+(115,2),(115,4), -- Bone Shield
+(139,5), -- Celestial Alignment
+(106,29),(106,30),(106,31), -- Chain Heal
+(154,29),(154,30),(154,31), -- Chain Lightning
+(142,17),(142,18), -- Chi Wave
+(125,20),(125,21), -- Cleanse
+(120,35),(120,37),(120,38), -- Cleave
+(169,14), -- Conjure Food
+(166,12), -- Counter Shot
+(171,14),(171,15),(171,16), -- Counterspell
+(114,2),(114,3),(114,4), -- Dark Command
+(182,5),(182,7),(182,8), -- Dash
+(116,2),(116,3),(116,4), -- Death and Decay
+(164,13), -- Deterrence
+(145,18), -- Detox
+(165,10),(165,12),(165,13), -- Disengage
+(148,23),(148,24),(148,25), -- Dispel Magic
+(129,20), -- Divine Plea
+(124,21),(124,22), -- Divine Shield
+(130,22), -- Divine Storm
+(151,23),(151,25), -- Dominate Mind
+(175,34), -- Drain Life
+(118,2),(118,3),(118,4), -- Empower Rune Weapon
+(183,19), -- Energizing Brew
+(134,5),(134,8),(134,9), -- Entangling Roots
+(159,26),(159,28), -- Evasion
+(161,27),(161,28), -- Fan of Knives
+(180,32),(180,34), -- Fear
+(163,10), -- Feign Death
+(167,10),(167,12),(167,13), -- Freezing Trap
+(156,30), -- Ghost Wolf
+(108,7),(108,8), -- Growl
+(141,17), -- Guard
+(102,35),(102,37),(102,38), -- Heroic Leap
+(157,29),(157,30), -- Hex
+(128,20), -- Holy Radiance
+(137,5),(137,9), -- Hurricane
+(168,16), -- Ice Block
+(133,5),(133,7),(133,8),(133,9), -- Innervate
+(105,26),(105,27),(105,28), -- Kick
+(10,23),(10,24),(10,25), -- Leap of Faith
+(146,18), -- Mana Tea
+(162,26),(162,27), -- Marked for Death
+(177,33),(177,34), -- Metamorphosis
+(117,2),(117,3),(117,4), -- Mind Freeze
+(150,24),(150,25), -- Mind Sear
+(101,10),(101,12),(101,13), -- Multi-Shot
+(136,9), -- Nature's Cure
+(144,17),(144,19), -- Paralysis
+(172,14),(172,15),(172,16), -- Polymorph
+(152,25), -- Power Infusion
+(11,23),(11,24), -- Prayer of Healing
+(140,17),(140,19), -- Provoke
+(121,35),(121,37),(121,38), -- Pummel
+(107,31), -- Purify Spirit
+(178,32),(178,33), -- Rain of Fire
+(103,10),(103,12),(103,13), -- Rapid Fire
+(126,20),(126,21),(126,22), -- Rebuke
+(122,35),(122,37), -- Recklessness
+(123,21), -- Reckoning
+(127,20),(127,21),(127,22), -- Repentance
+(143,17),(143,18),(143,19), -- Roll
+(104,26),(104,27),(104,28), -- Sap
+(149,23),(149,24), -- Shadowfiend
+(6,37),(6,38), -- Shield Wall
+(176,32), -- Singe Magic
+(147,18),(147,19), -- Spear Hand Strike
+(179,32),(179,33),(179,34), -- Spell Lock
+(160,26),(160,27),(160,28), -- Sprint
+(181,32),(181,33),(181,34), -- Summon Infernal
+(100,35),(100,38), -- Taunt
+(173,14),(173,15),(173,16), -- Time Warp
+(174,33), -- Unending Resolve
+(153,31), -- Water Shield
+(135,9), -- Wild Growth
+(155,29),(155,31); -- Wind Shear
diff --git a/sql/updates/world/2015_05_27_00_world.sql b/sql/updates/world/2015_05_27_00_world.sql
new file mode 100644
index 00000000000..8e62a9e3343
--- /dev/null
+++ b/sql/updates/world/2015_05_27_00_world.sql
@@ -0,0 +1,51 @@
+--
+DELETE FROM `creature_formations` WHERE `leaderGUID`=366728;
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(366728, 366728, 0, 0, 2, 0, 0),
+(366728, 366739, 0, 0, 2, 0, 0),
+(366728, 366727, 0, 0, 2, 0, 0);
+
+DELETE FROM `creature_addon` WHERE `guid` IN (366739, 366727);
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES
+(366739,0,0,0,1,0, ''),
+(366727,0,0,0,1,0, '');
+
+-- Magram Warden SAI
+SET @ENTRY := 36134;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,4,0,100,1,0,0,0,0,11,8258,0,0,0,0,0,1,0,0,0,0,0,0,0,"Magram Warden - On Aggro - Cast 'Devotion Aura' (No Repeat)"),
+(@ENTRY,0,1,0,11,0,100,1,0,0,0,0,11,7165,0,0,0,0,0,1,0,0,0,0,0,0,0,"Magram Warden - On Respawn - Cast 'Battle Stance' (No Repeat)"),
+(@ENTRY,0,2,0,0,0,100,0,2000,4500,12000,14000,11,25710,0,0,0,0,0,2,0,0,0,0,0,0,0,"Magram Warden - In Combat - Cast 'Heroic Strike'"),
+(@ENTRY,0,3,0,2,0,100,1,0,15,0,0,25,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Magram Warden - Between 0-15% Health - Flee For Assist (No Repeat)"),
+(@ENTRY,0,4,0,6,0,100,0,0,0,0,0,45,1,0,0,0,0,0,11,36137,100,0,0,0,0,0,"Magram Warden - On Just Died - Set Data 1 0");
+
+-- Kolkar Prisoner SAI
+SET @ENTRY := 36137;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,2,0,100,1,0,15,0,0,25,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kolkar Prisoner - Between 0-15% Health - Flee For Assist (No Repeat)"),
+(@ENTRY,0,1,0,38,0,100,0,1,0,0,0,88,@ENTRY*100+00,@ENTRY*100+01,@ENTRY*100+02,0,0,0,1,0,0,0,0,0,0,0,"Kolkar Prisoner - On Data Set 1 0 - Run Random Script");
+
+-- Actionlist SAI
+SET @ENTRY := 3613700;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,-1256.915283,1051.419556,91.691681,2.778741,"On Script - Move To Position"),
+(@ENTRY,9,1,0,0,0,100,0,12000,12000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Despawn Instant");
+
+-- Actionlist SAI
+SET @ENTRY := 3613701;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,-1276.356445,1026.592651,91.140945,2.778741,"On Script - Move To Position"),
+(@ENTRY,9,1,0,0,0,100,0,12000,12000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Despawn Instant");
+
+-- Actionlist SAI
+SET @ENTRY := 3613702;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=9;
+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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,9,0,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,-1263.007324,967.299744,90.557411,3.721225,"On Script - Move To Position"),
+(@ENTRY,9,1,0,0,0,100,0,12000,12000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"On Script - Despawn Instant");
diff --git a/sql/updates/world/2015_05_29_00_world.sql b/sql/updates/world/2015_05_29_00_world.sql
new file mode 100644
index 00000000000..779427a0167
--- /dev/null
+++ b/sql/updates/world/2015_05_29_00_world.sql
@@ -0,0 +1 @@
+ALTER TABLE `quest_template` CHANGE `Float10` `RewardXPMultiplier` float NOT NULL DEFAULT '1';
diff --git a/sql/updates/world/2015_06_01_00_world_2015_05_26_05.sql b/sql/updates/world/2015_06_01_00_world_2015_05_26_05.sql
new file mode 100644
index 00000000000..d7ef0e17204
--- /dev/null
+++ b/sql/updates/world/2015_06_01_00_world_2015_05_26_05.sql
@@ -0,0 +1,3 @@
+DELETE FROM `spell_script_names` WHERE `spell_id` = 39291;
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(39291, 'spell_remove_kargath_executioner');
diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp
index 20d1193b8e2..e1c0b187c46 100644
--- a/src/server/bnetserver/Main.cpp
+++ b/src/server/bnetserver/Main.cpp
@@ -57,9 +57,9 @@ void SignalHandler(const boost::system::error_code& error, int signalNumber);
void KeepDatabaseAliveHandler(const boost::system::error_code& error);
variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile);
-std::unique_ptr<boost::asio::io_service> _ioService;
-std::unique_ptr<boost::asio::deadline_timer> _dbPingTimer;
-uint32 _dbPingInterval;
+static std::unique_ptr<boost::asio::io_service> _ioService;
+static std::unique_ptr<boost::asio::deadline_timer> _dbPingTimer;
+static uint32 _dbPingInterval;
LoginDatabaseWorkerPool LoginDatabase;
int main(int argc, char** argv)
diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp
index 25a9a86bc1b..e0b1ed3b161 100644
--- a/src/server/collision/Management/MMapManager.cpp
+++ b/src/server/collision/Management/MMapManager.cpp
@@ -177,7 +177,8 @@ namespace MMAP
{
TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header in mmap %04u%02i%02i.mmtile", mapId, x, y);
fclose(file);
- return NULL;
+ delete pTile;
+ return nullptr;
}
if (pTile->fileHeader.mmapVersion != MMAP_VERSION)
@@ -185,7 +186,8 @@ namespace MMAP
TC_LOG_ERROR("phase", "MMAP:LoadTile: %04u%02i%02i.mmtile was built with generator v%i, expected v%i",
mapId, x, y, pTile->fileHeader.mmapVersion, MMAP_VERSION);
fclose(file);
- return NULL;
+ delete pTile;
+ return nullptr;
}
pTile->data = (unsigned char*)dtAlloc(pTile->fileHeader.size, DT_ALLOC_PERM);
@@ -196,7 +198,8 @@ namespace MMAP
{
TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header or data in mmap %04u%02i%02i.mmtile", mapId, x, y);
fclose(file);
- return NULL;
+ delete pTile;
+ return nullptr;
}
fclose(file);
@@ -475,7 +478,10 @@ namespace MMAP
PhasedTile* pt = new PhasedTile();
// remove old tile
if (dtStatusFailed(navMesh->removeTile(loadedTileRefs[packedXY], &pt->data, &pt->dataSize)))
+ {
TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not unload %04u%02i%02i.mmtile from navmesh", _mapId, x, y);
+ delete pt;
+ }
else
{
TC_LOG_DEBUG("phase", "MMapData::AddSwap: Unloaded %04u%02i%02i.mmtile from navmesh", _mapId, x, y);
diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp
index 86391d5488a..ce39dc02da8 100644
--- a/src/server/collision/Maps/TileAssembler.cpp
+++ b/src/server/collision/Maps/TileAssembler.cpp
@@ -24,7 +24,6 @@
#include <set>
#include <iomanip>
#include <sstream>
-#include <iomanip>
using G3D::Vector3;
using G3D::AABox;
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index 91eb00f17c5..3ea18f272ae 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -128,7 +128,7 @@ class UnitAI
virtual void InitializeAI() { if (!me->isDead()) Reset(); }
- virtual void Reset() { };
+ virtual void Reset() { }
// Called when unit is charmed
virtual void OnCharmed(bool apply) = 0;
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 40ab7ebc52e..6d56774e447 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -847,6 +847,7 @@ class RBACData
* @return Success or failure (with reason) to grant the permission
*
* Example Usage:
+ * @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->GrantRole(permissionId) == RBAC_IN_DENIED_LIST)
@@ -870,6 +871,7 @@ class RBACData
* @return Success or failure (with reason) to deny the permission
*
* Example Usage:
+ * @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->DenyRole(permissionId) == RBAC_ID_DOES_NOT_EXISTS)
@@ -894,6 +896,7 @@ class RBACData
* @return Success or failure (with reason) to remove the permission
*
* Example Usage:
+ * @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->RevokeRole(permissionId) == RBAC_OK)
@@ -984,9 +987,6 @@ class RBACData
*
* Given a list of permissions, gets all the inherited permissions
* @param permissions The list of permissions to expand
- *
- * @return new list of permissions containing original permissions and
- * all other pemissions that are linked to the original ones
*/
void ExpandPermissions(RBACPermissionContainer& permissions);
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index cfe93b0cde3..9c347879768 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -28,6 +28,7 @@
#include "DBCEnums.h"
#include "DisableMgr.h"
#include "GameEventMgr.h"
+#include "Garrison.h"
#include "GridNotifiersImpl.h"
#include "Group.h"
#include "Guild.h"
@@ -1161,6 +1162,7 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
SetCriteriaProgress(achievementCriteria, 1, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
@@ -1269,6 +1271,39 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED:
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES:
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER:
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR:
+ case ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER:
+ case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
+ case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING:
+ case ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING:
+ case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON:
+ case ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT:
+ case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS:
break; // Not implemented yet :(
}
@@ -1413,6 +1448,7 @@ bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteria const* achieveme
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
return progress->counter >= 1;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
return progress->counter >= (requiredAmount * 75);
@@ -2492,6 +2528,44 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(ModifierTreeNode const*
if (!unit || unit->GetHealthPct() >= reqValue)
return false;
break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY: // 145
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->PacketInfo.Quality != reqValue)
+ return false;
+
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL: // 146
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->PacketInfo.FollowerLevel < reqValue)
+ return false;
+
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ILVL: // 184
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->GetItemLevel() < reqValue)
+ return false;
+ break;
+ }
default:
break;
}
@@ -2729,6 +2803,74 @@ char const* AchievementGlobalMgr::GetCriteriaTypeString(AchievementCriteriaTypes
return "GUILD_CHALLENGE_TYPE";
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
return "GUILD_CHALLENGE";
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED:
+ return "LFR_DUNGEONS_COMPLETED";
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES:
+ return "LFR_LEAVES";
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER:
+ return "LFR_VOTE_KICKS_INITIATED_BY_PLAYER";
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER:
+ return "LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER";
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR:
+ return "BE_KICKED_FROM_LFR";
+ case ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
+ return "COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
+ return "COMPLETE_SCENARIO_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO:
+ return "COMPLETE_SCENARIO";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
+ return "OWN_BATTLE_PET";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
+ return "OWN_BATTLE_PET_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET:
+ return "CAPTURE_BATTLE_PET";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE:
+ return "WIN_PET_BATTLE";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET:
+ return "LEVEL_BATTLE_PET";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT:
+ return "CAPTURE_BATTLE_PET_CREDIT";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT:
+ return "LEVEL_BATTLE_PET_CREDIT";
+ case ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA:
+ return "ENTER_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA:
+ return "LEAVE_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER:
+ return "COMPLETE_DUNGEON_ENCOUNTER";
+ case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
+ return "PLACE_GARRISON_BUILDING";
+ case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING:
+ return "UPGRADE_GARRISON_BUILDING";
+ case ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING:
+ return "CONSTRUCT_GARRISON_BUILDING";
+ case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON:
+ return "UPGRADE_GARRISON";
+ case ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION:
+ return "START_GARRISON_MISSION";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT:
+ return "COMPLETE_GARRISON_MISSION_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION:
+ return "COMPLETE_GARRISON_MISSION";
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT:
+ return "RECRUIT_GARRISON_FOLLOWER_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT:
+ return "LEARN_GARRISON_BLUEPRINT_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT:
+ return "COMPLETE_GARRISON_SHIPMENT";
+ case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL:
+ return "RAISE_GARRISON_FOLLOWER_ITEM_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL:
+ return "RAISE_GARRISON_FOLLOWER_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY:
+ return "OWN_TOY";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT:
+ return "OWN_TOY_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
+ return "RECRUIT_GARRISON_FOLLOWER";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS:
+ return "OWN_HEIRLOOMS";
}
return "MISSING_TYPE";
}
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index c6c46c48f50..f37526ae71b 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -71,7 +71,7 @@ namespace Trinity
void do_helper(WorldPacket& data, char const* text)
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgtype, LANG_UNIVERSAL, _source, _source, text);
+ packet.Initialize(_msgtype, LANG_UNIVERSAL, _source, _source, text);
packet.Write();
data = packet.Move();
}
@@ -98,7 +98,7 @@ namespace Trinity
snprintf(str, 2048, text, arg1str, arg2str);
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgtype, LANG_UNIVERSAL, _source, _source, str);
+ packet.Initialize(_msgtype, LANG_UNIVERSAL, _source, _source, str);
packet.Write();
data = packet.Move();
}
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h
index 9a65019a390..eb225250a56 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.h
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.h
@@ -106,7 +106,7 @@ class BattlegroundQueue
class SelectionPool
{
public:
- SelectionPool(): PlayerCount(0) { };
+ SelectionPool(): PlayerCount(0) { }
void Init();
bool AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount);
bool KickGroup(uint32 size);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
index 3694c62d663..8b6f16d1ff9 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
@@ -42,7 +42,7 @@ class BattlegroundBFGScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(std::vector<int32>& stats)
+ void BuildObjectivesBlock(std::vector<int32>& stats) override
{
stats.push_back(BasesAssaulted);
stats.push_back(BasesDefended);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundTP.h b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
index b11485d6025..1dfd3801864 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
@@ -42,7 +42,7 @@ class BattlegroundTPScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(std::vector<int32>& stats)
+ void BuildObjectivesBlock(std::vector<int32>& stats) override
{
stats.push_back(FlagCaptures);
stats.push_back(FlagReturns);
diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 04b6eb1b5b1..90c44aa501b 100644
--- a/src/server/game/Chat/Channels/Channel.cpp
+++ b/src/server/game/Chat/Channels/Channel.cpp
@@ -626,10 +626,10 @@ void Channel::Say(ObjectGuid const& guid, std::string const& what, uint32 lang)
WorldPackets::Chat::Chat packet;
if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
- packet.Initalize(CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, _name);
+ packet.Initialize(CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, _name);
else
{
- packet.Initalize(CHAT_MSG_CHANNEL, Language(lang), nullptr, nullptr, what, 0, _name);
+ packet.Initialize(CHAT_MSG_CHANNEL, Language(lang), nullptr, nullptr, what, 0, _name);
packet.SenderGUID = guid;
packet.TargetGUID = guid;
}
@@ -990,32 +990,42 @@ void Channel::MakeVoiceOff(WorldPackets::Channel::ChannelNotify& data, ObjectGui
void Channel::JoinNotify(Player const* player)
{
ObjectGuid const& guid = player->GetGUID();
- WorldPacket data(IsConstant() ? SMSG_USERLIST_ADD : SMSG_USERLIST_UPDATE, 8 + 1 + 1 + 4 + GetName().size());
- data << guid;
- data << uint8(GetPlayerFlags(guid));
- data << uint8(GetFlags());
- data << uint32(GetNumPlayers());
- data << GetName();
if (IsConstant())
- SendToAllButOne(&data, guid);
+ {
+ WorldPackets::Channel::UserlistAdd userlistAdd;
+ userlistAdd.AddedUserGUID = guid;
+ userlistAdd.ChannelFlags = GetFlags();
+ userlistAdd.UserFlags = GetPlayerFlags(guid);
+ userlistAdd.ChannelID = GetChannelId();
+ userlistAdd.ChannelName = GetName();
+ SendToAllButOne(userlistAdd.Write(), guid);
+ }
else
- SendToAll(&data);
+ {
+ WorldPackets::Channel::UserlistUpdate userlistUpdate;
+ userlistUpdate.UpdatedUserGUID = guid;
+ userlistUpdate.ChannelFlags = GetFlags();
+ userlistUpdate.UserFlags = GetPlayerFlags(guid);
+ userlistUpdate.ChannelID = GetChannelId();
+ userlistUpdate.ChannelName = GetName();
+ SendToAll(userlistUpdate.Write());
+ }
}
void Channel::LeaveNotify(Player const* player)
{
ObjectGuid const& guid = player->GetGUID();
- WorldPacket data(SMSG_USERLIST_REMOVE, 8 + 1 + 4 + GetName().size());
- data << guid;
- data << uint8(GetFlags());
- data << uint32(GetNumPlayers());
- data << GetName();
+ WorldPackets::Channel::UserlistRemove userlistRemove;
+ userlistRemove.RemovedUserGUID = guid;
+ userlistRemove.ChannelFlags = GetFlags();
+ userlistRemove.ChannelID = GetChannelId();
+ userlistRemove.ChannelName = GetName();
if (IsConstant())
- SendToAllButOne(&data, guid);
+ SendToAllButOne(userlistRemove.Write(), guid);
else
- SendToAll(&data);
+ SendToAll(userlistRemove.Write());
}
void Channel::SetModerator(ObjectGuid const& guid, bool set)
diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h
index 2cfe0797bce..23cd4e4cada 100644
--- a/src/server/game/Chat/Channels/Channel.h
+++ b/src/server/game/Chat/Channels/Channel.h
@@ -72,7 +72,9 @@ enum ChatNotify
CHAT_NOT_IN_AREA_NOTICE = 0x20, //+ "[%s] You are not in the correct area for this channel."; -- The user is trying to send a chat to a zone specific channel, and they're not physically in that zone.
CHAT_NOT_IN_LFG_NOTICE = 0x21, //+ "[%s] You must be queued in looking for group before joining this channel."; -- The user must be in the looking for group system to join LFG chat channels.
CHAT_VOICE_ON_NOTICE = 0x22, //+ "[%s] Channel voice enabled by %s.";
- CHAT_VOICE_OFF_NOTICE = 0x23 //+ "[%s] Channel voice disabled by %s.";
+ CHAT_VOICE_OFF_NOTICE = 0x23, //+ "[%s] Channel voice disabled by %s.";
+ CHAT_TRIAL_RESTRICTED = 0x24,
+ CHAT_NOT_ALLOWED_IN_CHANNEL = 0x25
};
enum ChannelFlags
@@ -206,7 +208,7 @@ class Channel
void DeVoice(Player const* player);
void JoinNotify(Player const* player);
void LeaveNotify(Player const* player);
- void SetOwnership(bool ownership) { _ownership = ownership; };
+ void SetOwnership(bool ownership) { _ownership = ownership; }
static void CleanOldChannelsInDB();
private:
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index c7952d7758c..ed6aa52da5a 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -201,7 +201,7 @@ void ChatHandler::SendSysMessage(const char *str)
while (char* line = LineFromMessage(pos))
{
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
m_session->SendPacket(packet.Write());
}
@@ -219,7 +219,7 @@ void ChatHandler::SendGlobalSysMessage(const char *str)
while (char* line = LineFromMessage(pos))
{
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
sWorld->SendGlobalMessage(packet.Write());
}
@@ -237,7 +237,7 @@ void ChatHandler::SendGlobalGMSysMessage(const char *str)
while (char* line = LineFromMessage(pos))
{
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
sWorld->SendGlobalGMMessage(packet.Write());
}
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index fc05f0fdc6a..719e539a9c4 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -159,6 +159,12 @@ enum AchievementCriteriaAdditionalCondition
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND = 63, // NYI
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RARITY = 65,
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RACE = 66,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY = 145,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL = 146,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_RARE_MISSION = 147, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_LEVEL = 149, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_MISSION_TYPE = 167, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ILVL = 184,
};
enum AchievementCriteriaFlags
@@ -188,121 +194,169 @@ enum AchievementCriteriaTimedTypes
enum AchievementCriteriaTypes
{
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS = 3, // struct { uint32 itemCount; }
- ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, // you have to complete a daily quest x times in a row
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11,
- ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12,
- ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP = 16,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH = 17,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19,
- ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20,
- ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23,
- ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24,
- ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27,
- ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28,
- ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29,
- ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32,
- ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40,
- ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42,
- ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK = 44,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT = 45,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION = 47,
- ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48,
- ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, /// @todo itemlevel is mentioned in text but not present in dbc
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51,
- ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52,
- ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53,
- ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54,
- ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55,
- ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, /// @todo in some cases map not present, and in some cases need do without die
- ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57,
- ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60,
- ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61,
- ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67,
- ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68,
- ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 = 69,
- ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70,
- ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72,
+ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS = 3, // struct { uint32 itemCount; }
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, // you have to complete a daily quest x times in a row
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11,
+ ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12,
+ ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP = 16,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATH = 17,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19,
+ ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20,
+ ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23,
+ ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27,
+ ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28,
+ ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29,
+ ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30,
+ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32,
+ ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33,
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34,
+ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39,
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40,
+ ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41,
+ ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42,
+ ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK = 44,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT = 45,
+ ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46,
+ ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION = 47,
+ ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48,
+ ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49,
+ ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, /// @todo itemlevel is mentioned in text but not present in dbc
+ ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51,
+ ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52,
+ ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53,
+ ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54,
+ ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55,
+ ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, /// @todo in some cases map not present, and in some cases need do without die
+ ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57,
+ ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60,
+ ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61,
+ ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66,
+ ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67,
+ ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68,
+ ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 = 69,
+ ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70,
+ ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72,
/// @todo 73: Achievements 1515, 1241, 1103 (Name: Mal'Ganis)
- ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN = 74,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76,
- ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77,
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS = 80,
- ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION = 82,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID = 83,
- ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS = 84,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88,
- ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90,
- ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102,
- ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST = 104,
- ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106,
- ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107,
- ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109,
- ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, /// @todo target entry is missing
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113,
- ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115,
- ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
- ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS = 124,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125,
- ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD = 126,
- ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL = 127,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS = 128,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS = 129,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND = 130,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING = 132,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD = 133,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD = 134,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD = 135,
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD = 136,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE = 139 //struct { uint32 count; } Guild Challenge
-};
-
-#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 188
+ ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN = 74,
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76,
+ ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77,
+ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS = 80,
+ ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION = 82,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID = 83,
+ ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS = 84,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86,
+ ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87,
+ ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88,
+ ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89,
+ ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90,
+ ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91,
+ ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93,
+ ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102,
+ ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST = 104,
+ ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106,
+ ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107,
+ ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108,
+ ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109,
+ ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, /// @todo target entry is missing
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112,
+ ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113,
+ ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114,
+ ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115,
+ ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
+ ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS = 124,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125,
+ ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD = 126,
+ ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL = 127,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS = 128,
+ ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS = 129,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND = 130,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING = 132,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD = 133,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD = 134,
+ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD = 135,
+ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD = 136,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE = 139, //struct { uint32 count; } Guild Challenge
+ // 140 unk
+ // 141 unk
+ // 142 unk
+ // 143 unk
+ // 144 unk
+ ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED = 145,
+ ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES = 146,
+ ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER = 147,
+ ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER = 148,
+ ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR = 149,
+ ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK = 150,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT = 151,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO = 152,
+ // ACHIEVEMENT_CRITERIA_TYPE_REACH_SOMETHING_LIKE_AREATRIGGER = 153,
+ // 154
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET = 155,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT = 156,
+ ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET = 157,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE = 158,
+ // 159
+ ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET = 160,
+ ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT = 161, // triggers a quest credit
+ ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT = 162, // triggers a quest credit
+ ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA = 163, // triggers a quest credit
+ ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA = 164, // triggers a quest credit
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER = 165,
+ ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING = 167,
+ ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING = 168,
+ ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING = 169,
+ ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON = 170,
+ ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION = 171,
+ // 172
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT = 173,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION = 174,
+ ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT = 175,
+ // 176
+ // 177
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT = 178,
+ // 179
+ // 180
+ // 181
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT = 182,
+ ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL = 183,
+ ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL = 184,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY = 185,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT = 186,
+ ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER = 187,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS = 189
+};
+
+#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 190
enum AchievementCriteriaTreeOperator
{
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index e1f0c595b5f..540d4cf6d9e 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -60,6 +60,7 @@ static AreaFlagByMapID sAreaFlagByMapID; // for instances wit
static WMOAreaInfoByTripple sWMOAreaInfoByTripple;
DBCStorage <AchievementEntry> sAchievementStore(Achievementfmt);
+DBCStorage <AnimKitEntry> sAnimKitStore(AnimKitfmt);
DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
DBCStorage <ArmorLocationEntry> sArmorLocationStore(ArmorLocationfmt);
DBCStorage <AuctionHouseEntry> sAuctionHouseStore(AuctionHouseEntryfmt);
@@ -369,6 +370,7 @@ void LoadDBCStores(const std::string& dataPath)
}
LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc"/*, &CustomAchievementfmt, &CustomAchievementIndex*/);//19116
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAnimKitStore, dbcPath, "AnimKit.dbc");//19865
LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc");//19116
LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc");//19116
LoadDBC(availableDbcLocales, bad_dbc_files, sArmorLocationStore, dbcPath, "ArmorLocation.dbc");//19116
@@ -881,9 +883,9 @@ void Map2ZoneCoordinates(float& x, float& y, uint32 zone)
std::swap(x, y); // client have map coords swapped
}
-MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapID)
+MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapId, Difficulty* difficulty /*= nullptr*/)
{
- auto itr = sMapDifficultyMap.find(mapID);
+ auto itr = sMapDifficultyMap.find(mapId);
if (itr == sMapDifficultyMap.end())
return nullptr;
@@ -892,14 +894,22 @@ MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapID)
for (auto& p : itr->second)
{
- DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(p.first);
- if (!difficulty)
+ DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(p.first);
+ if (!difficultyEntry)
continue;
- if (difficulty->Flags & DIFFICULTY_FLAG_DEFAULT)
+ if (difficultyEntry->Flags & DIFFICULTY_FLAG_DEFAULT)
+ {
+ if (difficulty)
+ *difficulty = Difficulty(p.first);
+
return p.second;
+ }
}
+ if (difficulty)
+ *difficulty = Difficulty(itr->second.begin()->first);
+
return itr->second.begin()->second;
}
@@ -920,7 +930,7 @@ MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficult
{
DifficultyEntry const* diffEntry = sDifficultyStore.LookupEntry(difficulty);
if (!diffEntry)
- return GetDefaultMapDifficulty(mapId);
+ return GetDefaultMapDifficulty(mapId, &difficulty);
uint32 tmpDiff = difficulty;
MapDifficultyEntry const* mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff));
@@ -929,7 +939,7 @@ MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficult
tmpDiff = diffEntry->FallbackDifficultyID;
diffEntry = sDifficultyStore.LookupEntry(tmpDiff);
if (!diffEntry)
- return GetDefaultMapDifficulty(mapId);
+ return GetDefaultMapDifficulty(mapId, &difficulty);
// pull new data
mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); // we are 10 normal or 25 normal
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index 72c0c35f1cb..5ad47549351 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -66,7 +66,7 @@ void Zone2MapCoordinates(float &x, float &y, uint32 zone);
void Map2ZoneCoordinates(float &x, float &y, uint32 zone);
typedef std::unordered_map<uint32, std::unordered_map<uint32, MapDifficultyEntry const*>> MapDifficultyMap;
-MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapID);
+MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapId, Difficulty* difficulty = nullptr);
MapDifficultyEntry const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty);
@@ -123,6 +123,7 @@ private:
};
extern DBCStorage <AchievementEntry> sAchievementStore;
+extern DBCStorage <AnimKitEntry> sAnimKitStore;
extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
extern DBCStorage <ArmorLocationEntry> sArmorLocationStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 2893ea3df83..f8f140ff02b 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -50,12 +50,12 @@ struct AchievementEntry
uint32 CriteriaTree; // 14
};
-struct AchievementCategoryEntry
+struct AnimKitEntry
{
uint32 ID; // 0
- uint32 Parent; // 1 -1 for main category
- //char* Name_lang; // 2
- //uint32 UIOrder; // 3
+ //uint32 OneShotDuration; // 1
+ //uint32 OneShotStopAnimKitID; // 2
+ //uint32 LowDefAnimKitID; // 3
};
// Temporary define until max depth is found somewhere (adt?)
@@ -494,12 +494,15 @@ struct CriteriaEntry
uint32 ObjectiveId;
// ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31
+ // ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA = 163
+ // ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA = 164
uint32 AreaID;
// ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36
// ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41
// ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42
// ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57
+ // ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY = 185
uint32 ItemID;
// ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38
@@ -544,6 +547,21 @@ struct CriteriaEntry
// ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109
uint32 LootType;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER = 165
+ uint32 DungeonEncounterID;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING = 169
+ uint32 GarrBuildingID;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON = 170
+ uint32 GarrisonLevel;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION = 174
+ uint32 GarrMissionID;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT = 182
+ uint32 CharShipmentContainerID;
} Asset; // 2
uint32 StartEvent; // 3
uint32 StartAsset; // 4
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index e3b474bc27b..a67ec26ed7c 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -25,6 +25,7 @@
char const Achievementfmt[] = "niixsxiixixxiii";
const std::string CustomAchievementfmt = "pppaaaapapaapp";
const std::string CustomAchievementIndex = "ID";
+char const AnimKitfmt[] = "nxxx";
char const AreaTableEntryfmt[] = "iiiniixxxxxxisiiiiixxxxxxxxxx";
char const AreaTriggerEntryfmt[] = "nifffxxxfffffxxxx";
char const ArmorLocationfmt[] = "nfffff";
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index b077f3e6110..e786c3b9c7c 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -412,7 +412,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
joinData.result = LFG_JOIN_NOT_MEET_REQS;
else if (grp)
{
- if (grp->GetMembersCount() > MAXGROUPSIZE)
+ if (grp->GetMembersCount() > MAX_GROUP_SIZE)
joinData.result = LFG_JOIN_TOO_MUCH_MEMBERS;
else
{
diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp
index 97f87a4d814..30e9a587353 100644
--- a/src/server/game/DungeonFinding/LFGQueue.cpp
+++ b/src/server/game/DungeonFinding/LFGQueue.cpp
@@ -323,7 +323,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
LfgRolesMap proposalRoles;
// Check for correct size
- if (check.size() > MAXGROUPSIZE || check.empty())
+ if (check.size() > MAX_GROUP_SIZE || check.empty())
{
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s): Size wrong - Not compatibles", strGuids.c_str());
return LFG_INCOMPATIBLES_WRONG_GROUP_SIZE;
@@ -349,7 +349,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
// Check if more than one LFG group and number of players joining
uint8 numPlayers = 0;
uint8 numLfgGroups = 0;
- for (GuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it)
+ for (GuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAX_GROUP_SIZE; ++it)
{
ObjectGuid guid = *it;
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
@@ -374,8 +374,8 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
}
}
- // Group with less that MAXGROUPSIZE members always compatible
- if (check.size() == 1 && numPlayers != MAXGROUPSIZE)
+ // Group with less that MAX_GROUP_SIZE members always compatible
+ if (check.size() == 1 && numPlayers != MAX_GROUP_SIZE)
{
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) single group. Compatibles", strGuids.c_str());
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());
@@ -396,7 +396,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
return LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS;
}
- if (numPlayers > MAXGROUPSIZE)
+ if (numPlayers > MAX_GROUP_SIZE)
{
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Too much players (%u)", strGuids.c_str(), numPlayers);
SetCompatibles(strGuids, LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS);
@@ -473,7 +473,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
}
// Enough players?
- if (numPlayers != MAXGROUPSIZE)
+ if (numPlayers != MAX_GROUP_SIZE)
{
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Compatibles but not enough players(%u)", strGuids.c_str(), numPlayers);
LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS);
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 815c98c9710..faa458d45dc 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -505,7 +505,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
packet.Info.SuggestedGroupNum = quest->GetSuggestedPlayers();
packet.Info.RewardNextQuest = quest->GetNextQuestInChain();
packet.Info.RewardXPDifficulty = quest->GetXPDifficulty();
- packet.Info.Float10 = quest->Float10; // Unk
+ packet.Info.RewardXPMultiplier = quest->GetXPMultiplier();
packet.Info.Float13 = quest->Float13; // Unk
if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 852269855df..da2257641d5 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -180,7 +180,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
m_stationaryPosition.Relocate(x, y, z, ang);
if (!IsPositionValid())
{
- TC_LOG_ERROR("misc", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", guidlow, name_id, x, y);
+ TC_LOG_ERROR("misc", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", guidlow, GetSpawnId(), name_id, x, y);
return false;
}
@@ -195,13 +195,13 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(name_id);
if (!goinfo)
{
- TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created: non-existing entry in `gameobject_template`. Map: %u (X: %f Y: %f Z: %f)", guidlow, name_id, map->GetId(), x, y, z);
+ TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: non-existing entry in `gameobject_template`. Map: %u (X: %f Y: %f Z: %f)", guidlow, GetSpawnId(), name_id, map->GetId(), x, y, z);
return false;
}
if (goinfo->type == GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT)
{
- TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created: gameobject type GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT cannot be manually created.", guidlow, name_id);
+ TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: gameobject type GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT cannot be manually created.", guidlow, GetSpawnId(), name_id);
return false;
}
@@ -214,7 +214,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
if (goinfo->type >= MAX_GAMEOBJECT_TYPE)
{
- TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created: non-existing GO type '%u' in `gameobject_template`. It will crash client if created.", guidlow, name_id, goinfo->type);
+ TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: non-existing GO type '%u' in `gameobject_template`. It will crash client if created.", guidlow, GetSpawnId(), name_id, goinfo->type);
return false;
}
@@ -310,7 +310,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
break;
}
- if (GameObjectAddon const* addon = sObjectMgr->GetGameObjectAddon(guidlow))
+ if (GameObjectAddon const* addon = sObjectMgr->GetGameObjectAddon(GetSpawnId()))
{
if (addon->InvisibilityValue)
{
@@ -2163,7 +2163,7 @@ void GameObject::SetTransportState(GOState state, uint32 stopFrame /*= 0*/)
m_goValue.Transport.StateUpdateTimer = 0;
m_goValue.Transport.PathProgress = getMSTime();
if (GetGoState() >= GO_STATE_TRANSPORT_STOPPED)
- m_goValue.Transport.StopFrames->at(GetGoState() - GO_STATE_TRANSPORT_STOPPED);
+ m_goValue.Transport.PathProgress += m_goValue.Transport.StopFrames->at(GetGoState() - GO_STATE_TRANSPORT_STOPPED);
SetGoState(GO_STATE_TRANSPORT_ACTIVE);
}
else
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index c2f7718438e..655af613220 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -212,11 +212,16 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
break;
}
- if (!(flags & UPDATEFLAG_LIVING))
- if (WorldObject const* worldObject = dynamic_cast<WorldObject const*>(this))
+ if (WorldObject const* worldObject = dynamic_cast<WorldObject const*>(this))
+ {
+ if (!(flags & UPDATEFLAG_LIVING))
if (!worldObject->m_movementInfo.transport.guid.IsEmpty())
flags |= UPDATEFLAG_TRANSPORT_POSITION;
+ if (worldObject->GetAIAnimKitId() || worldObject->GetMovementAnimKitId() || worldObject->GetMeleeAnimKitId())
+ flags |= UPDATEFLAG_ANIMKITS;
+ }
+
if (flags & UPDATEFLAG_STATIONARY_POSITION)
{
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
@@ -237,14 +242,9 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
}
if (Unit const* unit = ToUnit())
- {
if (unit->GetVictim())
flags |= UPDATEFLAG_HAS_TARGET;
- if (unit->GetAIAnimKitId() || unit->GetMovementAnimKitId() || unit->GetMeleeAnimKitId())
- flags |= UPDATEFLAG_ANIMKITS;
- }
-
ByteBuffer buf(0x400);
buf << uint8(updateType);
buf << GetPackGUID();
@@ -502,10 +502,10 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint32 flags) const
if (AnimKitCreate)
{
- Unit const* unit = ToUnit();
- *data << uint16(unit->GetAIAnimKitId()); // AiID
- *data << uint16(unit->GetMovementAnimKitId()); // MovementID
- *data << uint16(unit->GetMeleeAnimKitId()); // MeleeID
+ WorldObject const* self = static_cast<WorldObject const*>(this);
+ *data << uint16(self->GetAIAnimKitId()); // AiID
+ *data << uint16(self->GetMovementAnimKitId()); // MovementID
+ *data << uint16(self->GetMeleeAnimKitId()); // MeleeID
}
if (Rotation)
@@ -1446,7 +1446,9 @@ void MovementInfo::OutDebug()
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0),
m_name(""), m_isActive(false), m_isWorldObject(isWorldObject), m_zoneScript(NULL),
m_transport(NULL), m_currMap(NULL), m_InstanceId(0),
-m_phaseMask(PHASEMASK_NORMAL), _dbPhase(0), m_notifyflags(0), m_executed_notifies(0)
+m_phaseMask(PHASEMASK_NORMAL), _dbPhase(0), m_notifyflags(0), m_executed_notifies(0),
+m_aiAnimKitId(0), m_movementAnimKitId(0), m_meleeAnimKitId(0)
+
{
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST);
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
@@ -3100,6 +3102,54 @@ ObjectGuid WorldObject::GetTransGUID() const
return ObjectGuid::Empty;
}
+void WorldObject::SetAIAnimKitId(uint16 animKitId)
+{
+ if (m_aiAnimKitId == animKitId)
+ return;
+
+ if (animKitId && !sAnimKitStore.LookupEntry(animKitId))
+ return;
+
+ m_aiAnimKitId = animKitId;
+
+ WorldPacket data(SMSG_SET_AI_ANIM_KIT, 8 + 2);
+ data << GetPackGUID();
+ data << uint16(animKitId);
+ SendMessageToSet(&data, true);
+}
+
+void WorldObject::SetMovementAnimKitId(uint16 animKitId)
+{
+ if (m_movementAnimKitId == animKitId)
+ return;
+
+ if (animKitId && !sAnimKitStore.LookupEntry(animKitId))
+ return;
+
+ m_movementAnimKitId = animKitId;
+
+ WorldPacket data(SMSG_SET_MOVEMENT_ANIM_KIT, 8 + 2);
+ data << GetPackGUID();
+ data << uint16(animKitId);
+ SendMessageToSet(&data, true);
+}
+
+void WorldObject::SetMeleeAnimKitId(uint16 animKitId)
+{
+ if (m_meleeAnimKitId == animKitId)
+ return;
+
+ if (animKitId && !sAnimKitStore.LookupEntry(animKitId))
+ return;
+
+ m_meleeAnimKitId = animKitId;
+
+ WorldPacket data(SMSG_SET_MELEE_ANIM_KIT, 8 + 2);
+ data << GetPackGUID();
+ data << uint16(animKitId);
+ SendMessageToSet(&data, true);
+}
+
void WorldObject::RebuildTerrainSwaps()
{
// Clear all terrain swaps, will be rebuilt below
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index b4b66bd5121..b9a6320a835 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -649,6 +649,13 @@ class WorldObject : public Object, public WorldLocation
virtual float GetStationaryZ() const { return GetPositionZ(); }
virtual float GetStationaryO() const { return GetOrientation(); }
+ uint16 GetAIAnimKitId() const { return m_aiAnimKitId; }
+ void SetAIAnimKitId(uint16 animKitId);
+ uint16 GetMovementAnimKitId() const { return m_movementAnimKitId; }
+ void SetMovementAnimKitId(uint16 animKitId);
+ uint16 GetMeleeAnimKitId() const { return m_meleeAnimKitId; }
+ void SetMeleeAnimKitId(uint16 animKitId);
+
protected:
std::string m_name;
bool m_isActive;
@@ -689,6 +696,10 @@ class WorldObject : public Object, public WorldLocation
bool CanDetect(WorldObject const* obj, bool ignoreStealth) const;
bool CanDetectInvisibilityOf(WorldObject const* obj) const;
bool CanDetectStealthOf(WorldObject const* obj) const;
+
+ uint16 m_aiAnimKitId;
+ uint16 m_movementAnimKitId;
+ uint16 m_meleeAnimKitId;
};
namespace Trinity
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 05d649fe632..c8152e3ac36 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -39,8 +39,8 @@
Pet::Pet(Player* owner, PetType type) :
Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false),
- m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
- m_declinedname(NULL)
+ m_petType(type), m_duration(0), m_loading(false), m_declinedname(NULL),
+ m_groupUpdateMask(0)
{
ASSERT(GetOwner());
@@ -337,8 +337,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
owner->PetSpellInitialize();
- if (owner->GetGroup())
- owner->SetGroupUpdateFlag(GROUP_UPDATE_PET);
+ SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
// TODO: 6.x remove/update pet talents
//owner->SendTalentsInfoData(true);
@@ -1938,6 +1937,21 @@ void Pet::SetDisplayId(uint32 modelId)
if (!isControlled())
return;
+ SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID);
+}
+
+void Pet::SetGroupUpdateFlag(uint32 flag)
+{
+ if (GetOwner()->GetGroup())
+ {
+ m_groupUpdateMask |= flag;
+ GetOwner()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET);
+ }
+}
+
+void Pet::ResetGroupUpdateFlag()
+{
+ m_groupUpdateMask = GROUP_UPDATE_FLAG_PET_NONE;
if (GetOwner()->GetGroup())
- GetOwner()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID);
+ GetOwner()->RemoveGroupUpdateFlag(GROUP_UPDATE_FLAG_PET);
}
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index 494db54208d..70f14fbd7ca 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -134,9 +134,9 @@ class Pet : public Guardian
uint32 m_usedTalentCount;
- uint64 GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; }
- void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); }
- void ResetAuraUpdateMaskForRaid() { m_auraRaidUpdateMask = 0; }
+ uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; }
+ void SetGroupUpdateFlag(uint32 flag);
+ void ResetGroupUpdateFlag();
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
@@ -147,9 +147,9 @@ class Pet : public Guardian
protected:
PetType m_petType;
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
- uint64 m_auraRaidUpdateMask;
bool m_loading;
uint32 m_regenTimer;
+ uint32 m_groupUpdateMask;
DeclinedName *m_declinedname;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index a3a602d2f4a..96e58f41fc6 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -100,6 +100,7 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldStatePackets.h"
+#include "InstancePackets.h"
#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)
@@ -701,7 +702,6 @@ Player::Player(WorldSession* session): Unit(true)
// group is initialized in the reference constructor
SetGroupInvite(NULL);
m_groupUpdateMask = 0;
- m_auraRaidUpdateMask = 0;
m_bPassOnGroupLoot = false;
duel = NULL;
@@ -802,7 +802,7 @@ Player::Player(WorldSession* session): Unit(true)
m_dungeonDifficulty = DIFFICULTY_NORMAL;
m_raidDifficulty = DIFFICULTY_NORMAL_RAID;
m_legacyRaidDifficulty = DIFFICULTY_10_N;
- m_raidMapDifficulty = DIFFICULTY_NORMAL_RAID;
+ m_prevMapDifficulty = DIFFICULTY_NORMAL_RAID;
m_lastPotionId = 0;
_talentMgr = new PlayerTalentInfo();
@@ -887,7 +887,6 @@ Player::Player(WorldSession* session): Unit(true)
_maxPersonalArenaRate = 0;
memset(_voidStorageItems, 0, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*));
- memset(_CUFProfiles, 0, MAX_CUF_PROFILES * sizeof(CUFProfile*));
m_achievementMgr = new AchievementMgr<Player>(this);
m_reputationMgr = new ReputationMgr(this);
@@ -927,9 +926,6 @@ Player::~Player()
for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
delete _voidStorageItems[i];
- for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
- delete _CUFProfiles[i];
-
ClearResurrectRequestData();
sWorld->DecreasePlayerCount();
@@ -1125,10 +1121,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac
UpdateMaxHealth(); // Update max Health (for add bonus from stamina)
SetFullHealth();
if (getPowerType() == POWER_MANA)
- {
- UpdateMaxPower(POWER_MANA); // Update max Mana (for add bonus from intellect)
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
- }
if (getPowerType() == POWER_RUNIC_POWER)
{
@@ -4594,6 +4587,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
CharacterDatabase.CommitTransaction(trans);
sWorld->DeleteCharacterInfo(playerguid);
@@ -7387,7 +7384,11 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
// group update
if (GetGroup())
+ {
SetGroupUpdateFlag(GROUP_UPDATE_FULL);
+ if (Pet* pet = GetPet())
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
+ }
m_zoneUpdateId = newZone;
m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
@@ -7698,23 +7699,23 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
break;
case ITEM_MOD_AGILITY: // modify agility
HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, float(val), apply);
+ ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_STRENGTH: //modify strength
HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STRENGTH, float(val), apply);
+ ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_INTELLECT: //modify intellect
HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_INTELLECT, float(val), apply);
+ ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_SPIRIT: //modify spirit
HandleStatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_SPIRIT, float(val), apply);
+ ApplyStatBuffMod(STAT_SPIRIT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_SPIRIT, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_STAMINA: //modify stamina
HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STAMINA, float(val), apply);
+ ApplyStatBuffMod(STAT_STAMINA, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_DEFENSE_SKILL_RATING:
ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply);
@@ -7847,6 +7848,32 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
case ITEM_MOD_ARCANE_RESISTANCE:
HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
break;
+ case ITEM_MOD_AGI_STR_INT:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ break;
+ case ITEM_MOD_AGI_STR:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ break;
+ case ITEM_MOD_AGI_INT:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ break;
+ case ITEM_MOD_STR_INT:
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ break;
}
}
@@ -17344,18 +17371,19 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
_LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES));
- m_achievementMgr->CheckAllAchievementCriteria(this);
-
_LoadEquipmentSets(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS));
_LoadCUFProfiles(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES));
- std::unique_ptr<Garrison> garrison(new Garrison(this));
+ std::unique_ptr<Garrison> garrison = Trinity::make_unique<Garrison>(this);
if (garrison->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON),
holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS),
- holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS)))
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES)))
_garrison = std::move(garrison);
+ m_achievementMgr->CheckAllAchievementCriteria(this);
return true;
}
@@ -17369,19 +17397,19 @@ void Player::_LoadCUFProfiles(PreparedQueryResult result)
// SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?
Field* fields = result->Fetch();
- uint8 id = fields[0].GetUInt8();
- std::string name = fields[1].GetString();
- uint16 frameHeight = fields[2].GetUInt16();
- uint16 frameWidth = fields[3].GetUInt16();
- uint8 sortBy = fields[4].GetUInt8();
- uint8 healthText = fields[5].GetUInt8();
- uint32 boolOptions = fields[6].GetUInt32();
- uint8 unk146 = fields[7].GetUInt8();
- uint8 unk147 = fields[8].GetUInt8();
- uint8 unk148 = fields[9].GetUInt8();
- uint16 unk150 = fields[10].GetUInt16();
- uint16 unk152 = fields[11].GetUInt16();
- uint16 unk154 = fields[12].GetUInt16();
+ uint8 id = fields[0].GetUInt8();
+ std::string name = fields[1].GetString();
+ uint16 frameHeight = fields[2].GetUInt16();
+ uint16 frameWidth = fields[3].GetUInt16();
+ uint8 sortBy = fields[4].GetUInt8();
+ uint8 healthText = fields[5].GetUInt8();
+ uint32 boolOptions = fields[6].GetUInt32();
+ uint8 topPoint = fields[7].GetUInt8();
+ uint8 bottomPoint = fields[8].GetUInt8();
+ uint8 leftPoint = fields[9].GetUInt8();
+ uint16 topOffset = fields[10].GetUInt16();
+ uint16 bottomOffset = fields[11].GetUInt16();
+ uint16 leftOffset = fields[12].GetUInt16();
if (id > MAX_CUF_PROFILES)
{
@@ -17389,7 +17417,7 @@ void Player::_LoadCUFProfiles(PreparedQueryResult result)
continue;
}
- _CUFProfiles[id] = new CUFProfile(name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154);
+ _CUFProfiles[id] = Trinity::make_unique<CUFProfile>(name, frameHeight, frameWidth, sortBy, healthText, boolOptions, topPoint, bottomPoint, leftPoint, topOffset, bottomOffset, leftOffset);
}
while (result->NextRow());
}
@@ -18557,12 +18585,7 @@ void Player::SetPendingBind(uint32 instanceId, uint32 bindTimer)
void Player::SendRaidInfo()
{
- uint32 counter = 0;
-
- WorldPacket data(SMSG_INSTANCE_INFO, 4);
-
- size_t p_counter = data.wpos();
- data << uint32(counter); // placeholder
+ WorldPackets::Instance::InstanceInfo instanceInfo;
time_t now = time(NULL);
@@ -18573,27 +18596,28 @@ void Player::SendRaidInfo()
if (itr->second.perm)
{
InstanceSave* save = itr->second.save;
- bool isHeroic = save->GetDifficultyID() == DIFFICULTY_10_HC || save->GetDifficultyID() == DIFFICULTY_25_HC;
- uint32 completedEncounters = 0;
+
+ WorldPackets::Instance::InstanceLockInfos lockInfos;
+
+ lockInfos.InstanceID = save->GetInstanceId();
+ lockInfos.MapID = save->GetMapId();
+ lockInfos.DifficultyID = save->GetDifficultyID();
+ lockInfos.TimeRemaining = save->GetResetTime() - now;
+
+ lockInfos.CompletedMask = 0;
if (Map* map = sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId()))
if (InstanceScript* instanceScript = ((InstanceMap*)map)->GetInstanceScript())
- completedEncounters = instanceScript->GetCompletedEncounterMask();
+ lockInfos.CompletedMask = instanceScript->GetCompletedEncounterMask();
+
+ lockInfos.Locked = lockInfos.TimeRemaining <= 0;
+ lockInfos.Extended = false;
- data << uint32(save->GetMapId()); // map id
- data << uint32(save->GetDifficultyID()); // difficulty
- data << uint32(isHeroic); // heroic
- data << uint64(save->GetInstanceId()); // instance id
- data << uint8(1); // expired = 0
- data << uint8(0); // extended = 1
- data << uint32(save->GetResetTime() - now); // reset time
- data << uint32(completedEncounters); // completed encounters mask
- ++counter;
+ instanceInfo.LockList.push_back(lockInfos);
}
}
}
- data.put<uint32>(p_counter, counter);
- GetSession()->SendPacket(&data);
+ GetSession()->SendPacket(instanceInfo.Write());
}
/// convert the player's binds to the group
@@ -19418,13 +19442,13 @@ void Player::_SaveCUFProfiles(SQLTransaction& trans)
stmt->setUInt16(4, _CUFProfiles[i]->FrameWidth);
stmt->setUInt8(5, _CUFProfiles[i]->SortBy);
stmt->setUInt8(6, _CUFProfiles[i]->HealthText);
- stmt->setUInt32(7, _CUFProfiles[i]->BoolOptions.to_ulong()); // 27 of 32 fields used, fits in an int
- stmt->setUInt8(8, _CUFProfiles[i]->Unk146);
- stmt->setUInt8(9, _CUFProfiles[i]->Unk147);
- stmt->setUInt8(10, _CUFProfiles[i]->Unk148);
- stmt->setUInt16(11, _CUFProfiles[i]->Unk150);
- stmt->setUInt16(12, _CUFProfiles[i]->Unk152);
- stmt->setUInt16(13, _CUFProfiles[i]->Unk154);
+ stmt->setUInt32(7, _CUFProfiles[i]->BoolOptions.to_ulong()); // 25 of 32 fields used, fits in an int
+ stmt->setUInt8(8, _CUFProfiles[i]->TopPoint);
+ stmt->setUInt8(9, _CUFProfiles[i]->BottomPoint);
+ stmt->setUInt8(10, _CUFProfiles[i]->LeftPoint);
+ stmt->setUInt16(11, _CUFProfiles[i]->TopOffset);
+ stmt->setUInt16(12, _CUFProfiles[i]->BottomOffset);
+ stmt->setUInt16(13, _CUFProfiles[i]->LeftOffset);
}
trans->Append(stmt);
@@ -19966,10 +19990,10 @@ void Player::SendExplorationExperience(uint32 Area, uint32 Experience)
GetSession()->SendPacket(WorldPackets::Misc::ExplorationExperience(Experience, Area).Write());
}
-void Player::SendDungeonDifficulty()
+void Player::SendDungeonDifficulty(int32 forcedDifficulty /*= -1*/)
{
WorldPackets::Misc::DungeonDifficultySet dungeonDifficultySet;
- dungeonDifficultySet.DifficultyID = GetDungeonDifficultyID();
+ dungeonDifficultySet.DifficultyID = forcedDifficulty == -1 ? GetDungeonDifficultyID() : forcedDifficulty;
GetSession()->SendPacket(dungeonDifficultySet.Write());
}
@@ -20220,7 +20244,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
GetSession()->SendPacket(&data);
if (GetGroup())
- SetGroupUpdateFlag(GROUP_UPDATE_PET);
+ SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET);
}
}
@@ -20259,7 +20283,7 @@ void Player::Say(std::string const& text, Language language, WorldObject const*
sScriptMgr->OnPlayerChat(this, CHAT_MSG_SAY, language, _text);
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_SAY, language, this, this, _text);
+ packet.Initialize(CHAT_MSG_SAY, language, this, this, _text);
SendMessageToSetInRange(packet.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
}
@@ -20269,7 +20293,7 @@ void Player::Yell(std::string const& text, Language language, WorldObject const*
sScriptMgr->OnPlayerChat(this, CHAT_MSG_YELL, language, _text);
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_YELL, language, this, this, _text);
+ packet.Initialize(CHAT_MSG_YELL, language, this, this, _text);
SendMessageToSetInRange(packet.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true);
}
@@ -20279,7 +20303,7 @@ void Player::TextEmote(std::string const& text, WorldObject const* /*= nullptr*/
sScriptMgr->OnPlayerChat(this, CHAT_MSG_EMOTE, LANG_UNIVERSAL, _text);
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text);
+ packet.Initialize(CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text);
SendMessageToSetInRange(packet.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT));
}
@@ -20292,7 +20316,7 @@ void Player::WhisperAddon(std::string const& text, const std::string& prefix, Pl
return;
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_WHISPER, LANG_ADDON, this, this, text, 0, "", DEFAULT_LOCALE, prefix);
+ packet.Initialize(CHAT_MSG_WHISPER, LANG_ADDON, this, this, text, 0, "", DEFAULT_LOCALE, prefix);
receiver->SendDirectMessage(packet.Write());
}
@@ -20309,14 +20333,14 @@ void Player::Whisper(std::string const& text, Language language, Player* target,
sScriptMgr->OnPlayerChat(this, CHAT_MSG_WHISPER, language, _text, target);
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_WHISPER, Language(language), this, this, _text);
+ packet.Initialize(CHAT_MSG_WHISPER, Language(language), this, this, _text);
target->SendDirectMessage(packet.Write());
// rest stuff shouldn't happen in case of addon message
if (isAddonMessage)
return;
- packet.Initalize(CHAT_MSG_WHISPER_INFORM, Language(language), target, target, _text);
+ packet.Initialize(CHAT_MSG_WHISPER_INFORM, Language(language), target, target, _text);
SendDirectMessage(packet.Write());
if (!isAcceptWhispers() && !IsGameMaster() && !target->IsGameMaster())
@@ -22618,11 +22642,20 @@ void Player::SendInitialPacketsAfterAddToMap()
if (GetMap()->IsRaid())
{
- DifficultyEntry const* difficulty = sDifficultyStore.AssertEntry(GetMap()->GetDifficultyID());
- SendRaidDifficulty((difficulty->Flags & DIFFICULTY_FLAG_LEGACY) != 0, GetMap()->GetDifficultyID());
+ m_prevMapDifficulty = GetMap()->GetDifficultyID();
+ DifficultyEntry const* difficulty = sDifficultyStore.AssertEntry(m_prevMapDifficulty);
+ SendRaidDifficulty((difficulty->Flags & DIFFICULTY_FLAG_LEGACY) != 0, m_prevMapDifficulty);
}
else if (GetMap()->IsNonRaidDungeon())
- SendDungeonDifficulty();
+ {
+ m_prevMapDifficulty = GetMap()->GetDifficultyID();
+ SendDungeonDifficulty(m_prevMapDifficulty);
+ }
+ else if (!GetMap()->Instanceable())
+ {
+ DifficultyEntry const* difficulty = sDifficultyStore.AssertEntry(m_prevMapDifficulty);
+ SendRaidDifficulty((difficulty->Flags & DIFFICULTY_FLAG_LEGACY) != 0);
+ }
if (_garrison)
_garrison->SendRemoteInfo();
@@ -22636,9 +22669,8 @@ void Player::SendUpdateToOutOfRangeGroupMembers()
group->UpdatePlayerOutOfRange(this);
m_groupUpdateMask = GROUP_UPDATE_FLAG_NONE;
- m_auraRaidUpdateMask = 0;
if (Pet* pet = GetPet())
- pet->ResetAuraUpdateMaskForRaid();
+ pet->ResetGroupUpdateFlag();
}
void Player::SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8 arg)
@@ -22697,10 +22729,10 @@ void Player::ApplyEquipCooldown(Item* pItem)
GetSpellHistory()->AddCooldown(effectData->SpellID, pItem->GetEntry(), std::chrono::seconds(30));
- WorldPacket data(SMSG_ITEM_COOLDOWN, 12);
- data << pItem->GetGUID();
- data << uint32(effectData->SpellID);
- GetSession()->SendPacket(&data);
+ WorldPackets::Item::ItemCooldown data;
+ data.ItemGuid = pItem->GetGUID();
+ data.SpellID = effectData->SpellID;
+ GetSession()->SendPacket(data.Write());
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index df08a1b30d4..5bae50edb68 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -207,8 +207,9 @@ enum CUFBoolOptions
CUF_DISPLAY_POWER_BAR,
CUF_DISPLAY_BORDER,
CUF_USE_CLASS_COLORS,
- CUF_DISPLAY_NON_BOSS_DEBUFFS,
CUF_DISPLAY_HORIZONTAL_GROUPS,
+ CUF_DISPLAY_NON_BOSS_DEBUFFS,
+ CUF_DYNAMIC_POSITION,
CUF_LOCKED,
CUF_SHOWN,
CUF_AUTO_ACTIVATE_2_PLAYERS,
@@ -222,9 +223,6 @@ enum CUFBoolOptions
CUF_AUTO_ACTIVATE_SPEC_2,
CUF_AUTO_ACTIVATE_PVP,
CUF_AUTO_ACTIVATE_PVE,
- CUF_UNK_145,
- CUF_UNK_156,
- CUF_UNK_157,
// The unks is _LOCKED and _SHOWN and _DYNAMIC, unknown order
@@ -236,32 +234,32 @@ struct CUFProfile
{
CUFProfile() : ProfileName(), BoolOptions() // might want to change default value for options
{
- FrameHeight = 0;
- FrameWidth = 0;
- SortBy = 0;
- HealthText = 0;
- Unk146 = 0;
- Unk147 = 0;
- Unk148 = 0;
- Unk150 = 0;
- Unk152 = 0;
- Unk154 = 0;
+ FrameHeight = 0;
+ FrameWidth = 0;
+ SortBy = 0;
+ HealthText = 0;
+ TopPoint = 0;
+ BottomPoint = 0;
+ LeftPoint = 0;
+ TopOffset = 0;
+ BottomOffset = 0;
+ LeftOffset = 0;
}
CUFProfile(const std::string& name, uint16 frameHeight, uint16 frameWidth, uint8 sortBy, uint8 healthText, uint32 boolOptions,
- uint8 unk146, uint8 unk147, uint8 unk148, uint16 unk150, uint16 unk152, uint16 unk154)
+ uint8 topPoint, uint8 bottomPoint, uint8 leftPoint, uint16 topOffset, uint16 bottomOffset, uint16 leftOffset)
: ProfileName(name), BoolOptions((int)boolOptions)
{
- FrameHeight = frameHeight;
- FrameWidth = frameWidth;
- SortBy = sortBy;
- HealthText = healthText;
- Unk146 = unk146;
- Unk147 = unk147;
- Unk148 = unk148;
- Unk150 = unk150;
- Unk152 = unk152;
- Unk154 = unk154;
+ FrameHeight = frameHeight;
+ FrameWidth = frameWidth;
+ SortBy = sortBy;
+ HealthText = healthText;
+ TopPoint = topPoint;
+ BottomPoint = bottomPoint;
+ LeftPoint = leftPoint;
+ TopOffset = topOffset;
+ BottomOffset = bottomOffset;
+ LeftOffset = leftOffset;
}
std::string ProfileName;
@@ -270,15 +268,15 @@ struct CUFProfile
uint8 SortBy;
uint8 HealthText;
- // LeftAlign, TopAlight, BottomAllign (unk order)
- uint8 Unk146;
- uint8 Unk147;
- uint8 Unk148;
+ // LeftAlign, TopAlight, BottomAlign
+ uint8 TopPoint;
+ uint8 BottomPoint;
+ uint8 LeftPoint;
- // LeftOffset, TopOffset and BottomOffset (unk order)
- uint16 Unk150;
- uint16 Unk152;
- uint16 Unk154;
+ // LeftOffset, TopOffset and BottomOffset
+ uint16 TopOffset;
+ uint16 BottomOffset;
+ uint16 LeftOffset;
std::bitset<CUF_BOOL_OPTIONS_COUNT> BoolOptions;
@@ -486,9 +484,9 @@ struct Runes
struct EnchantDuration
{
- EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) { };
+ EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) { }
EnchantDuration(Item* _item, EnchantmentSlot _slot, uint32 _leftduration) : item(_item), slot(_slot),
- leftduration(_leftduration){ ASSERT(item); };
+ leftduration(_leftduration){ ASSERT(item); }
Item* item;
EnchantmentSlot slot;
@@ -989,6 +987,8 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_GARRISON,
PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS,
PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS,
+ PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS,
+ PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES,
MAX_PLAYER_LOGIN_QUERY
};
@@ -1737,8 +1737,9 @@ class Player : public Unit, public GridObject<Player>
void AddTimedQuest(uint32 questId) { m_timedquests.insert(questId); }
void RemoveTimedQuest(uint32 questId) { m_timedquests.erase(questId); }
- void SaveCUFProfile(uint8 id, CUFProfile* profile) { delete _CUFProfiles[id]; _CUFProfiles[id] = profile; } ///> Replaces a CUF profile at position 0-4
- CUFProfile* GetCUFProfile(uint8 id) const { return _CUFProfiles[id]; } ///> Retrieves a CUF profile at position 0-4
+ void SaveCUFProfile(uint8 id, std::nullptr_t) { _CUFProfiles[id] = nullptr; } ///> Empties a CUF profile at position 0-4
+ void SaveCUFProfile(uint8 id, std::unique_ptr<CUFProfile> profile) { _CUFProfiles[id] = std::move(profile); } ///> Replaces a CUF profile at position 0-4
+ CUFProfile* GetCUFProfile(uint8 id) const { return _CUFProfiles[id].get(); } ///> Retrieves a CUF profile at position 0-4
uint8 GetCUFProfilesCount() const
{
uint8 count = 0;
@@ -2056,7 +2057,6 @@ class Player : public Unit, public GridObject<Player>
uint32 GetSpellByProto(ItemTemplate* proto);
float GetHealthBonusFromStamina();
- float GetManaBonusFromIntellect();
bool UpdateStats(Stats stat) override;
bool UpdateAllStats() override;
@@ -2132,7 +2132,7 @@ class Player : public Unit, public GridObject<Player>
void SendAutoRepeatCancel(Unit* target);
void SendExplorationExperience(uint32 Area, uint32 Experience);
- void SendDungeonDifficulty();
+ void SendDungeonDifficulty(int32 forcedDifficulty = -1);
void SendRaidDifficulty(bool legacy, int32 forcedDifficulty = -1);
void ResetInstances(uint8 method, bool isRaid, bool isLegacy);
void SendResetInstanceSuccess(uint32 MapId);
@@ -2143,7 +2143,7 @@ class Player : public Unit, public GridObject<Player>
bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); }
void UpdateUnderwaterState(Map* m, float x, float y, float z) override;
- void SendMessageToSet(WorldPacket const* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); };// overwrite Object::SendMessageToSet
+ void SendMessageToSet(WorldPacket const* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); }// overwrite Object::SendMessageToSet
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) override; // overwrite Object::SendMessageToSetInRange
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool own_team_only);
void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) override;
@@ -2522,8 +2522,7 @@ class Player : public Unit, public GridObject<Player>
uint8 GetSubGroup() const { return m_group.getSubGroup(); }
uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; }
void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; }
- uint64 GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; }
- void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); }
+ void RemoveGroupUpdateFlag(uint32 flag) { m_groupUpdateMask &= ~flag; }
Player* GetNextRandomRaidMember(float radius);
PartyResult CanUninviteFromGroup(ObjectGuid guidMember = ObjectGuid::Empty) const;
@@ -2761,7 +2760,7 @@ class Player : public Unit, public GridObject<Player>
Difficulty m_dungeonDifficulty;
Difficulty m_raidDifficulty;
Difficulty m_legacyRaidDifficulty;
- Difficulty m_raidMapDifficulty;
+ Difficulty m_prevMapDifficulty;
uint32 m_atLoginFlags;
@@ -2889,7 +2888,6 @@ class Player : public Unit, public GridObject<Player>
GroupReference m_originalGroup;
Group* m_groupInvite;
uint32 m_groupUpdateMask;
- uint64 m_auraRaidUpdateMask;
bool m_bPassOnGroupLoot;
// last used pet number (for BG's)
@@ -2912,7 +2910,7 @@ class Player : public Unit, public GridObject<Player>
uint8 m_grantableLevels;
- CUFProfile* _CUFProfiles[MAX_CUF_PROFILES];
+ std::array<std::unique_ptr<CUFProfile>, MAX_CUF_PROFILES> _CUFProfiles = {};
private:
// internal common parts for CanStore/StoreItem functions
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 7034f7fbdc5..f449cec1eef 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -231,7 +231,7 @@ void Transport::Update(uint32 diff)
sScriptMgr->OnTransportUpdate(this, diff);
}
-void Transport::DelayedUpdate(uint32 diff)
+void Transport::DelayedUpdate(uint32 /*diff*/)
{
if (GetKeyFrames().size() <= 1)
return;
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index e9af35ff952..526d2b020e1 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -117,7 +117,6 @@ bool Player::UpdateStats(Stats stat)
UpdateMaxHealth();
break;
case STAT_INTELLECT:
- UpdateMaxPower(POWER_MANA);
UpdateAllSpellCritChances();
UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently
break;
@@ -266,17 +265,6 @@ float Player::GetHealthBonusFromStamina()
return stamina * ratio;
}
-float Player::GetManaBonusFromIntellect()
-{
- // Taken from PaperDollFrame.lua - 4.3.4.15595
- float intellect = GetStat(STAT_INTELLECT);
-
- float baseInt = std::min(20.0f, intellect);
- float moreInt = intellect - baseInt;
-
- return baseInt + (moreInt * 15.0f);
-}
-
void Player::UpdateMaxHealth()
{
UnitMods unitMod = UNIT_MOD_HEALTH;
@@ -293,11 +281,9 @@ void Player::UpdateMaxPower(Powers power)
{
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float bonusPower = (power == POWER_MANA && GetCreatePowers(power) > 0) ? GetManaBonusFromIntellect() : 0;
-
float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
+ value += GetModifierValue(unitMod, TOTAL_VALUE);
value *= GetModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, uint32(value));
@@ -746,10 +732,6 @@ void Player::UpdateManaRegen()
// Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen
spirit_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA);
- // SpiritRegen(SPI, INT, LEVEL) = (0.001 + (SPI x sqrt(INT) x BASE_REGEN[LEVEL])) x 5
- if (GetStat(STAT_INTELLECT) > 0.0f)
- spirit_regen *= std::sqrt(GetStat(STAT_INTELLECT));
-
// CombatRegen = 5% of Base Mana
float base_regen = GetCreateMana() * 0.01f + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 7ae20779fa7..490c31e683c 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -237,6 +237,7 @@ Unit::Unit(bool isWorldObject) :
for (uint8 i = 0; i < UNIT_MOD_END; ++i)
{
m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
+ m_auraModifiersGroup[i][BASE_PCT_EXCLUDE_CREATE] = 100.0f;
m_auraModifiersGroup[i][BASE_PCT] = 1.0f;
m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f;
m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
@@ -284,10 +285,6 @@ Unit::Unit(bool isWorldObject) :
_oldFactionId = 0;
_isWalkingBeforeCharm = false;
-
- _aiAnimKitId = 0;
- _movementAnimKitId = 0;
- _meleeAnimKitId = 0;
}
////////////////////////////////////////////////////////////
@@ -4822,50 +4819,29 @@ void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVict
victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpell, amount, procAura);
}
-void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo)
+void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* info)
{
- AuraEffect const* aura = pInfo->auraEff;
+ AuraEffect const* aura = info->auraEff;
+ WorldPackets::CombatLog::SpellPeriodicAuraLog data;
+ data.TargetGUID = GetGUID();
+ data.CasterGUID = aura->GetCasterGUID();
+ data.SpellID = aura->GetId();
- WorldPacket data(SMSG_SPELL_PERIODIC_AURA_LOG, 30);
- data << GetPackGUID();
- data << aura->GetCasterGUID().WriteAsPacked();
- data << uint32(aura->GetId()); // spellId
- data << uint32(1); // count
- data << uint32(aura->GetAuraType()); // auraId
- switch (aura->GetAuraType())
- {
- case SPELL_AURA_PERIODIC_DAMAGE:
- case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
- data << uint32(pInfo->damage); // damage
- data << uint32(pInfo->overDamage); // overkill?
- data << uint32(aura->GetSpellInfo()->GetSchoolMask());
- data << uint32(pInfo->absorb); // absorb
- data << uint32(pInfo->resist); // resist
- data << uint8(pInfo->critical); // new 3.1.2 critical tick
- break;
- case SPELL_AURA_PERIODIC_HEAL:
- case SPELL_AURA_OBS_MOD_HEALTH:
- data << uint32(pInfo->damage); // damage
- data << uint32(pInfo->overDamage); // overheal
- data << uint32(pInfo->absorb); // absorb
- data << uint8(pInfo->critical); // new 3.1.2 critical tick
- break;
- case SPELL_AURA_OBS_MOD_POWER:
- case SPELL_AURA_PERIODIC_ENERGIZE:
- data << uint32(aura->GetMiscValue()); // power type
- data << uint32(pInfo->damage); // damage
- break;
- case SPELL_AURA_PERIODIC_MANA_LEECH:
- data << uint32(aura->GetMiscValue()); // power type
- data << uint32(pInfo->damage); // amount
- data << float(pInfo->multiplier); // gain multiplier
- break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::SendPeriodicAuraLog: unknown aura %u", uint32(aura->GetAuraType()));
- return;
- }
+ /// @todo: should send more logs in one packet when multistrike
+ WorldPackets::CombatLog::SpellPeriodicAuraLog::SpellLogEffect spellLogEffect;
+ spellLogEffect.Effect = aura->GetAuraType();
+ spellLogEffect.Amount = info->damage;
+ spellLogEffect.OverHealOrKill = info->overDamage;
+ spellLogEffect.SchoolMaskOrPower = aura->GetSpellInfo()->GetSchoolMask();
+ spellLogEffect.AbsorbedOrAmplitude = info->absorb;
+ spellLogEffect.Resisted = info->resist;
+ spellLogEffect.Crit = info->critical;
+ spellLogEffect.Multistrike = false; // NYI
+ /// @todo: implement debug info
- SendMessageToSet(&data, true);
+ data.Effects.push_back(spellLogEffect);
+
+ SendMessageToSet(data.Write(), true);
}
void Unit::SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo)
@@ -6957,15 +6933,11 @@ void Unit::setPowerType(Powers new_powertype)
if (ToPlayer()->GetGroup())
ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POWER_TYPE);
}
- else if (Pet* pet = ToCreature()->ToPet())
+ /*else if (Pet* pet = ToCreature()->ToPet()) TODO 6.x
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE);
- }
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE);
+ }*/
float powerMultiplier = 1.0f;
if (!IsPet())
@@ -11245,6 +11217,7 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
switch (modifierType)
{
case BASE_VALUE:
+ case BASE_PCT_EXCLUDE_CREATE:
case TOTAL_VALUE:
m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount;
break;
@@ -11320,7 +11293,8 @@ float Unit::GetTotalStatValue(Stats stat) const
return 0.0f;
// value = ((base_value * base_pct) + total_value) * total_pct
- float value = m_auraModifiersGroup[unitMod][BASE_VALUE] + GetCreateStat(stat);
+ float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f));
+ value += GetCreateStat(stat);
value *= m_auraModifiersGroup[unitMod][BASE_PCT];
value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
@@ -11339,7 +11313,7 @@ float Unit::GetTotalAuraModValue(UnitMods unitMod) const
if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
return 0.0f;
- float value = m_auraModifiersGroup[unitMod][BASE_VALUE];
+ float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f));
value *= m_auraModifiersGroup[unitMod][BASE_PCT];
value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
@@ -11470,11 +11444,7 @@ void Unit::SetHealth(uint32 val)
else if (Pet* pet = ToCreature()->ToPet())
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP);
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP);
}
}
@@ -11495,11 +11465,7 @@ void Unit::SetMaxHealth(uint32 val)
else if (Pet* pet = ToCreature()->ToPet())
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP);
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP);
}
if (val < health)
@@ -11551,15 +11517,11 @@ void Unit::SetPower(Powers power, int32 val)
if (player->GetGroup())
player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER);
}
- else if (Pet* pet = ToCreature()->ToPet())
+ /*else if (Pet* pet = ToCreature()->ToPet()) TODO 6.x
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
- }
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
+ }*/
}
void Unit::SetMaxPower(Powers power, int32 val)
@@ -11577,15 +11539,11 @@ void Unit::SetMaxPower(Powers power, int32 val)
if (ToPlayer()->GetGroup())
ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER);
}
- else if (Pet* pet = ToCreature()->ToPet())
+ /*else if (Pet* pet = ToCreature()->ToPet()) TODO 6.x
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
- }
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
+ }*/
if (val < cur_power)
SetPower(power, val);
@@ -13007,23 +12965,13 @@ void Unit::UpdateAuraForGroup(uint8 slot)
if (Player* player = ToPlayer())
{
if (player->GetGroup())
- {
player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_AURAS);
- player->SetAuraUpdateMaskForRaid(slot);
- }
}
else if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsPet())
{
Pet* pet = ((Pet*)this);
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- {
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS);
- pet->SetAuraUpdateMaskForRaid(slot);
- }
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS);
}
}
@@ -13401,45 +13349,6 @@ void Unit::SendDurabilityLoss(Player* receiver, uint32 percent)
receiver->GetSession()->SendPacket(packet.Write());
}
-void Unit::SetAIAnimKitId(uint16 animKitId)
-{
- if (_aiAnimKitId == animKitId)
- return;
-
- _aiAnimKitId = animKitId;
-
- WorldPacket data(SMSG_SET_AI_ANIM_KIT, 8 + 2);
- data << GetPackGUID();
- data << uint16(animKitId);
- SendMessageToSet(&data, true);
-}
-
-void Unit::SetMovementAnimKitId(uint16 animKitId)
-{
- if (_movementAnimKitId == animKitId)
- return;
-
- _movementAnimKitId = animKitId;
-
- WorldPacket data(SMSG_SET_MOVEMENT_ANIM_KIT, 8 + 2);
- data << GetPackGUID();
- data << uint16(animKitId);
- SendMessageToSet(&data, true);
-}
-
-void Unit::SetMeleeAnimKitId(uint16 animKitId)
-{
- if (_meleeAnimKitId == animKitId)
- return;
-
- _meleeAnimKitId = animKitId;
-
- WorldPacket data(SMSG_SET_MELEE_ANIM_KIT, 8 + 2);
- data << GetPackGUID();
- data << uint16(animKitId);
- SendMessageToSet(&data, true);
-}
-
void Unit::PlayOneShotAnimKit(uint16 animKitId)
{
WorldPacket data(SMSG_PLAY_ONE_SHOT_ANIM_KIT, 7+2);
@@ -16401,7 +16310,7 @@ void Unit::Whisper(std::string const& text, Language language, Player* target, b
LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex();
WorldPackets::Chat::Chat packet;
- packet.Initalize(isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, language, this, target, text, 0, "", locale);
+ packet.Initialize(isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, language, this, target, text, 0, "", locale);
target->SendDirectMessage(packet.Write());
}
@@ -16448,7 +16357,7 @@ void Unit::Whisper(uint32 textId, Player* target, bool isBossWhisper /*= false*/
LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex();
WorldPackets::Chat::Chat packet;
- packet.Initalize(isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, LANG_UNIVERSAL, this, target, DB2Manager::GetBroadcastTextValue(bct, locale, getGender()), 0, "", locale);
+ packet.Initialize(isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, LANG_UNIVERSAL, this, target, DB2Manager::GetBroadcastTextValue(bct, locale, getGender()), 0, "", locale);
target->SendDirectMessage(packet.Write());
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 252f044b4ef..538bcea9eba 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -330,13 +330,6 @@ enum UnitRename
#define MAX_AGGRO_RESET_TIME 10 // in seconds
#define MAX_AGGRO_RADIUS 45.0f // yards
-enum Swing
-{
- NOSWING = 0,
- SINGLEHANDEDSWING = 1,
- TWOHANDEDSWING = 2
-};
-
enum VictimState
{
VICTIMSTATE_INTACT = 0, // set when attacker misses
@@ -418,7 +411,7 @@ namespace Movement
}
typedef std::list<Unit*> UnitList;
-typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
+typedef std::list<std::pair<Aura*, uint8>> DispelChargesList;
struct SpellImmune
{
@@ -431,10 +424,11 @@ typedef std::list<SpellImmune> SpellImmuneList;
enum UnitModifierType
{
BASE_VALUE = 0,
- BASE_PCT = 1,
- TOTAL_VALUE = 2,
- TOTAL_PCT = 3,
- MODIFIER_TYPE_END = 4
+ BASE_PCT_EXCLUDE_CREATE = 1, // percent modifier affecting all stat values from auras and gear but not player base for level
+ BASE_PCT = 2,
+ TOTAL_VALUE = 3,
+ TOTAL_PCT = 4,
+ MODIFIER_TYPE_END = 5
};
enum WeaponDamageRange
@@ -443,13 +437,6 @@ enum WeaponDamageRange
MAXDAMAGE
};
-enum DamageTypeToSchool
-{
- RESISTANCE,
- DAMAGE_DEALT,
- DAMAGE_TAKEN
-};
-
enum AuraRemoveMode
{
AURA_REMOVE_NONE = 0,
@@ -1489,12 +1476,6 @@ class Unit : public WorldObject
MountCapabilityEntry const* GetMountCapability(uint32 mountType) const;
void SendDurabilityLoss(Player* receiver, uint32 percent);
- uint16 GetAIAnimKitId() const { return _aiAnimKitId; }
- void SetAIAnimKitId(uint16 animKitId);
- uint16 GetMovementAnimKitId() const { return _movementAnimKitId; }
- void SetMovementAnimKitId(uint16 animKitId);
- uint16 GetMeleeAnimKitId() const { return _meleeAnimKitId; }
- void SetMeleeAnimKitId(uint16 animKitId);
void PlayOneShotAnimKit(uint16 animKitId);
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
@@ -1986,7 +1967,7 @@ class Unit : public WorldObject
void TauntApply(Unit* victim);
void TauntFadeOut(Unit* taunter);
ThreatManager& getThreatManager() { return m_ThreatManager; }
- void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); };
+ void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); }
void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ }
HostileRefManager& getHostileRefManager() { return m_HostileRefManager; }
@@ -2346,10 +2327,6 @@ class Unit : public WorldObject
time_t _lastDamagedTime; // Part of Evade mechanics
- uint16 _aiAnimKitId;
- uint16 _movementAnimKitId;
- uint16 _meleeAnimKitId;
-
SpellHistory* _spellHistory;
};
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index 5edd6f3da2d..6f3b5c63180 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -98,7 +98,7 @@ class GameEventMgr
{
private:
GameEventMgr();
- ~GameEventMgr() { };
+ ~GameEventMgr() { }
public:
static GameEventMgr* instance()
diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp
index 3087de37472..749ebb562c5 100644
--- a/src/server/game/Garrison/Garrison.cpp
+++ b/src/server/game/Garrison/Garrison.cpp
@@ -25,7 +25,8 @@ Garrison::Garrison(Player* owner) : _owner(owner), _siteLevel(nullptr), _followe
{
}
-bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings)
+bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings,
+ PreparedQueryResult followers, PreparedQueryResult abilities)
{
if (!garrison)
return false;
@@ -76,6 +77,59 @@ bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blue
} while (buildings->NextRow());
}
+ // 0 1 2 3 4 5 6 7 8 9
+ // SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status FROM character_garrison_followers WHERE guid = ?
+ if (followers)
+ {
+ do
+ {
+ Field* fields = followers->Fetch();
+
+ uint64 dbId = fields[0].GetUInt64();
+ uint32 followerId = fields[1].GetUInt32();
+ if (!sGarrFollowerStore.LookupEntry(followerId))
+ continue;
+
+ _followerIds.insert(followerId);
+ Follower& follower = _followers[dbId];
+ follower.PacketInfo.DbID = dbId;
+ follower.PacketInfo.GarrFollowerID = followerId;
+ follower.PacketInfo.Quality = fields[2].GetUInt32();
+ follower.PacketInfo.FollowerLevel = fields[3].GetUInt32();
+ follower.PacketInfo.ItemLevelWeapon = fields[4].GetUInt32();
+ follower.PacketInfo.ItemLevelArmor = fields[5].GetUInt32();
+ follower.PacketInfo.Xp = fields[6].GetUInt32();
+ follower.PacketInfo.CurrentBuildingID = fields[7].GetUInt32();
+ follower.PacketInfo.CurrentMissionID = fields[8].GetUInt32();
+ follower.PacketInfo.FollowerStatus = fields[9].GetUInt32();
+ if (!sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID))
+ follower.PacketInfo.CurrentBuildingID = 0;
+
+ //if (!sGarrMissionStore.LookupEntry(follower.PacketInfo.CurrentMissionID))
+ // follower.PacketInfo.CurrentMissionID = 0;
+
+ } while (followers->NextRow());
+
+ if (abilities)
+ {
+ do
+ {
+ Field* fields = abilities->Fetch();
+ uint64 dbId = fields[0].GetUInt64();
+ GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(fields[1].GetUInt32());
+
+ if (!ability)
+ continue;
+
+ auto itr = _followers.find(dbId);
+ if (itr == _followers.end())
+ continue;
+
+ itr->second.PacketInfo.AbilityID.push_back(ability);
+ } while (abilities->NextRow());
+ }
+ }
+
return true;
}
@@ -93,6 +147,10 @@ void Garrison::SaveToDB(SQLTransaction& trans)
stmt->setUInt64(0, _owner->GetGUID().GetCounter());
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON);
stmt->setUInt64(0, _owner->GetGUID().GetCounter());
stmt->setUInt32(1, _siteLevel->ID);
@@ -121,6 +179,35 @@ void Garrison::SaveToDB(SQLTransaction& trans)
trans->Append(stmt);
}
}
+
+ for (auto const& p : _followers)
+ {
+ Follower const& follower = p.second;
+ uint8 index = 0;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS);
+ stmt->setUInt64(index++, follower.PacketInfo.DbID);
+ stmt->setUInt64(index++, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(index++, follower.PacketInfo.GarrFollowerID);
+ stmt->setUInt32(index++, follower.PacketInfo.Quality);
+ stmt->setUInt32(index++, follower.PacketInfo.FollowerLevel);
+ stmt->setUInt32(index++, follower.PacketInfo.ItemLevelWeapon);
+ stmt->setUInt32(index++, follower.PacketInfo.ItemLevelArmor);
+ stmt->setUInt32(index++, follower.PacketInfo.Xp);
+ stmt->setUInt32(index++, follower.PacketInfo.CurrentBuildingID);
+ stmt->setUInt32(index++, follower.PacketInfo.CurrentMissionID);
+ stmt->setUInt32(index++, follower.PacketInfo.FollowerStatus);
+ trans->Append(stmt);
+
+ uint8 slot = 0;
+ for (GarrAbilityEntry const* ability : follower.PacketInfo.AbilityID)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES);
+ stmt->setUInt64(0, follower.PacketInfo.DbID);
+ stmt->setUInt32(1, ability->ID);
+ stmt->setUInt8(2, slot++);
+ trans->Append(stmt);
+ }
+ }
}
bool Garrison::Create(uint32 garrSiteId)
@@ -348,15 +435,17 @@ void Garrison::AddFollower(uint32 garrFollowerId)
{
WorldPackets::Garrison::GarrisonAddFollowerResult addFollowerResult;
GarrFollowerEntry const* followerEntry = sGarrFollowerStore.LookupEntry(garrFollowerId);
- if (_followers.count(garrFollowerId) || !followerEntry)
+ if (_followerIds.count(garrFollowerId) || !followerEntry)
{
addFollowerResult.Result = GARRISON_GENERIC_UNKNOWN_ERROR;
_owner->SendDirectMessage(addFollowerResult.Write());
return;
}
- Follower& follower = _followers[garrFollowerId];
- follower.PacketInfo.DbID = sGarrisonMgr.GenerateFollowerDbId();
+ _followerIds.insert(garrFollowerId);
+ uint64 dbId = sGarrisonMgr.GenerateFollowerDbId();
+ Follower& follower = _followers[dbId];
+ follower.PacketInfo.DbID = dbId;
follower.PacketInfo.GarrFollowerID = garrFollowerId;
follower.PacketInfo.Quality = followerEntry->Quality; // TODO: handle magic upgrades
follower.PacketInfo.FollowerLevel = followerEntry->Level;
@@ -370,6 +459,17 @@ void Garrison::AddFollower(uint32 garrFollowerId)
addFollowerResult.Follower = follower.PacketInfo;
_owner->SendDirectMessage(addFollowerResult.Write());
+
+ _owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER, follower.PacketInfo.DbID);
+}
+
+Garrison::Follower const* Garrison::GetFollower(uint64 dbId) const
+{
+ auto itr = _followers.find(dbId);
+ if (itr != _followers.end())
+ return &itr->second;
+
+ return nullptr;
}
void Garrison::SendInfo()
@@ -481,7 +581,7 @@ GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32
if (!_owner->HasCurrency(building->CostCurrencyID, building->CostCurrencyAmount))
return GARRISON_ERROR_NOT_ENOUGH_CURRENCY;
- if (!_owner->HasEnoughMoney(uint64(building->CostMoney * GOLD)))
+ if (!_owner->HasEnoughMoney(uint64(building->CostMoney) * GOLD))
return GARRISON_ERROR_NOT_ENOUGH_GOLD;
// New building cannot replace another building currently under construction
@@ -583,3 +683,8 @@ bool Garrison::Building::CanActivate() const
return false;
}
+
+uint32 Garrison::Follower::GetItemLevel() const
+{
+ return (PacketInfo.ItemLevelWeapon + PacketInfo.ItemLevelArmor) / 2;
+}
diff --git a/src/server/game/Garrison/Garrison.h b/src/server/game/Garrison/Garrison.h
index 348998b276c..71d67a1b6b5 100644
--- a/src/server/game/Garrison/Garrison.h
+++ b/src/server/game/Garrison/Garrison.h
@@ -43,7 +43,8 @@ enum GarrisonAbilityFlags
GARRISON_ABILITY_CANNOT_ROLL = 0x02,
GARRISON_ABILITY_HORDE_ONLY = 0x04,
GARRISON_ABILITY_ALLIANCE_ONLY = 0x08,
- GARRISON_ABILITY_FLAG_CANNOT_REMOVE = 0x10
+ GARRISON_ABILITY_FLAG_CANNOT_REMOVE = 0x10,
+ GARRISON_ABILITY_FLAG_EXCLUSIVE = 0x20
};
enum GarrisonError
@@ -99,12 +100,15 @@ public:
struct Follower
{
+ uint32 GetItemLevel() const;
+
WorldPackets::Garrison::GarrisonFollower PacketInfo;
};
explicit Garrison(Player* owner);
- bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings);
+ bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings,
+ PreparedQueryResult followers, PreparedQueryResult abilities);
void SaveToDB(SQLTransaction& trans);
bool Create(uint32 garrSiteId);
@@ -128,6 +132,7 @@ public:
// Followers
void AddFollower(uint32 garrFollowerId);
+ Follower const* GetFollower(uint64 dbId) const;
void SendInfo();
void SendRemoteInfo() const;
@@ -148,6 +153,7 @@ private:
std::unordered_map<uint32 /*garrPlotInstanceId*/, Plot> _plots;
std::unordered_set<uint32 /*garrBuildingId*/> _knownBuildings;
std::unordered_map<uint64 /*dbId*/, Follower> _followers;
+ std::unordered_set<uint32> _followerIds;
};
#endif // Garrison_h__
diff --git a/src/server/game/Garrison/GarrisonMap.cpp b/src/server/game/Garrison/GarrisonMap.cpp
index 7316504d185..b9cf63140b4 100644
--- a/src/server/game/Garrison/GarrisonMap.cpp
+++ b/src/server/game/Garrison/GarrisonMap.cpp
@@ -97,7 +97,7 @@ void GarrisonGridLoader::Visit(CreatureMapType& /*m*/)
}
GarrisonMap::GarrisonMap(uint32 id, time_t expiry, uint32 instanceId, Map* parent, ObjectGuid const& owner)
- : Map(id, expiry, instanceId, DIFFICULTY_NORMAL, parent), _owner(owner)
+ : Map(id, expiry, instanceId, DIFFICULTY_NORMAL, parent), _owner(owner), _loadingPlayer(nullptr)
{
GarrisonMap::InitVisibilityDistance();
}
@@ -112,6 +112,9 @@ void GarrisonMap::LoadGridObjects(NGridType* grid, Cell const& cell)
Garrison* GarrisonMap::GetGarrison()
{
+ if (_loadingPlayer)
+ return _loadingPlayer->GetGarrison();
+
if (Player* owner = ObjectAccessor::FindConnectedPlayer(_owner))
return owner->GetGarrison();
@@ -124,3 +127,16 @@ void GarrisonMap::InitVisibilityDistance()
m_VisibleDistance = World::GetMaxVisibleDistanceInBGArenas();
m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInBGArenas();
}
+
+bool GarrisonMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
+{
+ if (player->GetGUID() == _owner)
+ _loadingPlayer = player;
+
+ bool result = Map::AddPlayerToMap(player, initPlayer);
+
+ if (player->GetGUID() == _owner)
+ _loadingPlayer = nullptr;
+
+ return result;
+}
diff --git a/src/server/game/Garrison/GarrisonMap.h b/src/server/game/Garrison/GarrisonMap.h
index 0ccc77b05fa..5f5c9b134b7 100644
--- a/src/server/game/Garrison/GarrisonMap.h
+++ b/src/server/game/Garrison/GarrisonMap.h
@@ -21,6 +21,7 @@
#include "Map.h"
class Garrison;
+class Player;
class GarrisonMap : public Map
{
@@ -32,8 +33,11 @@ public:
void InitVisibilityDistance() override;
+ bool AddPlayerToMap(Player* player, bool initPlayer = true) override;
+
private:
ObjectGuid _owner;
+ Player* _loadingPlayer; ///< @workaround Player is not registered in ObjectAccessor during login
};
#endif // GarrisonMap_h__
diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp
index 3229ee7d02a..f95acef952c 100644
--- a/src/server/game/Garrison/GarrisonMgr.cpp
+++ b/src/server/game/Garrison/GarrisonMgr.cpp
@@ -17,6 +17,7 @@
#include "GarrisonMgr.h"
#include "Containers.h"
+#include "DatabaseEnv.h"
#include "Garrison.h"
#include "ObjectDefines.h"
#include "World.h"
@@ -55,6 +56,9 @@ void GarrisonMgr::Initialize()
}
}
}
+
+ InitializeDbIdSequences();
+ LoadFollowerClassSpecAbilities();
}
GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const
@@ -139,11 +143,12 @@ uint32 const AbilitiesForQuality[][2] =
{ 2, 3 } // Legendary
};
-std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const
+std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const
{
ASSERT(faction < 2);
- std::list<uint32> result;
+ bool hasForcedExclusiveTrait = false;
+ std::list<GarrAbilityEntry const*> result;
int32 slots[2] = { AbilitiesForQuality[quality][0], AbilitiesForQuality[quality][1] };
GarrAbilities const* abilities = nullptr;
@@ -151,7 +156,7 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
if (itr != _garrisonFollowerAbilities[faction].end())
abilities = &itr->second;
- std::list<uint32> abilityList, forcedAbilities, traitList, forcedTraits;
+ std::list<GarrAbilityEntry const*> abilityList, forcedAbilities, traitList, forcedTraits;
if (abilities)
{
for (GarrAbilityEntry const* ability : abilities->Counters)
@@ -162,9 +167,9 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
continue;
if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
- forcedAbilities.push_back(ability->ID);
+ forcedAbilities.push_back(ability);
else
- abilityList.push_back(ability->ID);
+ abilityList.push_back(ability);
}
for (GarrAbilityEntry const* ability : abilities->Traits)
@@ -175,36 +180,51 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
continue;
if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
- forcedTraits.push_back(ability->ID);
+ forcedTraits.push_back(ability);
else
- traitList.push_back(ability->ID);
+ traitList.push_back(ability);
}
}
Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
Trinity::Containers::RandomResizeList(traitList, std::max<int32>(0, slots[1] - forcedTraits.size()));
- // Add counters specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation
+ // Add abilities specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation
if (initial)
{
forcedAbilities.splice(forcedAbilities.end(), abilityList);
forcedTraits.splice(forcedTraits.end(), traitList);
}
- if (slots[0] > forcedAbilities.size() + abilityList.size())
+ forcedAbilities.sort();
+ abilityList.sort();
+ forcedTraits.sort();
+ traitList.sort();
+
+ // check if we have a trait from exclusive category
+ for (GarrAbilityEntry const* ability : forcedTraits)
{
- std::list<uint32> classSpecAbilities; // = GetDefaultClassSpecAbilities(follower, faction)
+ if (ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ {
+ hasForcedExclusiveTrait = true;
+ break;
+ }
+ }
- abilityList.splice(abilityList.end(), classSpecAbilities);
- abilityList.sort();
- abilityList.unique();
+ if (slots[0] > forcedAbilities.size() + abilityList.size())
+ {
+ std::list<GarrAbilityEntry const*> classSpecAbilities = GetClassSpecAbilities(follower, faction);
+ std::list<GarrAbilityEntry const*> classSpecAbilitiesTemp, classSpecAbilitiesTemp2;
+ classSpecAbilitiesTemp2.swap(abilityList);
+ std::set_difference(classSpecAbilities.begin(), classSpecAbilities.end(), forcedAbilities.begin(), forcedAbilities.end(), std::back_inserter(classSpecAbilitiesTemp));
+ std::set_union(classSpecAbilitiesTemp.begin(), classSpecAbilitiesTemp.end(), classSpecAbilitiesTemp2.begin(), classSpecAbilitiesTemp2.end(), std::back_inserter(abilityList));
Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
}
if (slots[1] > forcedTraits.size() + traitList.size())
{
- std::list<uint32> genericTraits;
+ std::list<GarrAbilityEntry const*> genericTraits, genericTraitsTemp;
for (GarrAbilityEntry const* ability : _garrisonFollowerRandomTraits)
{
if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
@@ -212,14 +232,44 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
continue;
- genericTraits.push_back(ability->ID);
+ // forced exclusive trait exists, skip other ones entirely
+ if (hasForcedExclusiveTrait && ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ continue;
+
+ genericTraitsTemp.push_back(ability);
}
- traitList.splice(traitList.end(), genericTraits);
- traitList.sort();
- traitList.unique();
+ std::set_difference(genericTraitsTemp.begin(), genericTraitsTemp.end(), forcedTraits.begin(), forcedTraits.end(), std::back_inserter(genericTraits));
+ genericTraits.splice(genericTraits.begin(), traitList);
+ // "split" the list into two parts [nonexclusive, exclusive] to make selection later easier
+ genericTraits.sort([](GarrAbilityEntry const* a1, GarrAbilityEntry const* a2)
+ {
+ uint32 e1 = a1->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE;
+ uint32 e2 = a2->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE;
+ if (e1 != e2)
+ return e1 < e2;
+
+ return a1->ID < a2->ID;
+ });
+ genericTraits.unique();
- Trinity::Containers::RandomResizeList(traitList, std::max<int32>(0, slots[1] - forcedTraits.size()));
+ std::size_t firstExclusive = 0, total = genericTraits.size();
+ for (auto itr = genericTraits.begin(); itr != genericTraits.end(); ++itr, ++firstExclusive)
+ if ((*itr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ break;
+
+ while (traitList.size() < std::max<int32>(0, slots[1] - forcedTraits.size()) && total)
+ {
+ auto itr = genericTraits.begin();
+ std::advance(itr, urand(0, total-- - 1));
+ if ((*itr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ total = firstExclusive; // selected exclusive trait - no other can be selected now
+ else
+ --firstExclusive;
+
+ traitList.push_back(*itr);
+ genericTraits.erase(itr);
+ }
}
result.splice(result.end(), forcedAbilities);
@@ -229,3 +279,75 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
return result;
}
+
+std::list<GarrAbilityEntry const*> GarrisonMgr::GetClassSpecAbilities(GarrFollowerEntry const* follower, uint32 faction) const
+{
+ std::list<GarrAbilityEntry const*> abilities;
+ uint32 classSpecId;
+ switch (faction)
+ {
+ case GARRISON_FACTION_INDEX_HORDE:
+ classSpecId = follower->HordeGarrClassSpecID;
+ break;
+ case GARRISON_FACTION_INDEX_ALLIANCE:
+ classSpecId = follower->AllianceGarrClassSpecID;
+ break;
+ default:
+ return abilities;
+ }
+
+ if (!sGarrClassSpecStore.LookupEntry(classSpecId))
+ return abilities;
+
+ auto itr = _garrisonFollowerClassSpecAbilities.find(classSpecId);
+ if (itr != _garrisonFollowerClassSpecAbilities.end())
+ abilities = itr->second;
+
+ return abilities;
+}
+
+void GarrisonMgr::InitializeDbIdSequences()
+{
+ if (QueryResult result = CharacterDatabase.Query("SELECT MAX(dbId) FROM character_garrison_followers"))
+ _followerDbIdGenerator = (*result)[0].GetUInt64() + 1;
+}
+
+void GarrisonMgr::LoadFollowerClassSpecAbilities()
+{
+ QueryResult result = WorldDatabase.Query("SELECT classSpecId, abilityId FROM garrison_follower_class_spec_abilities");
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 garrison follower class spec abilities. DB table `garrison_follower_class_spec_abilities` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 classSpecId = fields[0].GetUInt32();
+ uint32 abilityId = fields[1].GetUInt32();
+
+ if (!sGarrClassSpecStore.LookupEntry(classSpecId))
+ {
+ TC_LOG_ERROR("sql.sql", "Non-existing GarrClassSpec.db2 entry %u was referenced in `garrison_follower_class_spec_abilities` by row (%u, %u).", classSpecId, classSpecId, abilityId);
+ continue;
+ }
+
+ GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(abilityId);
+ if (!ability)
+ {
+ TC_LOG_ERROR("sql.sql", "Non-existing GarrAbility.db2 entry %u was referenced in `garrison_follower_class_spec_abilities` by row (%u, %u).", abilityId, classSpecId, abilityId);
+ continue;
+ }
+
+ _garrisonFollowerClassSpecAbilities[classSpecId].push_back(ability);
+ ++count;
+
+ } while (result->NextRow());
+
+ for (auto& pair : _garrisonFollowerClassSpecAbilities)
+ pair.second.sort();
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u garrison follower class spec abilities.", count);
+}
diff --git a/src/server/game/Garrison/GarrisonMgr.h b/src/server/game/Garrison/GarrisonMgr.h
index f037c0867a0..63810e3c3ab 100644
--- a/src/server/game/Garrison/GarrisonMgr.h
+++ b/src/server/game/Garrison/GarrisonMgr.h
@@ -45,18 +45,23 @@ public:
uint32 GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const;
GarrBuildingEntry const* GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const;
uint64 GenerateFollowerDbId();
- std::list<uint32> RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const;
+ std::list<GarrAbilityEntry const*> RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const;
+ std::list<GarrAbilityEntry const*> GetClassSpecAbilities(GarrFollowerEntry const* follower, uint32 faction) const;
private:
+ void InitializeDbIdSequences();
+ void LoadFollowerClassSpecAbilities();
+
std::unordered_map<uint32 /*garrSiteId*/, std::vector<GarrSiteLevelPlotInstEntry const*>> _garrisonPlotInstBySiteLevel;
std::unordered_map<uint32 /*mapId*/, std::unordered_map<uint32 /*garrPlotId*/, GameObjectsEntry const*>> _garrisonPlots;
std::unordered_map<uint32 /*garrPlotId*/, std::unordered_set<uint32/*garrBuildingId*/>> _garrisonBuildingsByPlot;
std::unordered_map<uint64 /*garrBuildingId | garrSiteLevelPlotInstId << 32*/, uint32 /*garrBuildingPlotInstId*/> _garrisonBuildingPlotInstances;
std::unordered_map<uint32 /*buildingType*/, std::vector<GarrBuildingEntry const*>> _garrisonBuildingsByType;
std::unordered_map<uint32 /*garrFollowerId*/, GarrAbilities> _garrisonFollowerAbilities[2];
- std::unordered_set<GarrAbilityEntry const*> _garrisonFollowerRandomTraits;
+ std::unordered_map<uint32 /*classSpecId*/, std::list<GarrAbilityEntry const*>> _garrisonFollowerClassSpecAbilities;
+ std::set<GarrAbilityEntry const*> _garrisonFollowerRandomTraits;
- uint64 _followerDbIdGenerator;
+ uint64 _followerDbIdGenerator = UI64LIT(1);
};
#define sGarrisonMgr GarrisonMgr::Instance()
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index ac87f58af5c..cdd550a98f2 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -2242,6 +2242,25 @@ bool ObjectMgr::GetPlayerNameByGUID(ObjectGuid const& guid, std::string& name)
return false;
}
+bool ObjectMgr::GetPlayerNameAndClassByGUID(ObjectGuid const& guid, std::string& name, uint8& _class)
+{
+ if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
+ {
+ name = player->GetName();
+ _class = player->getClass();
+ return true;
+ }
+
+ if (CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid))
+ {
+ name = characterInfo->Name;
+ _class = characterInfo->Class;
+ return true;
+ }
+
+ return false;
+}
+
uint32 ObjectMgr::GetPlayerTeamByGUID(ObjectGuid const& guid)
{
if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
@@ -3620,10 +3639,10 @@ void ObjectMgr::LoadQuests()
mExclusiveQuestGroups.clear();
QueryResult result = WorldDatabase.Query("SELECT "
- //0 1 2 3 4 5 6 7 8 9 10 11 12
- "ID, QuestType, QuestLevel, QuestPackageID, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, Float10, RewardMoney, RewardMoneyDifficulty, "
- //13 14 15 16 17 18 19 20 21
- "Float13, RewardBonusMoney, RewardDisplaySpell, RewardSpell, RewardHonor, RewardKillHonor, StartItem, Flags, FlagsEx, "
+ //0 1 2 3 4 5 6 7 8 9 10
+ "ID, QuestType, QuestLevel, QuestPackageID, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, "
+ //11 12 13 14 15 16 17 18 19 20 21
+ "RewardMoney, RewardMoneyDifficulty, Float13, RewardBonusMoney, RewardDisplaySpell, RewardSpell, RewardHonor, RewardKillHonor, StartItem, Flags, FlagsEx, "
//22 23 24 25 26 27 28 29
"RewardItem1, RewardAmount1, ItemDrop1, ItemDropQuantity1, RewardItem2, RewardAmount2, ItemDrop2, ItemDropQuantity2, "
//30 31 32 33 34 35 36 37
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index dc26e30773c..4277ab74048 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -780,6 +780,7 @@ class ObjectMgr
* @return true if player was found, false otherwise
*/
static bool GetPlayerNameByGUID(ObjectGuid const& guid, std::string& name);
+ static bool GetPlayerNameAndClassByGUID(ObjectGuid const& guid, std::string& name, uint8& _class);
static uint32 GetPlayerTeamByGUID(ObjectGuid const& guid);
static uint32 GetPlayerAccountIdByGUID(ObjectGuid const& guid);
static uint32 GetPlayerAccountIdByPlayerName(std::string const& name);
@@ -1364,7 +1365,7 @@ class ObjectMgr
{
auto itr = _guidGenerators.find(high);
if (itr == _guidGenerators.end())
- itr = _guidGenerators.insert(std::make_pair(high, std::unique_ptr<ObjectGuidGenerator<high>>(new ObjectGuidGenerator<high>()))).first;
+ itr = _guidGenerators.insert(std::make_pair(high, Trinity::make_unique<ObjectGuidGenerator<high>>())).first;
return *itr->second;
}
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index f359e1eff57..fadf7e1970e 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -21,6 +21,7 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Player.h"
+#include "Pet.h"
#include "World.h"
#include "ObjectMgr.h"
#include "GroupMgr.h"
@@ -35,6 +36,7 @@
#include "Util.h"
#include "LFGMgr.h"
#include "UpdateFieldFlags.h"
+#include "PartyPackets.h"
Roll::Roll(ObjectGuid _guid, LootItem const& li) : itemGUID(_guid), itemid(li.itemid),
itemRandomPropId(li.randomPropertyId), itemRandomSuffix(li.randomSuffix), itemCount(li.count),
@@ -55,11 +57,15 @@ Loot* Roll::getLoot()
Group::Group() : m_leaderGuid(), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL),
m_dungeonDifficulty(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_NORMAL_RAID), m_legacyRaidDifficulty(DIFFICULTY_10_N),
-m_bgGroup(NULL), m_bfGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(),
-m_masterLooterGuid(), m_subGroupsCounts(NULL), m_guid(), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0)
+m_bgGroup(nullptr), m_bfGroup(nullptr), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(),
+m_masterLooterGuid(), m_subGroupsCounts(nullptr), m_guid(), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0),
+m_readyCheckStarted(false), m_readyCheckTimer(0), m_activeMarkers(0)
{
- for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
m_targetIcons[i].Clear();
+
+ for (uint8 i = 0; i < RAID_MARKERS_COUNT; ++i)
+ m_markers[i] = nullptr;
}
Group::~Group()
@@ -176,7 +182,7 @@ void Group::LoadGroupFromDB(Field* fields)
m_looterGuid = ObjectGuid::Create<HighGuid::Player>(fields[2].GetUInt64());
m_lootThreshold = ItemQualities(fields[3].GetUInt8());
- for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
m_targetIcons[i].SetRawValue(fields[4 + i].GetBinary());
m_groupType = GroupType(fields[12].GetUInt8());
@@ -199,7 +205,7 @@ void Group::LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uin
member.guid = ObjectGuid::Create<HighGuid::Player>(guidLow);
// skip non-existed member
- if (!ObjectMgr::GetPlayerNameByGUID(member.guid, member.name))
+ if (!ObjectMgr::GetPlayerNameAndClassByGUID(member.guid, member.name, member._class))
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_MEMBER);
stmt->setUInt64(0, guidLow);
@@ -207,9 +213,10 @@ void Group::LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uin
return;
}
- member.group = subgroup;
- member.flags = memberFlags;
- member.roles = roles;
+ member.group = subgroup;
+ member.flags = memberFlags;
+ member.roles = roles;
+ member.readyChecked = false;
m_memberSlots.push_back(member);
@@ -368,7 +375,7 @@ bool Group::AddMember(Player* player)
bool groupFound = false;
for (; subGroup < MAX_RAID_SUBGROUPS; ++subGroup)
{
- if (m_subGroupsCounts[subGroup] < MAXGROUPSIZE)
+ if (m_subGroupsCounts[subGroup] < MAX_GROUP_SIZE)
{
groupFound = true;
break;
@@ -380,11 +387,13 @@ bool Group::AddMember(Player* player)
}
MemberSlot member;
- member.guid = player->GetGUID();
- member.name = player->GetName();
- member.group = subGroup;
- member.flags = 0;
- member.roles = 0;
+ member.guid = player->GetGUID();
+ member.name = player->GetName();
+ member._class = player->getClass();
+ member.group = subGroup;
+ member.flags = 0;
+ member.roles = 0;
+ member.readyChecked = false;
m_memberSlots.push_back(member);
SubGroupCounterIncrease(subGroup);
@@ -407,7 +416,7 @@ bool Group::AddMember(Player* player)
if (!isRaidGroup()) // reset targetIcons for non-raid-groups
{
- for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
m_targetIcons[i].Clear();
}
@@ -455,7 +464,11 @@ bool Group::AddMember(Player* player)
}
}
}
+
player->SetGroupUpdateFlag(GROUP_UPDATE_FULL);
+ if (Pet* pet = player->GetPet())
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
+
UpdatePlayerOutOfRange(player);
// quest related GO state dependent from raid membership
@@ -552,12 +565,6 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
player->GetSession()->SendPacket(&data);
}
- // Do we really need to send this opcode?
- data.Initialize(SMSG_PARTY_UPDATE, 1+1+1+1+8+4+4+8);
- data << uint8(0x10) << uint8(0) << uint8(0) << uint8(0);
- data << m_guid << uint32(m_counter) << uint32(0) << uint64(0);
- player->GetSession()->SendPacket(&data);
-
_homebindIfInstance(player);
}
@@ -644,7 +651,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
}
}
-void Group::ChangeLeader(ObjectGuid newLeaderGuid)
+void Group::ChangeLeader(ObjectGuid newLeaderGuid, int8 partyIndex)
{
member_witerator slot = _getMemberWSlot(newLeaderGuid);
@@ -707,9 +714,10 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid)
m_leaderName = newLeader->GetName();
ToggleGroupMemberFlag(slot, MEMBER_FLAG_ASSISTANT, false);
- WorldPacket data(SMSG_GROUP_NEW_LEADER, m_leaderName.size()+1);
- data << slot->name;
- BroadcastPacket(&data, true);
+ WorldPackets::Party::GroupNewLeader groupNewLeader;
+ groupNewLeader.Name = m_leaderName;
+ groupNewLeader.PartyIndex = partyIndex;
+ BroadcastPacket(groupNewLeader.Write(), true);
}
void Group::Disband(bool hideDestroy /* = false */)
@@ -1491,45 +1499,38 @@ void Group::CountTheRoll(Rolls::iterator rollI)
delete roll;
}
-void Group::SetTargetIcon(uint8 id, ObjectGuid whoGuid, ObjectGuid targetGuid)
+void Group::SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy, uint8 partyIndex)
{
- if (id >= TARGETICONCOUNT)
+ if (symbol >= TARGET_ICONS_COUNT)
return;
// clean other icons
- if (!targetGuid.IsEmpty())
- for (int i = 0; i < TARGETICONCOUNT; ++i)
- if (m_targetIcons[i] == targetGuid)
- SetTargetIcon(i, ObjectGuid::Empty, ObjectGuid::Empty);
+ if (!target.IsEmpty())
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
+ if (m_targetIcons[i] == target)
+ SetTargetIcon(i, ObjectGuid::Empty, changedBy, partyIndex);
- m_targetIcons[id] = targetGuid;
+ m_targetIcons[symbol] = target;
- WorldPacket data(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, (1+8+1+8));
- data << uint8(0); // set targets
- data << whoGuid;
- data << uint8(id);
- data << targetGuid;
- BroadcastPacket(&data, true);
+ WorldPackets::Party::SendRaidTargetUpdateSingle updateSingle;
+ updateSingle.PartyIndex = partyIndex;
+ updateSingle.Target = target;
+ updateSingle.ChangedBy = changedBy;
+ updateSingle.Symbol = symbol;
+ BroadcastPacket(updateSingle.Write(), true);
}
-void Group::SendTargetIconList(WorldSession* session)
+void Group::SendTargetIconList(WorldSession* session, int8 partyIndex)
{
if (!session)
return;
- WorldPacket data(SMSG_SEND_RAID_TARGET_UPDATE_ALL, (1+TARGETICONCOUNT*9));
- data << uint8(1); // list targets
+ WorldPackets::Party::SendRaidTargetUpdateAll updateAll;
+ updateAll.PartyIndex = partyIndex;
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; i++)
+ updateAll.TargetIcons.insert(std::pair<uint8, ObjectGuid>(i, m_targetIcons[i]));
- for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
- {
- if (m_targetIcons[i].IsEmpty())
- continue;
-
- data << uint8(i);
- data << m_targetIcons[i];
- }
-
- session->SendPacket(&data);
+ session->SendPacket(updateAll.Write());
}
void Group::SendUpdate()
@@ -1556,56 +1557,79 @@ void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot)
slot = &(*witr);
}
- WorldPacket data(SMSG_PARTY_UPDATE, (1+1+1+1+1+4+8+4+4+(GetMembersCount()-1)*(13+8+1+1+1+1)+8+1+8+1+1+1+1));
- data << uint8(m_groupType); // group type (flags in 3.3)
- data << uint8(slot->group);
- data << uint8(slot->flags);
- data << uint8(slot->roles);
- if (isLFGGroup())
- {
- data << uint8(sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0); // FIXME - Dungeon save status? 2 = done
- data << uint32(sLFGMgr->GetDungeon(m_guid));
- data << uint8(0); // 4.x new
- }
+ WorldPackets::Party::PartyUpdate partyUpdate;
- data << m_guid;
- data << uint32(m_counter++); // 3.3, value increases every time this packet gets sent
- data << uint32(GetMembersCount()-1);
- for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
+ partyUpdate.PartyType = m_groupType;
+ partyUpdate.PartyIndex = 0;
+ partyUpdate.PartyFlags = uint8(IsCreated());
+
+ partyUpdate.PartyGUID = m_guid;
+ partyUpdate.LeaderGUID = m_leaderGuid;
+
+ partyUpdate.SequenceNum = m_counter++; // 3.3, value increases every time this packet gets sent
+
+ partyUpdate.MyIndex = -1;
+ uint8 index = 0;
+ for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr, ++index)
{
if (slot->guid == citr->guid)
- continue;
+ partyUpdate.MyIndex = index;
Player* member = ObjectAccessor::FindConnectedPlayer(citr->guid);
- uint8 onlineState = (member && !member->GetSession()->PlayerLogout()) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE;
- onlineState = onlineState | ((isBGGroup() || isBFGroup()) ? MEMBER_STATUS_PVP : 0);
+ WorldPackets::Party::GroupPlayerInfos playerInfos;
- data << citr->name;
- data << citr->guid; // guid
- data << uint8(onlineState); // online-state
- data << uint8(citr->group); // groupid
- data << uint8(citr->flags); // See enum GroupMemberFlags
- data << uint8(citr->roles); // Lfg Roles
+ playerInfos.GUID = citr->guid;
+ playerInfos.Name = citr->name;
+ playerInfos.Class = citr->_class;
+
+ playerInfos.Status = MEMBER_STATUS_OFFLINE;
+ if (member && member->GetSession() && !member->GetSession()->PlayerLogout())
+ playerInfos.Status = MEMBER_STATUS_ONLINE | (isBGGroup() || isBFGroup() ? MEMBER_STATUS_PVP : 0);
+
+ playerInfos.Subgroup = citr->group; // groupid
+ playerInfos.Flags = citr->flags; // See enum GroupMemberFlags
+ playerInfos.RolesAssigned = citr->roles; // Lfg Roles
+
+ partyUpdate.PlayerList.push_back(playerInfos);
}
- data << m_leaderGuid; // leader guid
+ if (GetMembersCount() > 1)
+ {
+ // LootSettings
+ partyUpdate.LootSettings = boost::in_place();
+ partyUpdate.LootSettings->Method = m_lootMethod;
+ partyUpdate.LootSettings->Threshold = m_lootThreshold;
+ partyUpdate.LootSettings->LootMaster = m_lootMethod == MASTER_LOOT ? m_masterLooterGuid : ObjectGuid::Empty;
+
+ // Difficulty Settings
+ partyUpdate.DifficultySettings = boost::in_place();
+ partyUpdate.DifficultySettings->DungeonDifficultyID = m_dungeonDifficulty;
+ partyUpdate.DifficultySettings->RaidDifficultyID = m_raidDifficulty;
+ partyUpdate.DifficultySettings->LegacyRaidDifficultyID = m_legacyRaidDifficulty;
+ }
- if (GetMembersCount() - 1)
+ // LfgInfos
+ if (isLFGGroup())
{
- data << uint8(m_lootMethod); // loot method
+ partyUpdate.LfgInfos = boost::in_place();
- if (m_lootMethod == MASTER_LOOT)
- data << m_masterLooterGuid; // master looter guid
- else
- data << uint64(0);
+ partyUpdate.LfgInfos->Slot = sLFGMgr->GetDungeon(m_guid);
+ partyUpdate.LfgInfos->BootCount = 0; // new 6.x
+ partyUpdate.LfgInfos->Aborted = false; // new 6.x
+
+ partyUpdate.LfgInfos->MyFlags = 0; // new 6.x
+ partyUpdate.LfgInfos->MyRandomSlot = 0; // new 6.x
+
+ partyUpdate.LfgInfos->MyPartialClear = sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0; // FIXME - Dungeon save status? 2 = done
+ partyUpdate.LfgInfos->MyGearDiff = 0.f; // new 6.x
+ partyUpdate.LfgInfos->MyFirstReward = false; // new 6.x
- data << uint8(m_lootThreshold); // loot threshold
- data << uint8(m_dungeonDifficulty); // Dungeon Difficulty
- data << uint8(m_raidDifficulty); // Raid Difficulty
+ partyUpdate.LfgInfos->MyStrangerCount = 0; // new 6.x
+ partyUpdate.LfgInfos->MyKickVoteCount = 0; // new 6.x
}
- player->GetSession()->SendPacket(&data);
+ player->GetSession()->SendPacket(partyUpdate.Write());
}
void Group::UpdatePlayerOutOfRange(Player* player)
@@ -1613,15 +1637,15 @@ void Group::UpdatePlayerOutOfRange(Player* player)
if (!player || !player->IsInWorld())
return;
- WorldPacket data;
- player->GetSession()->BuildPartyMemberStatsChangedPacket(player, &data);
+ WorldPackets::Party::PartyMemberStats packet;
+ packet.Initialize(player);
Player* member;
for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
member = itr->GetSource();
if (member && member != player && (!member->IsInMap(player) || !member->IsWithinDist(player, member->GetSightRange(), false)))
- member->GetSession()->SendPacket(&data);
+ member->GetSession()->SendPacket(packet.Write());
}
}
@@ -1653,32 +1677,6 @@ void Group::BroadcastPacket(WorldPacket const* packet, bool ignorePlayersInBGRai
}
}
-void Group::BroadcastReadyCheck(WorldPacket const* packet)
-{
- for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
- {
- Player* player = itr->GetSource();
- if (player && player->GetSession())
- if (IsLeader(player->GetGUID()) || IsAssistant(player->GetGUID()))
- player->GetSession()->SendPacket(packet);
- }
-}
-
-void Group::OfflineReadyCheck()
-{
- for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
- {
- Player* player = ObjectAccessor::FindConnectedPlayer(citr->guid);
- if (!player || !player->GetSession())
- {
- WorldPacket data(SMSG_READY_CHECK_RESPONSE, 9);
- data << citr->guid;
- data << uint8(0);
- BroadcastReadyCheck(&data);
- }
- }
-}
-
bool Group::_setMembersGroup(ObjectGuid guid, uint8 group)
{
member_witerator slot = _getMemberWSlot(guid);
@@ -1725,8 +1723,8 @@ void Group::ChangeMembersGroup(ObjectGuid guid, uint8 group)
if (slot == m_memberSlots.end())
return;
+ uint8 prevSubGroup = slot->group;
// Abort if the player is already in the target sub group
- uint8 prevSubGroup = GetMemberGroup(guid);
if (prevSubGroup == group)
return;
@@ -1758,7 +1756,6 @@ void Group::ChangeMembersGroup(ObjectGuid guid, uint8 group)
else
{
// If player is in BG raid, it is possible that he is also in normal raid - and that normal raid is stored in m_originalGroup reference
- prevSubGroup = player->GetOriginalSubGroup();
player->GetOriginalGroupRef().setSubGroup(group);
}
}
@@ -1767,6 +1764,51 @@ void Group::ChangeMembersGroup(ObjectGuid guid, uint8 group)
SendUpdate();
}
+void Group::SwapMembersGroups(ObjectGuid firstGuid, ObjectGuid secondGuid)
+{
+ if (!isRaidGroup())
+ return;
+
+ member_witerator slots[2];
+ slots[0] = _getMemberWSlot(firstGuid);
+ slots[1] = _getMemberWSlot(secondGuid);
+ if (slots[0] == m_memberSlots.end() || slots[1] == m_memberSlots.end())
+ return;
+
+ if (slots[0]->group == slots[1]->group)
+ return;
+
+ uint8 tmp = slots[0]->group;
+ slots[0]->group = slots[1]->group;
+ slots[1]->group = tmp;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ for (uint8 i = 0; i < 2; i++)
+ {
+ // Preserve new sub group in database for non-raid groups
+ if (!isBGGroup() && !isBFGroup())
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_MEMBER_SUBGROUP);
+
+ stmt->setUInt8(0, slots[i]->group);
+ stmt->setUInt64(1, slots[i]->guid.GetCounter());
+
+ trans->Append(stmt);
+ }
+
+ if (Player* player = ObjectAccessor::FindConnectedPlayer(slots[i]->guid))
+ {
+ if (player->GetGroup() == this)
+ player->GetGroupRef().setSubGroup(slots[i]->group);
+ else
+ player->GetOriginalGroupRef().setSubGroup(slots[i]->group);
+ }
+ }
+ CharacterDatabase.CommitTransaction(trans);
+
+ SendUpdate();
+}
+
// Retrieve the next Round-Roubin player for the group
//
// No update done if loot method is FFA.
@@ -2262,9 +2304,167 @@ void Group::SetLfgRoles(ObjectGuid guid, uint8 roles)
SendUpdate();
}
+uint8 Group::GetLfgRoles(ObjectGuid guid)
+{
+ member_witerator slot = _getMemberWSlot(guid);
+ if (slot == m_memberSlots.end())
+ return 0;
+
+ return slot->roles;
+}
+
+void Group::Update(uint32 diff)
+{
+ UpdateReadyCheck(diff);
+}
+
+void Group::UpdateReadyCheck(uint32 diff)
+{
+ if (!m_readyCheckStarted)
+ return;
+
+ m_readyCheckTimer -= diff;
+ if (m_readyCheckTimer <= 0)
+ EndReadyCheck();
+}
+
+void Group::StartReadyCheck(ObjectGuid starterGuid, int8 partyIndex, uint32 duration)
+{
+ if (m_readyCheckStarted)
+ return;
+
+ member_witerator slot = _getMemberWSlot(starterGuid);
+ if (slot == m_memberSlots.end())
+ return ;
+
+ m_readyCheckStarted = true;
+ m_readyCheckTimer = duration;
+
+ SetOfflineMembersReadyChecked();
+
+ SetMemberReadyChecked(&(*slot));
+
+ WorldPackets::Party::ReadyCheckStarted readyCheckStarted;
+ readyCheckStarted.PartyGUID = m_guid;
+ readyCheckStarted.PartyIndex = partyIndex;
+ readyCheckStarted.InitiatorGUID = starterGuid;
+ readyCheckStarted.Duration = duration;
+ BroadcastPacket(readyCheckStarted.Write(), false);
+}
+
+void Group::EndReadyCheck(void)
+{
+ if (!m_readyCheckStarted)
+ return;
+
+ m_readyCheckStarted = false;
+ m_readyCheckTimer = 0;
+
+ ResetMemberReadyChecked();
+
+ WorldPackets::Party::ReadyCheckCompleted readyCheckCompleted;
+ readyCheckCompleted.PartyIndex = 0;
+ readyCheckCompleted.PartyGUID = m_guid;
+ BroadcastPacket(readyCheckCompleted.Write(), false);
+}
+
+bool Group::IsReadyCheckCompleted(void) const
+{
+ for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
+ if (!citr->readyChecked)
+ return false;
+ return true;
+}
+
+void Group::SetMemberReadyCheck(ObjectGuid guid, bool ready)
+{
+ if (!m_readyCheckStarted)
+ return;
+
+ member_witerator slot = _getMemberWSlot(guid);
+ if (slot != m_memberSlots.end())
+ SetMemberReadyCheck(&(*slot), ready);
+}
+
+void Group::SetMemberReadyCheck(MemberSlot* slot, bool ready)
+{
+ WorldPackets::Party::ReadyCheckResponse response;
+ response.PartyGUID = m_guid;
+ response.Player = slot->guid;
+ response.IsReady = ready;
+ BroadcastPacket(response.Write(), false);
+
+ SetMemberReadyChecked(slot);
+}
+
+void Group::SetOfflineMembersReadyChecked(void)
+{
+ for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
+ {
+ Player* player = ObjectAccessor::FindConnectedPlayer(itr->guid);
+ if (!player || !player->GetSession())
+ SetMemberReadyCheck(&(*itr), false);
+ }
+}
+
+void Group::SetMemberReadyChecked(MemberSlot* slot)
+{
+ slot->readyChecked = true;
+ if (IsReadyCheckCompleted())
+ EndReadyCheck();
+}
+
+void Group::ResetMemberReadyChecked(void)
+{
+ for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
+ itr->readyChecked = false;
+}
+
+void Group::AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid)
+{
+ if (markerId >= RAID_MARKERS_COUNT || m_markers[markerId])
+ return;
+
+ m_activeMarkers |= (1 << markerId);
+ m_markers[markerId] = Trinity::make_unique<RaidMarker>(mapId, positionX, positionY, positionZ, transportGuid);
+ SendRaidMarkersChanged();
+}
+
+void Group::DeleteRaidMarker(uint8 markerId)
+{
+ if (markerId > RAID_MARKERS_COUNT)
+ return;
+
+ for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
+ if (m_markers[i] && (markerId == i || markerId == RAID_MARKERS_COUNT))
+ {
+ m_markers[i] = nullptr;
+ m_activeMarkers &= ~(1 << i);
+ }
+
+ SendRaidMarkersChanged();
+}
+
+void Group::SendRaidMarkersChanged(WorldSession* session, int8 partyIndex)
+{
+ WorldPackets::Party::RaidMarkersChanged packet;
+
+ packet.PartyIndex = partyIndex;
+ packet.ActiveMarkers = m_activeMarkers;
+
+ for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
+ if (m_markers[i])
+ packet.RaidMarkers.push_back(m_markers[i].get());
+
+ if (session)
+ session->SendPacket(packet.Write());
+ else
+ BroadcastPacket(packet.Write(), false);
+}
+
bool Group::IsFull() const
{
- return isRaidGroup() ? (m_memberSlots.size() >= MAXRAIDSIZE) : (m_memberSlots.size() >= MAXGROUPSIZE);
+ return isRaidGroup() ? (m_memberSlots.size() >= MAX_RAID_SIZE) : (m_memberSlots.size() >= MAX_GROUP_SIZE);
}
bool Group::isLFGGroup() const
@@ -2371,10 +2571,9 @@ bool Group::SameSubGroup(ObjectGuid guid1, MemberSlot const* slot2) const
bool Group::HasFreeSlotSubGroup(uint8 subgroup) const
{
- return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAXGROUPSIZE);
+ return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAX_GROUP_SIZE);
}
-
uint8 Group::GetMemberGroup(ObjectGuid guid) const
{
member_citerator mslot = _getMemberCSlot(guid);
@@ -2522,3 +2721,15 @@ void Group::ToggleGroupMemberFlag(member_witerator slot, uint8 flag, bool apply)
slot->flags &= ~flag;
}
+void Group::SetEveryoneIsAssistant(bool apply)
+{
+ if (apply)
+ m_groupType = GroupType(m_groupType | GROUPTYPE_EVERYONE_ASSISTANT);
+ else
+ m_groupType = GroupType(m_groupType & ~GROUPTYPE_EVERYONE_ASSISTANT);
+
+ for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
+ ToggleGroupMemberFlag(itr, MEMBER_FLAG_ASSISTANT, apply);
+
+ SendUpdate();
+}
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 4154f31a410..634d1f0f37b 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -24,6 +24,7 @@
#include "LootMgr.h"
#include "QueryResult.h"
#include "SharedDefines.h"
+#include "Object.h"
class Battlefield;
class Battleground;
@@ -38,10 +39,14 @@ class WorldSession;
struct MapEntry;
-#define MAXGROUPSIZE 5
-#define MAXRAIDSIZE 40
-#define MAX_RAID_SUBGROUPS MAXRAIDSIZE/MAXGROUPSIZE
-#define TARGETICONCOUNT 8
+#define MAX_GROUP_SIZE 5
+#define MAX_RAID_SIZE 40
+#define MAX_RAID_SUBGROUPS MAX_RAID_SIZE / MAX_GROUP_SIZE
+
+#define TARGET_ICONS_COUNT 8
+#define RAID_MARKERS_COUNT 8
+
+#define READYCHECK_DURATION 35000
enum RollVote
{
@@ -81,50 +86,59 @@ enum GroupMemberAssignment
enum GroupType
{
- GROUPTYPE_NORMAL = 0x00,
- GROUPTYPE_BG = 0x01,
- GROUPTYPE_RAID = 0x02,
- GROUPTYPE_BGRAID = GROUPTYPE_BG | GROUPTYPE_RAID, // mask
- GROUPTYPE_LFG_RESTRICTED = 0x04, // Script_HasLFGRestrictions()
- GROUPTYPE_LFG = 0x08,
+ GROUPTYPE_NORMAL = 0x00,
+ GROUPTYPE_BG = 0x01,
+ GROUPTYPE_RAID = 0x02,
+ GROUPTYPE_BGRAID = GROUPTYPE_BG | GROUPTYPE_RAID, // mask
+ GROUPTYPE_LFG_RESTRICTED = 0x04, // Script_HasLFGRestrictions()
+ GROUPTYPE_LFG = 0x08,
+ GROUPTYPE_EVERYONE_ASSISTANT = 0x40, // Script_IsEveryoneAssistant() (4.x)
// 0x10, leave/change group?, I saw this flag when leaving group and after leaving BG while in group
// GROUPTYPE_ONE_PERSON_PARTY = 0x20, 4.x Script_IsOnePersonParty()
- // GROUPTYPE_EVERYONE_ASSISTANT = 0x40 4.x Script_IsEveryoneAssistant()
};
enum GroupUpdateFlags
{
GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing
- GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16 (GroupMemberStatusFlag)
- GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32 (HP)
- GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32 (HP)
- GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8 (PowerType)
- GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // int16 (power value)
- GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // int16 (power value)
- GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16 (level value)
- GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16 (zone id)
- GROUP_UPDATE_FLAG_UNK100 = 0x00000100, // int16 (unk)
- GROUP_UPDATE_FLAG_POSITION = 0x00000200, // uint16 (x), uint16 (y), uint16 (z)
- GROUP_UPDATE_FLAG_AURAS = 0x00000400, // uint8 (unk), uint64 (mask), uint32 (count), for each bit set: uint32 (spell id) + uint16 (AuraFlags) (if has flags Scalable -> 3x int32 (bps))
- GROUP_UPDATE_FLAG_PET_GUID = 0x00000800, // uint64 (pet guid)
- GROUP_UPDATE_FLAG_PET_NAME = 0x00001000, // cstring (name, NULL terminated string)
- GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00002000, // uint16 (model id)
- GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00004000, // uint32 (HP)
- GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00008000, // uint32 (HP)
- GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00010000, // uint8 (PowerType)
- GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00020000, // uint16 (power value)
- GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00040000, // uint16 (power value)
- GROUP_UPDATE_FLAG_PET_AURAS = 0x00080000, // [see GROUP_UPDATE_FLAG_AURAS]
- GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00100000, // int32 (vehicle seat id)
- GROUP_UPDATE_FLAG_PHASE = 0x00200000, // int32 (unk), uint32 (phase count), for (count) uint16(phaseId)
-
- GROUP_UPDATE_PET = GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID |
- GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE |
- GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER | GROUP_UPDATE_FLAG_PET_AURAS, // all pet flags
- GROUP_UPDATE_FULL = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP |
- GROUP_UPDATE_FLAG_POWER_TYPE | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER |
- GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION |
- GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_PET | GROUP_UPDATE_FLAG_PHASE // all known flags, except UNK100 and VEHICLE_SEAT
+ GROUP_UPDATE_FLAG_UNK704 = 0x00000001, // uint8[2] (unk)
+ GROUP_UPDATE_FLAG_STATUS = 0x00000002, // uint16 (GroupMemberStatusFlag)
+ GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000004, // uint8 (PowerType)
+ GROUP_UPDATE_FLAG_UNK322 = 0x00000008, // uint16 (unk)
+ GROUP_UPDATE_FLAG_CUR_HP = 0x00000010, // uint32 (HP)
+ GROUP_UPDATE_FLAG_MAX_HP = 0x00000020, // uint32 (max HP)
+ GROUP_UPDATE_FLAG_CUR_POWER = 0x00000040, // int16 (power value)
+ GROUP_UPDATE_FLAG_MAX_POWER = 0x00000080, // int16 (max power value)
+ GROUP_UPDATE_FLAG_LEVEL = 0x00000100, // uint16 (level value)
+ GROUP_UPDATE_FLAG_UNK200000 = 0x00000200, // int16 (unk)
+ GROUP_UPDATE_FLAG_ZONE = 0x00000400, // uint16 (zone id)
+ GROUP_UPDATE_FLAG_UNK2000000 = 0x00000800, // int16 (unk)
+ GROUP_UPDATE_FLAG_UNK4000000 = 0x00001000, // int32 (unk)
+ GROUP_UPDATE_FLAG_POSITION = 0x00002000, // uint16 (x), uint16 (y), uint16 (z)
+ GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00104000, // int32 (vehicle seat id)
+ GROUP_UPDATE_FLAG_AURAS = 0x00008000, // uint8 (unk), uint64 (mask), uint32 (count), for each bit set: uint32 (spell id) + uint16 (AuraFlags) (if has flags Scalable -> 3x int32 (bps))
+ GROUP_UPDATE_FLAG_PET = 0x00010000, // complex (pet)
+ GROUP_UPDATE_FLAG_PHASE = 0x00020000, // int32 (unk), uint32 (phase count), for (count) uint16(phaseId)
+
+ GROUP_UPDATE_FULL = GROUP_UPDATE_FLAG_UNK704 | GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_POWER_TYPE |
+ GROUP_UPDATE_FLAG_UNK322 | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP |
+ GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL |
+ GROUP_UPDATE_FLAG_UNK200000 | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_UNK2000000 |
+ GROUP_UPDATE_FLAG_UNK4000000 | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_VEHICLE_SEAT |
+ GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET | GROUP_UPDATE_FLAG_PHASE // all known flags
+};
+
+enum GroupUpdatePetFlags
+{
+ GROUP_UPDATE_FLAG_PET_NONE = 0x00000000, // nothing
+ GROUP_UPDATE_FLAG_PET_GUID = 0x00000001, // ObjectGuid (pet guid)
+ GROUP_UPDATE_FLAG_PET_NAME = 0x00000002, // cstring (name, NULL terminated string)
+ GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00000004, // uint16 (model id)
+ GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00000008, // uint32 (HP)
+ GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00000010, // uint32 (max HP)
+ GROUP_UPDATE_FLAG_PET_AURAS = 0x00000020, // [see GROUP_UPDATE_FLAG_AURAS]
+
+ GROUP_UPDATE_PET_FULL = GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID |
+ GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_AURAS // all pet flags
};
class Roll : public LootValidatorRef
@@ -160,6 +174,18 @@ struct InstanceGroupBind
InstanceGroupBind() : save(NULL), perm(false) { }
};
+struct RaidMarker
+{
+ WorldLocation Location;
+ ObjectGuid TransportGUID;
+
+ RaidMarker(uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid = ObjectGuid::Empty)
+ {
+ Location.WorldRelocate(mapId, positionX, positionY, positionZ);
+ TransportGUID = transportGuid;
+ }
+};
+
/** request member stats checken **/
/// @todo uninvite people that not accepted invite
class Group
@@ -169,9 +195,11 @@ class Group
{
ObjectGuid guid;
std::string name;
+ uint8 _class;
uint8 group;
uint8 flags;
uint8 roles;
+ bool readyChecked;
};
typedef std::list<MemberSlot> MemberSlotList;
typedef MemberSlotList::const_iterator member_citerator;
@@ -197,7 +225,7 @@ class Group
bool AddLeaderInvite(Player* player);
bool AddMember(Player* player);
bool RemoveMember(ObjectGuid guid, const RemoveMethod &method = GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker = ObjectGuid::Empty, const char* reason = NULL);
- void ChangeLeader(ObjectGuid guid);
+ void ChangeLeader(ObjectGuid guid, int8 partyIndex = 0);
void SetLootMethod(LootMethod method);
void SetLooterGuid(ObjectGuid guid);
void SetMasterLooterGuid(ObjectGuid guid);
@@ -205,6 +233,31 @@ class Group
void SetLootThreshold(ItemQualities threshold);
void Disband(bool hideDestroy = false);
void SetLfgRoles(ObjectGuid guid, uint8 roles);
+ uint8 GetLfgRoles(ObjectGuid guid);
+ void SetEveryoneIsAssistant(bool apply);
+
+ // Update
+ void Update(uint32 diff);
+ void UpdateReadyCheck(uint32 diff);
+
+ // Ready check
+ void StartReadyCheck(ObjectGuid starterGuid, int8 partyIndex, uint32 duration = READYCHECK_DURATION);
+ void EndReadyCheck();
+
+ bool IsReadyCheckStarted(void) const { return m_readyCheckStarted; }
+ bool IsReadyCheckCompleted(void) const;
+
+ void SetOfflineMembersReadyChecked(void);
+ void SetMemberReadyCheck(ObjectGuid guid, bool ready);
+ void SetMemberReadyCheck(MemberSlot* slot, bool ready);
+
+ void SetMemberReadyChecked(MemberSlot* slot);
+ void ResetMemberReadyChecked(void);
+
+ // Raid Markers
+ void AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid = ObjectGuid::Empty);
+ void DeleteRaidMarker(uint8 markerId);
+ void SendRaidMarkersChanged(WorldSession* session = nullptr, int8 partyIndex = 0);
// properties accessories
bool IsFull() const;
@@ -221,7 +274,7 @@ class Group
ObjectGuid GetMasterLooterGuid() const;
ItemQualities GetLootThreshold() const;
- uint32 GetDbStoreId() const { return m_dbStoreId; };
+ uint32 GetDbStoreId() const { return m_dbStoreId; }
// member manipulation methods
bool IsMember(ObjectGuid guid) const;
@@ -254,7 +307,8 @@ class Group
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(Battleground const* bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot, ObjectGuid& errorGuid);
void ChangeMembersGroup(ObjectGuid guid, uint8 group);
- void SetTargetIcon(uint8 id, ObjectGuid whoGuid, ObjectGuid targetGuid);
+ void SwapMembersGroups(ObjectGuid firstGuid, ObjectGuid secondGuid);
+ void SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy, uint8 partyIndex);
void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag);
void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag);
@@ -269,7 +323,7 @@ class Group
// -no description-
//void SendInit(WorldSession* session);
- void SendTargetIconList(WorldSession* session);
+ void SendTargetIconList(WorldSession* session, int8 partyIndex = 0);
void SendUpdate();
void SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot = NULL);
void UpdatePlayerOutOfRange(Player* player);
@@ -290,8 +344,6 @@ class Group
void BroadcastPacket(WorldPacket const* packet, bool ignorePlayersInBGRaid, int group = -1, ObjectGuid ignoredPlayer = ObjectGuid::Empty);
void BroadcastAddonMessagePacket(WorldPacket const* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group = -1, ObjectGuid ignore = ObjectGuid::Empty);
- void BroadcastReadyCheck(WorldPacket const* packet);
- void OfflineReadyCheck();
/*********************************************************/
/*** LOOT SYSTEM ***/
@@ -351,7 +403,7 @@ class Group
Difficulty m_legacyRaidDifficulty;
Battleground* m_bgGroup;
Battlefield* m_bfGroup;
- ObjectGuid m_targetIcons[TARGETICONCOUNT];
+ ObjectGuid m_targetIcons[TARGET_ICONS_COUNT];
LootMethod m_lootMethod;
ItemQualities m_lootThreshold;
ObjectGuid m_looterGuid;
@@ -363,5 +415,13 @@ class Group
uint32 m_counter; // used only in SMSG_GROUP_LIST
uint32 m_maxEnchantingLevel;
uint32 m_dbStoreId; // Represents the ID used in database (Can be reused by other groups if group was disbanded)
+
+ // Ready Check
+ bool m_readyCheckStarted;
+ int32 m_readyCheckTimer;
+
+ // Raid markers
+ std::array<std::unique_ptr<RaidMarker>, RAID_MARKERS_COUNT> m_markers;
+ uint32 m_activeMarkers;
};
#endif
diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp
index f0c764e7269..7fb239cec48 100644
--- a/src/server/game/Groups/GroupMgr.cpp
+++ b/src/server/game/Groups/GroupMgr.cpp
@@ -233,3 +233,10 @@ void GroupMgr::LoadGroups()
TC_LOG_INFO("server.loading", ">> Loaded %u group-instance saves in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
}
+
+void GroupMgr::Update(uint32 diff)
+{
+ for (GroupContainer::iterator itr = GroupStore.begin(); itr != GroupStore.end(); itr++)
+ if (itr->second)
+ itr->second->Update(diff);
+}
diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h
index 6aafe77432c..2fdd6d978e9 100644
--- a/src/server/game/Groups/GroupMgr.h
+++ b/src/server/game/Groups/GroupMgr.h
@@ -50,6 +50,8 @@ public:
void AddGroup(Group* group);
void RemoveGroup(Group* group);
+ void Update(uint32 diff);
+
protected:
ObjectGuid::LowType NextGroupId;
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index c5812999490..d4c6a0a680d 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1602,11 +1602,11 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
}
// Invited player cannot be in another guild
- /*if (pInvitee->GetGuildId())
+ if (pInvitee->GetGuildId())
{
SendCommandResult(session, GUILD_COMMAND_INVITE_PLAYER, ERR_ALREADY_IN_GUILD_S, name);
return;
- }*/
+ }
// Invited player cannot be invited
if (pInvitee->GetGuildIdInvited())
@@ -2466,7 +2466,7 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::strin
if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK))
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, Language(language), session->GetPlayer(), nullptr, msg);
+ packet.Initialize(officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, Language(language), session->GetPlayer(), nullptr, msg);
WorldPacket const* data = packet.Write();
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
if (Player* player = itr->second->FindConnectedPlayer())
@@ -2481,7 +2481,7 @@ void Guild::BroadcastAddonToGuild(WorldSession* session, bool officerOnly, std::
if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK))
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, LANG_ADDON, session->GetPlayer(), nullptr, msg, 0, "", DEFAULT_LOCALE, prefix);
+ packet.Initialize(officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, LANG_ADDON, session->GetPlayer(), nullptr, msg, 0, "", DEFAULT_LOCALE, prefix);
WorldPacket const* data = packet.Write();
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
if (Player* player = itr->second->FindPlayer())
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 56d865e5d06..7b22d46d67b 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -248,6 +248,14 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES, stmt);
+
return res;
}
@@ -2566,25 +2574,18 @@ void WorldSession::SendCharRename(ResponseCodes result, WorldPackets::Character:
void WorldSession::SendCharCustomize(ResponseCodes result, WorldPackets::Character::CharCustomizeInfo const* customizeInfo)
{
- /// @todo: fix 6.x implementation
- (void)result;
- (void)customizeInfo;
- /*
- WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1 + 8 + customizeInfo.NewName.size() + 1 + 6);
- data << uint8(result);
if (result == RESPONSE_SUCCESS)
{
- data << customizeInfo.Guid;
- data << customizeInfo.NewName;
- data << uint8(customizeInfo.Gender);
- data << uint8(customizeInfo.Skin);
- data << uint8(customizeInfo.Face);
- data << uint8(customizeInfo.HairStyle);
- data << uint8(customizeInfo.HairColor);
- data << uint8(customizeInfo.FacialHair);
+ WorldPackets::Character::CharCustomizeResponse response(customizeInfo);
+ SendPacket(response.Write());
+ }
+ else
+ {
+ WorldPackets::Character::CharCustomizeFailed failed;
+ failed.Result = uint8(result);
+ failed.CharGUID = customizeInfo->CharGUID;
+ SendPacket(failed.Write());
}
- SendPacket(&data);
- */
}
void WorldSession::SendCharFactionChange(ResponseCodes result, WorldPackets::Character::CharRaceOrFactionChangeInfo const* factionChangeInfo)
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index b5550c2c073..b9fd383b19d 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -288,7 +288,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false, group->GetMemberGroup(GetPlayer()->GetGUID()));
break;
}
@@ -320,8 +320,8 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
}
case CHAT_MSG_RAID:
{
- Group* group = GetPlayer()->GetOriginalGroup();
- if (!group)
+ Group* group = GetPlayer()->GetGroup();
+ if (!group || !group->isRaidGroup() || group->isBGGroup())
return;
if (group->IsLeader(GetPlayer()->GetGUID()))
@@ -330,7 +330,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -344,7 +344,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
WorldPackets::Chat::Chat packet;
//in battleground, raid warning is sent only to players in battleground - code is ok
- packet.Initalize(CHAT_MSG_RAID_WARNING, Language(lang), sender, NULL, msg);
+ packet.Initialize(CHAT_MSG_RAID_WARNING, Language(lang), sender, NULL, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -381,7 +381,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -484,7 +484,7 @@ void WorldSession::HandleChatAddonMessage(ChatMsg type, std::string prefix, std:
}
WorldPackets::Chat::Chat packet;
- packet.Initalize(type, LANG_ADDON, sender, nullptr, text, 0, "", DEFAULT_LOCALE, prefix);
+ packet.Initialize(type, LANG_ADDON, sender, nullptr, text, 0, "", DEFAULT_LOCALE, prefix);
group->BroadcastAddonMessagePacket(packet.Write(), prefix, true, subGroup, sender->GetGUID());
break;
}
@@ -666,7 +666,7 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData)
return;
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_IGNORED, LANG_UNIVERSAL, _player, _player, GetPlayer()->GetName());
+ packet.Initialize(CHAT_MSG_IGNORED, LANG_UNIVERSAL, _player, _player, GetPlayer()->GetName());
player->SendDirectMessage(packet.Write());
}
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 9552c9a0655..eefe89fef74 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -35,6 +35,7 @@
#include "SpellAuraEffects.h"
#include "MiscPackets.h"
#include "LootPackets.h"
+#include "PartyPackets.h"
class Aura;
@@ -51,103 +52,59 @@ class Aura;
void WorldSession::SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res, uint32 val /* = 0 */)
{
- WorldPacket data(SMSG_PARTY_COMMAND_RESULT, 4 + member.size() + 1 + 4 + 4 + 8);
- data << uint32(operation);
- data << member;
- data << uint32(res);
- data << uint32(val); // LFD cooldown related (used with ERR_PARTY_LFG_BOOT_COOLDOWN_S and ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S)
- data << uint64(0); // player who caused error (in some cases).
-
- SendPacket(&data);
-}
-
-void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
-{
- ObjectGuid crossRealmGuid; // unused
-
- recvData.read_skip<uint32>(); // Non-zero in cross realm invites
- recvData.read_skip<uint32>(); // Always 0
-
- crossRealmGuid[2] = recvData.ReadBit();
- crossRealmGuid[7] = recvData.ReadBit();
-
- uint8 realmLen = recvData.ReadBits(9);
-
- crossRealmGuid[3] = recvData.ReadBit();
-
- uint8 nameLen = recvData.ReadBits(10);
-
- crossRealmGuid[5] = recvData.ReadBit();
- crossRealmGuid[4] = recvData.ReadBit();
- crossRealmGuid[6] = recvData.ReadBit();
- crossRealmGuid[0] = recvData.ReadBit();
- crossRealmGuid[1] = recvData.ReadBit();
+ WorldPackets::Party::PartyCommandResult packet;
- recvData.ReadByteSeq(crossRealmGuid[4]);
- recvData.ReadByteSeq(crossRealmGuid[7]);
- recvData.ReadByteSeq(crossRealmGuid[6]);
+ packet.Name = member;
+ packet.Command = uint8(operation);
+ packet.Result = uint8(res);
+ packet.ResultData = val;
+ packet.ResultGUID = ObjectGuid::Empty;
- std::string memberName, realmName;
- memberName = recvData.ReadString(nameLen);
- realmName = recvData.ReadString(realmLen); // unused
-
- recvData.ReadByteSeq(crossRealmGuid[1]);
- recvData.ReadByteSeq(crossRealmGuid[0]);
- recvData.ReadByteSeq(crossRealmGuid[5]);
- recvData.ReadByteSeq(crossRealmGuid[3]);
- recvData.ReadByteSeq(crossRealmGuid[2]);
-
- // attempt add selected player
-
- // cheating
- if (!normalizePlayerName(memberName))
- {
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
- return;
- }
+ SendPacket(packet.Write());
+}
- Player* player = ObjectAccessor::FindPlayerByName(memberName);
+void WorldSession::HandlePartyInviteOpcode(WorldPackets::Party::PartyInviteClient& packet)
+{
+ Player* player = ObjectAccessor::FindPlayerByName(packet.TargetName);
// no player
if (!player)
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, packet.TargetName, ERR_BAD_PLAYER_NAME_S);
return;
}
// restrict invite to GMs
if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->IsGameMaster() && player->IsGameMaster())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_BAD_PLAYER_NAME_S);
return;
}
// can't group with
if (!GetPlayer()->IsGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PLAYER_WRONG_FACTION);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_PLAYER_WRONG_FACTION);
return;
}
if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_TARGET_NOT_IN_INSTANCE_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_TARGET_NOT_IN_INSTANCE_S);
return;
}
// just ignore us
if (player->GetInstanceId() != 0 && player->GetDungeonDifficultyID() != GetPlayer()->GetDungeonDifficultyID())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_IGNORING_YOU_S);
return;
}
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUID()))
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_IGNORING_YOU_S);
return;
}
- ObjectGuid invitedGuid = player->GetGUID();
-
Group* group = GetPlayer()->GetGroup();
if (group && group->isBGGroup())
group = GetPlayer()->GetOriginalGroup();
@@ -155,67 +112,18 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
Group* group2 = player->GetGroup();
if (group2 && group2->isBGGroup())
group2 = player->GetOriginalGroup();
+
// player already in another group or invited
if (group2 || player->GetGroupInvite())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_ALREADY_IN_GROUP_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_ALREADY_IN_GROUP_S);
if (group2)
{
// tell the player that they were invited but it failed as they were already in a group
- WorldPacket data(SMSG_PARTY_INVITE, 45);
-
- data.WriteBit(0);
-
- data.WriteBit(invitedGuid[0]);
- data.WriteBit(invitedGuid[3]);
- data.WriteBit(invitedGuid[2]);
-
- data.WriteBit(0); // Inverse already in group
-
- data.WriteBit(invitedGuid[6]);
- data.WriteBit(invitedGuid[5]);
-
- data.WriteBits(0, 9); // Realm name
-
- data.WriteBit(invitedGuid[4]);
-
- data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length
-
- data.WriteBits(0, 24); // Count 2
-
- data.WriteBit(0);
-
- data.WriteBit(invitedGuid[1]);
- data.WriteBit(invitedGuid[7]);
-
- data.FlushBits();
-
- data.WriteByteSeq(invitedGuid[1]);
- data.WriteByteSeq(invitedGuid[4]);
-
- data << int32(getMSTime());
- data << int32(0);
- data << int32(0);
-
- data.WriteByteSeq(invitedGuid[6]);
- data.WriteByteSeq(invitedGuid[0]);
- data.WriteByteSeq(invitedGuid[2]);
- data.WriteByteSeq(invitedGuid[3]);
-
- // for count2 { int32(0) }
-
- data.WriteByteSeq(invitedGuid[5]);
-
- // data.append(realm name);
-
- data.WriteByteSeq(invitedGuid[7]);
-
- data.WriteString(GetPlayer()->GetName()); // inviter name
-
- data << int32(0);
-
- player->GetSession()->SendPacket(&data);
+ WorldPackets::Party::PartyInvite partyInvite;
+ partyInvite.Initialize(GetPlayer(), packet.ProposedRoles, false);
+ player->GetSession()->SendPacket(partyInvite.Write());
}
return;
@@ -264,79 +172,21 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
}
}
- // ok, we do it
- WorldPacket data(SMSG_PARTY_INVITE, 45);
-
- data.WriteBit(0);
-
- data.WriteBit(invitedGuid[0]);
- data.WriteBit(invitedGuid[3]);
- data.WriteBit(invitedGuid[2]);
-
- data.WriteBit(1); // Inverse already in group
-
- data.WriteBit(invitedGuid[6]);
- data.WriteBit(invitedGuid[5]);
-
- data.WriteBits(0, 9); // Realm name
-
- data.WriteBit(invitedGuid[4]);
-
- data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length
-
- data.WriteBits(0, 24); // Count 2
-
- data.WriteBit(0);
-
- data.WriteBit(invitedGuid[1]);
- data.WriteBit(invitedGuid[7]);
-
- data.FlushBits();
+ WorldPackets::Party::PartyInvite partyInvite;
+ partyInvite.Initialize(GetPlayer(), packet.ProposedRoles, true);
+ player->GetSession()->SendPacket(partyInvite.Write());
- data.WriteByteSeq(invitedGuid[1]);
- data.WriteByteSeq(invitedGuid[4]);
-
- data << int32(getMSTime());
- data << int32(0);
- data << int32(0);
-
- data.WriteByteSeq(invitedGuid[6]);
- data.WriteByteSeq(invitedGuid[0]);
- data.WriteByteSeq(invitedGuid[2]);
- data.WriteByteSeq(invitedGuid[3]);
-
- // for count2 { int32(0) }
-
- data.WriteByteSeq(invitedGuid[5]);
-
- // data.append(realm name);
-
- data.WriteByteSeq(invitedGuid[7]);
-
- data.WriteString(GetPlayer()->GetName());
-
- data << int32(0);
-
- player->GetSession()->SendPacket(&data);
-
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PARTY_RESULT_OK);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_PARTY_RESULT_OK);
}
-void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData)
+void WorldSession::HandlePartyInviteResponseOpcode(WorldPackets::Party::PartyInviteResponse& packet)
{
- recvData.ReadBit(); // unk always 0
- bool accept = recvData.ReadBit();
-
- // Never actually received?
- /*if (accept)
- recvData.read_skip<uint32>(); // unk*/
-
Group* group = GetPlayer()->GetGroupInvite();
if (!group)
return;
- if (accept)
+ if (packet.Accept)
{
// Remove player from invitees in any case
group->RemoveInvite(GetPlayer());
@@ -391,28 +241,22 @@ void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData)
return;
// report
- WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().size());
- data << GetPlayer()->GetName();
- leader->GetSession()->SendPacket(&data);
+ WorldPackets::Party::GroupDecline decline(GetPlayer()->GetName());
+ leader->GetSession()->SendPacket(decline.Write());
}
}
-void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData)
+void WorldSession::HandlePartyUninviteOpcode(WorldPackets::Party::PartyUninvite& packet)
{
- ObjectGuid guid;
- std::string reason;
- recvData >> guid;
- recvData >> reason;
-
- //can't uninvite yourself
- if (guid == GetPlayer()->GetGUID())
+ // can't uninvite yourself
+ if (packet.TargetGUID == GetPlayer()->GetGUID())
{
TC_LOG_ERROR("network", "WorldSession::HandleGroupUninviteGuidOpcode: leader %s (%s) tried to uninvite himself from the group.",
GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().ToString().c_str());
return;
}
- PartyResult res = GetPlayer()->CanUninviteFromGroup(guid);
+ PartyResult res = GetPlayer()->CanUninviteFromGroup(packet.TargetGUID);
if (res != ERR_PARTY_RESULT_OK)
{
SendPartyResult(PARTY_OP_UNINVITE, "", res);
@@ -423,13 +267,13 @@ void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData)
// grp is checked already above in CanUninviteFromGroup()
ASSERT(grp);
- if (grp->IsMember(guid))
+ if (grp->IsMember(packet.TargetGUID))
{
- Player::RemoveFromGroup(grp, guid, GROUP_REMOVEMETHOD_KICK, GetPlayer()->GetGUID(), reason.c_str());
+ Player::RemoveFromGroup(grp, packet.TargetGUID, GROUP_REMOVEMETHOD_KICK, GetPlayer()->GetGUID(), packet.Reason.c_str());
return;
}
- if (Player* player = grp->GetInvited(guid))
+ if (Player* player = grp->GetInvited(packet.TargetGUID))
{
player->UninviteFromGroup();
return;
@@ -438,12 +282,9 @@ void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData)
SendPartyResult(PARTY_OP_UNINVITE, "", ERR_TARGET_NOT_IN_GROUP_S);
}
-void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData)
+void WorldSession::HandleSetPartyLeaderOpcode(WorldPackets::Party::SetPartyLeader& packet)
{
- ObjectGuid guid;
- recvData >> guid;
-
- Player* player = ObjectAccessor::FindConnectedPlayer(guid);
+ Player* player = ObjectAccessor::FindConnectedPlayer(packet.TargetGUID);
Group* group = GetPlayer()->GetGroup();
if (!group || !player)
@@ -453,87 +294,35 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData)
return;
// Everything's fine, accepted.
- group->ChangeLeader(guid);
+ group->ChangeLeader(packet.TargetGUID, packet.PartyIndex);
group->SendUpdate();
}
-void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData)
+void WorldSession::HandleSetRoleOpcode(WorldPackets::Party::SetRole& packet)
{
- uint32 newRole;
- ObjectGuid guid1; // Assigner GUID
- ObjectGuid guid2; // Target GUID
-
- guid1 = GetPlayer()->GetGUID();
-
- recvData >> newRole;
-
- guid2[2] = recvData.ReadBit();
- guid2[6] = recvData.ReadBit();
- guid2[3] = recvData.ReadBit();
- guid2[7] = recvData.ReadBit();
- guid2[5] = recvData.ReadBit();
- guid2[1] = recvData.ReadBit();
- guid2[0] = recvData.ReadBit();
- guid2[4] = recvData.ReadBit();
-
- recvData.ReadByteSeq(guid2[6]);
- recvData.ReadByteSeq(guid2[4]);
- recvData.ReadByteSeq(guid2[1]);
- recvData.ReadByteSeq(guid2[3]);
- recvData.ReadByteSeq(guid2[0]);
- recvData.ReadByteSeq(guid2[5]);
- recvData.ReadByteSeq(guid2[2]);
- recvData.ReadByteSeq(guid2[7]);
-
- WorldPacket data(SMSG_ROLE_CHANGED_INFORM, 24);
-
- data.WriteBit(guid1[1]);
- data.WriteBit(guid2[0]);
- data.WriteBit(guid2[2]);
- data.WriteBit(guid2[4]);
- data.WriteBit(guid2[7]);
- data.WriteBit(guid2[3]);
- data.WriteBit(guid1[7]);
- data.WriteBit(guid2[5]);
- data.WriteBit(guid1[5]);
- data.WriteBit(guid1[4]);
- data.WriteBit(guid1[3]);
- data.WriteBit(guid2[6]);
- data.WriteBit(guid1[2]);
- data.WriteBit(guid1[6]);
- data.WriteBit(guid2[1]);
- data.WriteBit(guid1[0]);
-
- data.WriteByteSeq(guid1[7]);
- data.WriteByteSeq(guid2[3]);
- data.WriteByteSeq(guid1[6]);
- data.WriteByteSeq(guid2[4]);
- data.WriteByteSeq(guid2[0]);
- data << uint32(newRole); // New Role
- data.WriteByteSeq(guid2[6]);
- data.WriteByteSeq(guid2[2]);
- data.WriteByteSeq(guid1[0]);
- data.WriteByteSeq(guid1[4]);
- data.WriteByteSeq(guid2[1]);
- data.WriteByteSeq(guid1[3]);
- data.WriteByteSeq(guid1[5]);
- data.WriteByteSeq(guid1[2]);
- data.WriteByteSeq(guid2[5]);
- data.WriteByteSeq(guid2[7]);
- data.WriteByteSeq(guid1[1]);
- data << uint32(0); // Old Role
-
- if (Group* group = GetPlayer()->GetGroup())
+ WorldPackets::Party::RoleChangedInform roleChangedInform;
+
+ Group* group = GetPlayer()->GetGroup();
+ uint8 oldRole = group ? group->GetLfgRoles(packet.TargetGUID) : 0;
+ if (oldRole == packet.Role)
+ return;
+
+ roleChangedInform.PartyIndex = packet.PartyIndex;
+ roleChangedInform.From = GetPlayer()->GetGUID();
+ roleChangedInform.ChangedUnit = packet.TargetGUID;
+ roleChangedInform.OldRole = oldRole;
+ roleChangedInform.NewRole = packet.Role;
+
+ if (group)
{
- /// @todo probably should be sent only if (oldRole != newRole)
- group->BroadcastPacket(&data, false);
- group->SetLfgRoles(guid2, newRole);
+ group->BroadcastPacket(roleChangedInform.Write(), false);
+ group->SetLfgRoles(packet.TargetGUID, packet.Role);
}
else
- SendPacket(&data);
+ SendPacket(roleChangedInform.Write());
}
-void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/)
+void WorldSession::HandleLeaveGroupOpcode(WorldPackets::Party::LeaveGroup& /*packet*/)
{
Group* grp = GetPlayer()->GetGroup();
if (!grp)
@@ -554,13 +343,8 @@ void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/)
GetPlayer()->RemoveFromGroup(GROUP_REMOVEMETHOD_LEAVE);
}
-void WorldSession::HandleLootMethodOpcode(WorldPacket& recvData)
+void WorldSession::HandleSetLootMethodOpcode(WorldPackets::Party::SetLootMethod& packet)
{
- uint32 lootMethod;
- ObjectGuid lootMaster;
- uint32 lootThreshold;
- recvData >> lootMethod >> lootMaster >> lootThreshold;
-
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
@@ -569,20 +353,20 @@ void WorldSession::HandleLootMethodOpcode(WorldPacket& recvData)
if (!group->IsLeader(GetPlayer()->GetGUID()))
return;
- if (lootMethod > NEED_BEFORE_GREED)
+ if (packet.LootMethod > NEED_BEFORE_GREED)
return;
- if (lootThreshold < ITEM_QUALITY_UNCOMMON || lootThreshold > ITEM_QUALITY_ARTIFACT)
+ if (packet.LootThreshold < ITEM_QUALITY_UNCOMMON || packet.LootThreshold > ITEM_QUALITY_ARTIFACT)
return;
- if (lootMethod == MASTER_LOOT && !group->IsMember(lootMaster))
+ if (packet.LootMethod == MASTER_LOOT && !group->IsMember(packet.LootMasterGUID))
return;
/********************/
// everything's fine, do it
- group->SetLootMethod((LootMethod)lootMethod);
- group->SetMasterLooterGuid(lootMaster);
- group->SetLootThreshold((ItemQualities)lootThreshold);
+ group->SetLootMethod((LootMethod)packet.LootMethod);
+ group->SetMasterLooterGuid(packet.LootMasterGUID);
+ group->SetLootThreshold((ItemQualities)packet.LootThreshold);
group->SendUpdate();
}
@@ -605,28 +389,16 @@ void WorldSession::HandleLootRoll(WorldPackets::Loot::LootRoll& packet)
}
}
-void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData)
+void WorldSession::HandleMinimapPingOpcode(WorldPackets::Party::MinimapPingClient& packet)
{
- TC_LOG_DEBUG("network", "WORLD: Received MSG_MINIMAP_PING");
-
if (!GetPlayer()->GetGroup())
return;
- float x, y;
- recvData >> x;
- recvData >> y;
-
- //TC_LOG_DEBUG("misc", "Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
-
- /** error handling **/
- /********************/
-
- // everything's fine, do it
- WorldPacket data(SMSG_MINIMAP_PING, (8+4+4));
- data << GetPlayer()->GetGUID();
- data << float(x);
- data << float(y);
- GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID());
+ WorldPackets::Party::MinimapPing minimapPing;
+ minimapPing.Sender = GetPlayer()->GetGUID();
+ minimapPing.PositionX = packet.PositionX;
+ minimapPing.PositionY = packet.PositionY;
+ GetPlayer()->GetGroup()->BroadcastPacket(minimapPing.Write(), true, -1, GetPlayer()->GetGUID());
}
void WorldSession::HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient& packet)
@@ -643,8 +415,6 @@ void WorldSession::HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient&
// everything's fine, do it
roll = urand(minimum, maximum);
- //TC_LOG_DEBUG("misc", "ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
-
WorldPackets::Misc::RandomRoll randomRoll;
randomRoll.Min = minimum;
randomRoll.Max = maximum;
@@ -657,44 +427,31 @@ void WorldSession::HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient&
SendPacket(randomRoll.Write());
}
-void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
+void WorldSession::HandleUpdateRaidTargetOpcode(WorldPackets::Party::UpdateRaidTarget& packet)
{
- TC_LOG_DEBUG("network", "WORLD: Received MSG_RAID_TARGET_UPDATE");
-
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- uint8 x;
- recvData >> x;
-
- /** error handling **/
- /********************/
-
- // everything's fine, do it
- if (x == 0xFF) // target icon request
- group->SendTargetIconList(this);
- else // target icon update
+ if (packet.Symbol == 0xFF) // target icon request
+ group->SendTargetIconList(this, packet.PartyIndex);
+ else // target icon update
{
if (group->isRaidGroup() && !group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
return;
- ObjectGuid guid;
- recvData >> guid;
-
- if (guid.IsPlayer())
+ if (packet.Target.IsPlayer())
{
- Player* target = ObjectAccessor::FindConnectedPlayer(guid);
-
+ Player* target = ObjectAccessor::FindConnectedPlayer(packet.Target);
if (!target || target->IsHostileTo(GetPlayer()))
return;
}
- group->SetTargetIcon(x, _player->GetGUID(), guid);
+ group->SetTargetIcon(packet.Symbol, packet.Target, GetPlayer()->GetGUID(), packet.PartyIndex);
}
}
-void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData)
+void WorldSession::HandleConvertRaidOpcode(WorldPackets::Party::ConvertRaid& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
@@ -711,71 +468,56 @@ void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData)
SendPartyResult(PARTY_OP_INVITE, "", ERR_PARTY_RESULT_OK);
// New 4.x: it is now possible to convert a raid to a group if member count is 5 or less
-
- bool toRaid;
- recvData >> toRaid;
-
- if (toRaid)
+ if (packet.Raid)
group->ConvertToRaid();
else
group->ConvertToGroup();
}
-void WorldSession::HandleGroupRequestJoinUpdates(WorldPacket& /*recvData*/)
+void WorldSession::HandleRequestPartyJoinUpdates(WorldPackets::Party::RequestPartyJoinUpdates& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- // does some stuff. dunno what.
+ group->SendTargetIconList(this, packet.PartyIndex);
+ group->SendRaidMarkersChanged(this, packet.PartyIndex);
}
-void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
+void WorldSession::HandleChangeSubGroupOpcode(WorldPackets::Party::ChangeSubGroup& packet)
{
// we will get correct pointer for group here, so we don't have to check if group is BG raid
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- std::string name;
- uint8 groupNr;
- recvData >> name;
- recvData >> groupNr;
-
- if (groupNr >= MAX_RAID_SUBGROUPS)
+ if (packet.NewSubGroup >= MAX_RAID_SUBGROUPS)
return;
ObjectGuid senderGuid = GetPlayer()->GetGUID();
if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid))
return;
- if (!group->HasFreeSlotSubGroup(groupNr))
+ if (!group->HasFreeSlotSubGroup(packet.NewSubGroup))
return;
- Player* movedPlayer = ObjectAccessor::FindConnectedPlayerByName(name);
- ObjectGuid guid;
-
- if (movedPlayer)
- guid = movedPlayer->GetGUID();
- else
- {
- CharacterDatabase.EscapeString(name);
- guid = ObjectMgr::GetPlayerGUIDByName(name.c_str());
- }
-
- group->ChangeMembersGroup(guid, groupNr);
+ group->ChangeMembersGroup(packet.TargetGUID, packet.NewSubGroup);
}
-void WorldSession::HandleGroupSwapSubGroupOpcode(WorldPacket& recvData)
+void WorldSession::HandleSwapSubGroupsOpcode(WorldPackets::Party::SwapSubGroups& packet)
{
- std::string unk1;
- std::string unk2;
+ Group* group = GetPlayer()->GetGroup();
+ if (!group)
+ return;
- recvData >> unk1;
- recvData >> unk2;
+ ObjectGuid senderGuid = GetPlayer()->GetGUID();
+ if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid))
+ return;
+
+ group->SwapMembersGroups(packet.FirstTarget, packet.SecondTarget);
}
-void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData)
+void WorldSession::HandleSetAssistantLeaderOpcode(WorldPackets::Party::SetAssistantLeader& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
@@ -784,12 +526,7 @@ void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData)
if (!group->IsLeader(GetPlayer()->GetGUID()))
return;
- ObjectGuid guid;
- bool apply;
- recvData >> guid;
- recvData >> apply;
-
- group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_ASSISTANT);
+ group->SetGroupMemberFlag(packet.Target, packet.Apply, MEMBER_FLAG_ASSISTANT);
}
void WorldSession::HandlePartyAssignmentOpcode(WorldPacket& recvData)
@@ -826,509 +563,102 @@ void WorldSession::HandlePartyAssignmentOpcode(WorldPacket& recvData)
group->SendUpdate();
}
-void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData)
+void WorldSession::HandleDoReadyCheckOpcode(WorldPackets::Party::DoReadyCheck& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- if (recvData.empty()) // request
- {
- /** error handling **/
- if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
- return;
- /********************/
-
- // everything's fine, do it
- WorldPacket data(SMSG_READY_CHECK_STARTED, 8);
- data << GetPlayer()->GetGUID();
- group->BroadcastPacket(&data, false, -1);
+ /** error handling **/
+ if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
+ return;
+ /********************/
- group->OfflineReadyCheck();
- }
- else // answer
- {
- uint8 state;
- recvData >> state;
-
- // everything's fine, do it
- WorldPacket data(SMSG_READY_CHECK_RESPONSE, 9);
- data << GetPlayer()->GetGUID();
- data << uint8(state);
- group->BroadcastReadyCheck(&data);
- }
+ // everything's fine, do it
+ group->StartReadyCheck(GetPlayer()->GetGUID(), packet.PartyIndex);
}
-void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data)
+void WorldSession::HandleReadyCheckResponseOpcode(WorldPackets::Party::ReadyCheckResponseClient& packet)
{
- uint32 mask = player->GetGroupUpdateFlag();
-
- if (mask == GROUP_UPDATE_FLAG_NONE)
+ Group* group = GetPlayer()->GetGroup();
+ if (!group)
return;
- std::set<uint32> const& phases = player->GetPhases();
-
- if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also
- mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER);
-
- if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets
- mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);
-
- data->Initialize(SMSG_PARTY_MEMBER_STATE, 80); // average value
- *data << player->GetPackGUID();
- *data << uint32(mask);
-
- if (mask & GROUP_UPDATE_FLAG_STATUS)
- {
- uint16 playerStatus = MEMBER_STATUS_ONLINE;
- if (player->IsPvP())
- playerStatus |= MEMBER_STATUS_PVP;
-
- if (!player->IsAlive())
- {
- if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
- playerStatus |= MEMBER_STATUS_GHOST;
- else
- playerStatus |= MEMBER_STATUS_DEAD;
- }
-
- if (player->IsFFAPvP())
- playerStatus |= MEMBER_STATUS_PVP_FFA;
-
- if (player->isAFK())
- playerStatus |= MEMBER_STATUS_AFK;
-
- if (player->isDND())
- playerStatus |= MEMBER_STATUS_DND;
-
- *data << uint16(playerStatus);
- }
-
- if (mask & GROUP_UPDATE_FLAG_CUR_HP)
- *data << uint32(player->GetHealth());
-
- if (mask & GROUP_UPDATE_FLAG_MAX_HP)
- *data << uint32(player->GetMaxHealth());
-
- Powers powerType = player->getPowerType();
- if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
- *data << uint8(powerType);
-
- if (mask & GROUP_UPDATE_FLAG_CUR_POWER)
- *data << uint16(player->GetPower(powerType));
-
- if (mask & GROUP_UPDATE_FLAG_MAX_POWER)
- *data << uint16(player->GetMaxPower(powerType));
-
- if (mask & GROUP_UPDATE_FLAG_LEVEL)
- *data << uint16(player->getLevel());
-
- if (mask & GROUP_UPDATE_FLAG_ZONE)
- *data << uint16(player->GetZoneId());
-
- if (mask & GROUP_UPDATE_FLAG_UNK100)
- *data << uint16(0);
-
- if (mask & GROUP_UPDATE_FLAG_POSITION)
- {
- *data << uint16(player->GetPositionX());
- *data << uint16(player->GetPositionY());
- *data << uint16(player->GetPositionZ());
- }
-
- if (mask & GROUP_UPDATE_FLAG_AURAS)
- {
- *data << uint8(0);
- uint64 auramask = player->GetAuraUpdateMaskForRaid();
- *data << uint64(auramask);
- *data << uint32(MAX_AURAS); // count
- for (uint32 i = 0; i < MAX_AURAS; ++i)
- {
- if (auramask & (uint64(1) << i))
- {
- AuraApplication const* aurApp = player->GetVisibleAura(i);
- if (!aurApp)
- {
- *data << uint32(0);
- *data << uint16(0);
- continue;
- }
-
- *data << uint32(aurApp->GetBase()->GetId());
- *data << uint16(aurApp->GetFlags());
-
- if (aurApp->GetFlags() & AFLAG_SCALABLE)
- {
- for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
- *data << int32(eff->GetAmount());
- else
- *data << int32(0);
- }
- }
- }
- }
- }
-
- Pet* pet = player->GetPet();
- if (mask & GROUP_UPDATE_FLAG_PET_GUID)
- {
- if (pet)
- *data << pet->GetGUID();
- else
- *data << ObjectGuid::Empty;
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_NAME)
- {
- if (pet)
- *data << pet->GetName();
- else
- *data << uint8(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID)
- {
- if (pet)
- *data << uint16(pet->GetDisplayId());
- else
- *data << uint16(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
- {
- if (pet)
- *data << uint32(pet->GetHealth());
- else
- *data << uint32(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
- {
- if (pet)
- *data << uint32(pet->GetMaxHealth());
- else
- *data << uint32(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
- {
- if (pet)
- *data << uint8(pet->getPowerType());
- else
- *data << uint8(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER)
- {
- if (pet)
- *data << uint16(pet->GetPower(pet->getPowerType()));
- else
- *data << uint16(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER)
- {
- if (pet)
- *data << uint16(pet->GetMaxPower(pet->getPowerType()));
- else
- *data << uint16(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_AURAS)
- {
- if (pet)
- {
- *data << uint8(0);
- uint64 auramask = pet->GetAuraUpdateMaskForRaid();
- *data << uint64(auramask);
- *data << uint32(MAX_AURAS); // count
- for (uint32 i = 0; i < MAX_AURAS; ++i)
- {
- if (auramask & (uint64(1) << i))
- {
- AuraApplication const* aurApp = pet->GetVisibleAura(i);
- if (!aurApp)
- {
- *data << uint32(0);
- *data << uint16(0);
- continue;
- }
-
- *data << uint32(aurApp->GetBase()->GetId());
- *data << uint16(aurApp->GetFlags());
-
- if (aurApp->GetFlags() & AFLAG_SCALABLE)
- {
- for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
- *data << int32(eff->GetAmount());
- else
- *data << int32(0);
- }
- }
- }
- }
- }
- else
- {
- *data << uint8(0);
- *data << uint64(0);
- }
- }
-
- if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
- {
- if (Vehicle* veh = player->GetVehicle())
- *data << uint32(veh->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat]);
- else
- *data << uint32(0);
-
- }
-
- if (mask & GROUP_UPDATE_FLAG_PHASE)
- {
- *data << uint32(phases.empty() ? 8 : 0);
- *data << uint32(phases.size());
- for (std::set<uint32>::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- *data << uint16(*itr);
- }
+ // everything's fine, do it
+ group->SetMemberReadyCheck(GetPlayer()->GetGUID(), packet.IsReady);
}
-/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
-void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData)
+void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPackets::Party::RequestPartyMemberStats& packet)
{
- ObjectGuid Guid;
- recvData >> Guid;
+ WorldPackets::Party::PartyMemberStats partyMemberStats;
- Player* player = ObjectAccessor::FindConnectedPlayer(Guid);
+ Player* player = ObjectAccessor::FindConnectedPlayer(packet.TargetGUID);
if (!player)
{
- WorldPacket data(SMSG_PARTY_MEMBER_STATE, 3 + 4 + 2);
- data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
- data << Guid.WriteAsPacked();
- data << uint32(GROUP_UPDATE_FLAG_STATUS);
- data << uint16(MEMBER_STATUS_OFFLINE);
- SendPacket(&data);
- return;
- }
-
- Pet* pet = player->GetPet();
- Powers powerType = player->getPowerType();
- std::set<uint32> const& phases = player->GetPhases();
-
- WorldPacket data(SMSG_PARTY_MEMBER_STATE, 4 + 2 + 2 + 2 + 1 + 2 * 6 + 8 + 1 + 8);
- data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
- data << player->GetPackGUID();
-
- uint32 updateFlags = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP
- | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL
- | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS
- | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID | GROUP_UPDATE_FLAG_PET_AURAS;
-
- if (powerType != POWER_MANA)
- updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE;
-
- if (pet)
- updateFlags |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP
- | GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER;
-
- if (player->GetVehicle())
- updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT;
-
- if (!phases.empty())
- updateFlags |= GROUP_UPDATE_FLAG_PHASE;
-
- uint16 playerStatus = MEMBER_STATUS_ONLINE;
- if (player->IsPvP())
- playerStatus |= MEMBER_STATUS_PVP;
-
- if (!player->IsAlive())
- {
- if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
- playerStatus |= MEMBER_STATUS_GHOST;
- else
- playerStatus |= MEMBER_STATUS_DEAD;
- }
-
- if (player->IsFFAPvP())
- playerStatus |= MEMBER_STATUS_PVP_FFA;
-
- if (player->isAFK())
- playerStatus |= MEMBER_STATUS_AFK;
-
- if (player->isDND())
- playerStatus |= MEMBER_STATUS_DND;
-
- data << uint32(updateFlags);
- data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS
- data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP
- data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP
- if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE)
- data << uint8(powerType);
-
- data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER
- data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER
- data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL
- data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE
- data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION
- data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION
- data << uint16(player->GetPositionZ()); // GROUP_UPDATE_FLAG_POSITION
-
- // GROUP_UPDATE_FLAG_AURAS
- data << uint8(1);
- uint64 auramask = 0;
- size_t maskPos = data.wpos();
- data << uint64(auramask); // placeholder
- data << uint32(MAX_AURAS); // count
-
- for (uint8 i = 0; i < MAX_AURAS; ++i)
- {
- if (AuraApplication const* aurApp = player->GetVisibleAura(i))
- {
- auramask |= (uint64(1) << i);
-
- data << uint32(aurApp->GetBase()->GetId());
- data << uint16(aurApp->GetFlags());
-
- if (aurApp->GetFlags() & AFLAG_SCALABLE)
- {
- for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
- data << int32(eff->GetAmount());
- else
- data << int32(0);
- }
- }
- }
- }
-
- data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID)
- data << pet->GetGUID();
-
- data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME
- data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_HP)
- data << uint32(pet->GetHealth());
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_HP)
- data << uint32(pet->GetMaxHealth());
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
- data << (uint8)pet->getPowerType();
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_POWER)
- data << uint16(pet->GetPower(pet->getPowerType()));
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER)
- data << uint16(pet->GetMaxPower(pet->getPowerType()));
-
- // GROUP_UPDATE_FLAG_PET_AURAS
- uint64 petAuraMask = 0;
- data << uint8(1);
- maskPos = data.wpos();
- data << uint64(petAuraMask); // placeholder
- data << uint32(MAX_AURAS); // count
- if (pet)
- {
- for (uint8 i = 0; i < MAX_AURAS; ++i)
- {
- if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
- {
- petAuraMask |= (uint64(1) << i);
-
- data << uint32(aurApp->GetBase()->GetId());
- data << uint16(aurApp->GetFlags());
-
- if (aurApp->GetFlags() & AFLAG_SCALABLE)
- {
- for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
- data << int32(eff->GetAmount());
- else
- data << int32(0);
- }
- }
- }
- }
- }
-
- data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS
-
- if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
- data << uint32(player->GetVehicle()->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat]);
-
- if (updateFlags & GROUP_UPDATE_FLAG_PHASE)
- {
- data << uint32(phases.empty() ? 8 : 0);
- data << uint32(phases.size());
- for (std::set<uint32>::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- data << uint16(*itr);
+ partyMemberStats.MemberStats.GUID = packet.TargetGUID;
+ partyMemberStats.MemberStats.Status = MEMBER_STATUS_OFFLINE;
}
+ else
+ partyMemberStats.Initialize(player);
- SendPacket(&data);
+ SendPacket(partyMemberStats.Write());
}
-void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket& /*recvData*/)
+void WorldSession::HandleRequestRaidInfoOpcode(WorldPackets::Party::RequestRaidInfo& /*packet*/)
{
// every time the player checks the character screen
_player->SendRaidInfo();
}
-void WorldSession::HandleOptOutOfLootOpcode(WorldPacket& recvData)
+void WorldSession::HandleOptOutOfLootOpcode(WorldPackets::Party::OptOutOfLoot& packet)
{
- bool passOnLoot;
- recvData >> passOnLoot; // 1 always pass, 0 do not pass
-
// ignore if player not loaded
if (!GetPlayer()) // needed because STATUS_AUTHED
{
- if (passOnLoot)
+ if (packet.PassOnLoot)
TC_LOG_ERROR("network", "CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!");
return;
}
- GetPlayer()->SetPassOnGroupLoot(passOnLoot != 0);
+ GetPlayer()->SetPassOnGroupLoot(packet.PassOnLoot);
}
-void WorldSession::HandleRolePollBeginOpcode(WorldPacket& recvData)
+void WorldSession::HandleInitiateRolePoll(WorldPackets::Party::InitiateRolePoll& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- if (recvData.empty())
- {
- if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
- return;
+ ObjectGuid guid = GetPlayer()->GetGUID();
+ if (!group->IsLeader(guid) && !group->IsAssistant(guid))
+ return;
- ObjectGuid guid = GetPlayer()->GetGUID();
-
- WorldPacket data(SMSG_ROLE_POLL_INFORM, 8);
- data.WriteBit(guid[1]);
- data.WriteBit(guid[5]);
- data.WriteBit(guid[7]);
- data.WriteBit(guid[3]);
- data.WriteBit(guid[2]);
- data.WriteBit(guid[4]);
- data.WriteBit(guid[0]);
- data.WriteBit(guid[6]);
- data.WriteByteSeq(guid[4]);
- data.WriteByteSeq(guid[7]);
- data.WriteByteSeq(guid[0]);
- data.WriteByteSeq(guid[5]);
- data.WriteByteSeq(guid[1]);
- data.WriteByteSeq(guid[6]);
- data.WriteByteSeq(guid[2]);
- data.WriteByteSeq(guid[3]);
-
- GetPlayer()->GetGroup()->BroadcastPacket(&data, true);
- }
+ WorldPackets::Party::RolePollInform rolePollInform;
+ rolePollInform.From = GetPlayer()->GetGUID();
+ rolePollInform.PartyIndex = packet.PartyIndex;
+ group->BroadcastPacket(rolePollInform.Write(), true);
+}
+
+void WorldSession::HandleSetEveryoneIsAssistant(WorldPackets::Party::SetEveryoneIsAssistant& packet)
+{
+ Group* group = GetPlayer()->GetGroup();
+ if (!group)
+ return;
+
+ if (!group->IsLeader(GetPlayer()->GetGUID()))
+ return;
+
+ group->SetEveryoneIsAssistant(packet.EveryoneIsAssistant);
+}
+
+void WorldSession::HandleClearRaidMarker(WorldPackets::Party::ClearRaidMarker& packet)
+{
+ Group* group = GetPlayer()->GetGroup();
+ if (!group)
+ return;
+
+ if (group->isRaidGroup() && !group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
+ return;
+
+ group->DeleteRaidMarker(packet.MarkerId);
}
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index c938751e162..e6aecff9137 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -716,13 +716,12 @@ void WorldSession::SendEnchantmentLog(ObjectGuid target, ObjectGuid caster, uint
void WorldSession::SendItemEnchantTimeUpdate(ObjectGuid Playerguid, ObjectGuid Itemguid, uint32 slot, uint32 Duration)
{
- // last check 2.0.10
- WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8));
- data << Itemguid;
- data << uint32(slot);
- data << uint32(Duration);
- data << Playerguid;
- SendPacket(&data);
+ WorldPackets::Item::ItemEnchantTimeUpdate data;
+ data.ItemGuid = Itemguid;
+ data.DurationLeft = Duration;
+ data.Slot = slot;
+ data.OwnerGuid = Playerguid;
+ SendPacket(data.Write());
}
void WorldSession::HandleWrapItem(WorldPackets::Item::WrapItem& packet)
diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp
index c4d3358a333..4a3866cbb1b 100644
--- a/src/server/game/Handlers/LFGHandler.cpp
+++ b/src/server/game/Handlers/LFGHandler.cpp
@@ -86,7 +86,7 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData)
{
if (!sLFGMgr->isOptionEnabled(lfg::LFG_OPTION_ENABLE_DUNGEON_FINDER | lfg::LFG_OPTION_ENABLE_RAID_BROWSER) ||
(GetPlayer()->GetGroup() && GetPlayer()->GetGroup()->GetLeaderGUID() != GetPlayer()->GetGUID() &&
- (GetPlayer()->GetGroup()->GetMembersCount() == MAXGROUPSIZE || !GetPlayer()->GetGroup()->isLFGGroup())))
+ (GetPlayer()->GetGroup()->GetMembersCount() == MAX_GROUP_SIZE || !GetPlayer()->GetGroup()->isLFGGroup())))
{
recvData.rfinish();
return;
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 025bb45b42b..c87bff8511e 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1213,129 +1213,29 @@ void WorldSession::HandleObjectUpdateRescuedOpcode(WorldPackets::Misc::ObjectUpd
_player->m_clientGUIDs.insert(objectUpdateRescued.ObjectGUID);
}
-void WorldSession::HandleSaveCUFProfiles(WorldPacket& recvPacket)
+void WorldSession::HandleSaveCUFProfiles(WorldPackets::Misc::SaveCUFProfiles& packet)
{
- uint8 count = (uint8)recvPacket.ReadBits(20);
-
- if (count > MAX_CUF_PROFILES)
+ if (packet.CUFProfiles.size() > MAX_CUF_PROFILES)
{
TC_LOG_ERROR("entities.player", "HandleSaveCUFProfiles - %s tried to save more than %i CUF profiles. Hacking attempt?", GetPlayerName().c_str(), MAX_CUF_PROFILES);
- recvPacket.rfinish();
return;
}
- CUFProfile* profiles[MAX_CUF_PROFILES];
- uint8 strlens[MAX_CUF_PROFILES];
-
- for (uint8 i = 0; i < count; ++i)
- {
- profiles[i] = new CUFProfile;
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_2 , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_10_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_UNK_157 , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_HEAL_PREDICTION , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_1 , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVP , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_POWER_BAR , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_15_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_40_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_PETS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_5_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS, recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_2_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_UNK_156 , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_NON_BOSS_DEBUFFS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_MAIN_TANK_AND_ASSIST , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_AGGRO_HIGHLIGHT , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_3_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_BORDER , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_USE_CLASS_COLORS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_UNK_145 , recvPacket.ReadBit());
- strlens[i] = (uint8)recvPacket.ReadBits(8);
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVE , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_HORIZONTAL_GROUPS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_25_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_KEEP_GROUPS_TOGETHER , recvPacket.ReadBit());
- }
-
- for (uint8 i = 0; i < count; ++i)
- {
- recvPacket >> profiles[i]->Unk146;
- profiles[i]->ProfileName = recvPacket.ReadString(strlens[i]);
- recvPacket >> profiles[i]->Unk152;
- recvPacket >> profiles[i]->FrameHeight;
- recvPacket >> profiles[i]->FrameWidth;
- recvPacket >> profiles[i]->Unk150;
- recvPacket >> profiles[i]->HealthText;
- recvPacket >> profiles[i]->Unk147;
- recvPacket >> profiles[i]->SortBy;
- recvPacket >> profiles[i]->Unk154;
- recvPacket >> profiles[i]->Unk148;
-
- GetPlayer()->SaveCUFProfile(i, profiles[i]);
- }
+ for (uint8 i = 0; i < packet.CUFProfiles.size(); ++i)
+ GetPlayer()->SaveCUFProfile(i, std::move(packet.CUFProfiles[i]));
- for (uint8 i = count; i < MAX_CUF_PROFILES; ++i)
- GetPlayer()->SaveCUFProfile(i, NULL);
+ for (uint8 i = packet.CUFProfiles.size(); i < MAX_CUF_PROFILES; ++i)
+ GetPlayer()->SaveCUFProfile(i, nullptr);
}
void WorldSession::SendLoadCUFProfiles()
{
Player* player = GetPlayer();
- uint8 count = player->GetCUFProfilesCount();
+ WorldPackets::Misc::LoadCUFProfiles loadCUFProfiles;
- ByteBuffer byteBuffer(25 * count);
- WorldPacket data(SMSG_LOAD_CUF_PROFILES, 5 * count + 25 * count);
-
- data.WriteBits(count, 20);
- for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
- {
- CUFProfile* profile = player->GetCUFProfile(i);
- if (!profile)
- continue;
-
- data.WriteBit(profile->BoolOptions[CUF_UNK_157]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_10_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_5_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_25_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HEAL_PREDICTION]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVE]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HORIZONTAL_GROUPS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_40_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_3_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_AGGRO_HIGHLIGHT]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_BORDER]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_2_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_NON_BOSS_DEBUFFS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_MAIN_TANK_AND_ASSIST]);
- data.WriteBit(profile->BoolOptions[CUF_UNK_156]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_2]);
- data.WriteBit(profile->BoolOptions[CUF_USE_CLASS_COLORS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_POWER_BAR]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_1]);
- data.WriteBits(profile->ProfileName.size(), 8);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS]);
- data.WriteBit(profile->BoolOptions[CUF_KEEP_GROUPS_TOGETHER]);
- data.WriteBit(profile->BoolOptions[CUF_UNK_145]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_15_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_PETS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVP]);
-
- byteBuffer << uint16(profile->Unk154);
- byteBuffer << uint16(profile->FrameHeight);
- byteBuffer << uint16(profile->Unk152);
- byteBuffer << uint8(profile->Unk147);
- byteBuffer << uint16(profile->Unk150);
- byteBuffer << uint8(profile->Unk146);
- byteBuffer << uint8(profile->HealthText);
- byteBuffer << uint8(profile->SortBy);
- byteBuffer << uint16(profile->FrameWidth);
- byteBuffer << uint8(profile->Unk148);
- byteBuffer.WriteString(profile->ProfileName);
- }
-
- data.FlushBits();
- data.append(byteBuffer);
- SendPacket(&data);
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; i++)
+ if (CUFProfile* cufProfile = player->GetCUFProfile(i))
+ loadCUFProfiles.CUFProfiles.push_back(cufProfile);
+ SendPacket(loadCUFProfiles.Write());
}
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 7f1782ea1f0..429d3565052 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -616,8 +616,7 @@ void WorldSession::HandlePetRename(WorldPacket& recvData)
pet->SetName(name);
- if (pet->GetOwner()->GetGroup())
- pet->GetOwner()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME);
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME);
pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 3d2f60929fb..2d3090825da 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -281,8 +281,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast)
caster = _player;
}
- // check known spell
- if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellInfo->Id))
+ // check known spell or raid marker spell (which not requires player to know it)
+ if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellInfo->Id) && !spellInfo->HasEffect(SPELL_EFFECT_CHANGE_RAID_MARKER))
return;
// Check possible spell cast overrides
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index a63ed66446e..189b620b805 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -155,12 +155,6 @@ uint32 LootStore::LoadLootTable()
uint8 mincount = fields[7].GetUInt8();
uint8 maxcount = fields[8].GetUInt8();
- if (maxcount > std::numeric_limits<uint8>::max())
- {
- TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d Item %d: MaxCount value (%u) to large. must be less %u - skipped", GetName(), entry, item, maxcount, std::numeric_limits<uint8>::max());
- continue; // error already printed to log/console.
- }
-
if (groupid >= 1 << 7) // it stored in 7 bit field
{
TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d Item %d: GroupId (%u) must be less %u - skipped", GetName(), entry, item, groupid, 1 << 7);
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index a2faa8cc0a0..fb1ac3cc62d 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -699,7 +699,7 @@ class Map : public GridRefManager<NGridType>
{
auto itr = _guidGenerators.find(high);
if (itr == _guidGenerators.end())
- itr = _guidGenerators.insert(std::make_pair(high, std::unique_ptr<ObjectGuidGenerator<high>>(new ObjectGuidGenerator<high>()))).first;
+ itr = _guidGenerators.insert(std::make_pair(high, Trinity::make_unique<ObjectGuidGenerator<high>>())).first;
return *itr->second;
}
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
index 473e3163216..bd69844ae7c 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -214,7 +214,7 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save,
// some instances only have one difficulty
GetDownscaledMapDifficultyData(GetId(), difficulty);
- TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal");
+ TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save ? "" : "new ", InstanceId, GetId(), difficulty ? "heroic" : "normal");
InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this);
ASSERT(map->IsDungeon());
diff --git a/src/server/game/Maps/ZoneScript.h b/src/server/game/Maps/ZoneScript.h
index d8dba57d438..fd52bdd4c14 100644
--- a/src/server/game/Maps/ZoneScript.h
+++ b/src/server/game/Maps/ZoneScript.h
@@ -29,8 +29,8 @@ class ZoneScript
ZoneScript() { }
virtual ~ZoneScript() { }
- virtual uint32 GetCreatureEntry(uint32 /*guidlow*/, CreatureData const* data) { return data->id; }
- virtual uint32 GetGameObjectEntry(uint32 /*guidlow*/, uint32 entry) { return entry; }
+ virtual uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) { return data->id; }
+ virtual uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) { return entry; }
virtual void OnCreatureCreate(Creature* ) { }
virtual void OnCreatureRemove(Creature* ) { }
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index ed004c6174d..86e1c80bbd1 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -1113,7 +1113,7 @@ enum SpellEffectName
SPELL_EFFECT_REPUTATION = 103,
SPELL_EFFECT_SUMMON_OBJECT_SLOT1 = 104,
SPELL_EFFECT_SUMMON_OBJECT_SLOT2 = 105,
- SPELL_EFFECT_SUMMON_OBJECT_SLOT3 = 106,
+ SPELL_EFFECT_CHANGE_RAID_MARKER = 106,
SPELL_EFFECT_SUMMON_OBJECT_SLOT4 = 107,
SPELL_EFFECT_DISPEL_MECHANIC = 108,
SPELL_EFFECT_RESURRECT_PET = 109,
@@ -1174,7 +1174,7 @@ enum SpellEffectName
SPELL_EFFECT_REMOVE_AURA = 164,
SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT = 165,
SPELL_EFFECT_GIVE_CURRENCY = 166,
- SPELL_EFFECT_167 = 167,
+ SPELL_EFFECT_UPDATE_PLAYER_PHASE = 167,
SPELL_EFFECT_ALLOW_CONTROL_PET = 168, // NYI
SPELL_EFFECT_DESTROY_ITEM = 169,
SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES = 170, // NYI
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index 0b547d96e7f..c8da50364ba 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -182,7 +182,7 @@ class MotionMaster //: private std::stack<MovementGenerator *>
void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ);
void MoveJumpTo(float angle, float speedXY, float speedZ);
void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = EVENT_JUMP)
- { MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); };
+ { MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); }
void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP);
void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount);
void MoveFall(uint32 id = 0);
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index c878287b4ac..148cdeab68e 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -34,7 +34,7 @@ Quest::Quest(Field* questRecord)
SuggestedPlayers = questRecord[7].GetUInt8();
NextQuestInChain = questRecord[8].GetUInt32();
RewardXPDifficulty = questRecord[9].GetUInt32();
- Float10 = questRecord[10].GetFloat();
+ RewardXPMultiplier = questRecord[10].GetFloat();
RewardMoney = questRecord[11].GetUInt32();
RewardMoneyDifficulty = questRecord[12].GetUInt32();
Float13 = questRecord[13].GetFloat();
@@ -225,7 +225,7 @@ uint32 Quest::XPValue(uint32 playerLevel) const
else if (diffFactor > 10)
diffFactor = 10;
- uint32 xp = diffFactor * xpentry->Exp[RewardXPDifficulty] / 10;
+ uint32 xp = diffFactor * xpentry->Exp[RewardXPDifficulty] * RewardXPMultiplier / 10;
if (xp <= 100)
xp = 5 * ((xp + 2) / 5);
else if (xp <= 500)
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 8433a549c60..e11794dc64c 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -226,7 +226,8 @@ enum QuestObjectiveType
QUEST_OBJECTIVE_AREATRIGGER = 10,
QUEST_OBJECTIVE_WINPETBATTLEAGAINSTNPC = 11,
QUEST_OBJECTIVE_DEFEATBATTLEPET = 12,
- QUEST_OBJECTIVE_WINPVPPETBATTLES = 13
+ QUEST_OBJECTIVE_WINPVPPETBATTLES = 13,
+ QUEST_OBJECTIVE_CRITERIA_TREE = 14
};
struct QuestTemplateLocale
@@ -318,6 +319,7 @@ class Quest
uint32 GetBonusTalents() const { return RewardTalents; }
int32 GetRewArenaPoints() const {return RewardArenaPoints; }
uint32 GetXPDifficulty() const { return RewardXPDifficulty; }
+ float GetXPMultiplier() const { return RewardXPMultiplier; }
uint32 GetSrcItemId() const { return SourceItemId; }
uint32 GetSrcItemCount() const { return SourceItemIdCount; }
uint32 GetSrcSpell() const { return SourceSpellID; }
@@ -332,7 +334,7 @@ class Quest
std::string const& GetPortraitGiverName() const { return PortraitGiverName; }
std::string const& GetPortraitTurnInText() const { return PortraitTurnInText; }
std::string const& GetPortraitTurnInName() const { return PortraitTurnInName; }
- QuestObjectives const& GetObjectives() const { return Objectives; };
+ QuestObjectives const& GetObjectives() const { return Objectives; }
uint32 GetRewMoney() const;
uint32 GetRewMoneyDifficulty() const { return RewardMoneyDifficulty; }
uint32 GetRewHonor() const { return RewardHonor; }
@@ -401,7 +403,7 @@ class Quest
uint32 SuggestedPlayers;
uint32 NextQuestInChain;
uint32 RewardXPDifficulty;
- float Float10;
+ float RewardXPMultiplier;
int32 RewardMoney;
uint32 RewardMoneyDifficulty;
float Float13;
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 553c752ccce..aa8be4946e4 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -634,6 +634,7 @@ void AddSC_instance_magtheridons_lair();
void AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls
void AddSC_boss_warbringer_omrogg();
void AddSC_boss_warchief_kargath_bladefist();
+void AddSC_shattered_halls();
void AddSC_instance_shattered_halls();
void AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts
void AddSC_boss_omor_the_unscarred();
@@ -1188,6 +1189,7 @@ void AddOutlandScripts()
AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls
AddSC_boss_warbringer_omrogg();
AddSC_boss_warchief_kargath_bladefist();
+ AddSC_shattered_halls();
AddSC_instance_shattered_halls();
AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts
AddSC_boss_omor_the_unscarred();
diff --git a/src/server/game/Server/Packets/ChannelPackets.h b/src/server/game/Server/Packets/ChannelPackets.h
index 6c43588e86a..8dba1e84677 100644
--- a/src/server/game/Server/Packets/ChannelPackets.h
+++ b/src/server/game/Server/Packets/ChannelPackets.h
@@ -104,8 +104,8 @@ namespace WorldPackets
ObjectGuid AddedUserGUID;
- ChannelFlags ChannelFlags = CHANNEL_FLAG_NONE;
- ChannelMemberFlags UserFlags = MEMBER_FLAG_NONE;
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
+ uint8 UserFlags = MEMBER_FLAG_NONE;
int32 ChannelID = 0;
@@ -121,7 +121,7 @@ namespace WorldPackets
ObjectGuid RemovedUserGUID;
- ChannelFlags ChannelFlags = CHANNEL_FLAG_NONE;
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
uint32 ChannelID = 0;
@@ -137,8 +137,8 @@ namespace WorldPackets
ObjectGuid UpdatedUserGUID;
- ChannelFlags ChannelFlags = CHANNEL_FLAG_NONE;
- ChannelMemberFlags UserFlags = MEMBER_FLAG_NONE;
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
+ uint8 UserFlags = MEMBER_FLAG_NONE;
int32 ChannelID = 0;
diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp
index a48639f1b03..9c6bb07f56e 100644
--- a/src/server/game/Server/Packets/CharacterPackets.cpp
+++ b/src/server/game/Server/Packets/CharacterPackets.cpp
@@ -498,3 +498,40 @@ WorldPacket const* WorldPackets::Character::SetFactionVisible::Write()
_worldPacket << FactionIndex;
return &_worldPacket;
}
+
+WorldPackets::Character::CharCustomizeResponse::CharCustomizeResponse(WorldPackets::Character::CharCustomizeInfo const* info)
+ : ServerPacket(SMSG_CHAR_CUSTOMIZE, 16 + 1 + 1 + 1 + 1 + 1 + 1 + 1)
+{
+ CharGUID = info->CharGUID;
+ SexID = info->SexID;
+ SkinID = info->SkinID;
+ HairColorID = info->HairColorID;
+ HairStyleID = info->HairStyleID;
+ FacialHairStyleID = info->FacialHairStyleID;
+ FaceID = info->FaceID;
+ CharName = info->CharName;
+}
+
+WorldPacket const* WorldPackets::Character::CharCustomizeResponse::Write()
+{
+ _worldPacket << CharGUID;
+ _worldPacket << uint8(SexID);
+ _worldPacket << uint8(SkinID);
+ _worldPacket << uint8(HairColorID);
+ _worldPacket << uint8(HairStyleID);
+ _worldPacket << uint8(FacialHairStyleID);
+ _worldPacket << uint8(FaceID);
+ _worldPacket.WriteBits(CharName.length(), 6);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(CharName);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Character::CharCustomizeFailed::Write()
+{
+ _worldPacket << uint8(Result);
+ _worldPacket << CharGUID;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h
index cee4f5edb5c..10f1053f8ee 100644
--- a/src/server/game/Server/Packets/CharacterPackets.h
+++ b/src/server/game/Server/Packets/CharacterPackets.h
@@ -608,7 +608,7 @@ namespace WorldPackets
WorldPacket const* Write() override;
- BarberShopResult Result;
+ BarberShopResult Result = BARBER_SHOP_RESULT_SUCCESS;
};
class LogXPGain final : public ServerPacket
@@ -686,6 +686,35 @@ namespace WorldPackets
uint32 FactionIndex = 0;
};
+
+ class CharCustomizeResponse final : public ServerPacket
+ {
+ public:
+ CharCustomizeResponse() : ServerPacket(SMSG_CHAR_CUSTOMIZE, 16 + 1 + 1 + 1 + 1 + 1 + 1 + 1) { }
+ CharCustomizeResponse(CharCustomizeInfo const* customizeInfo);
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid CharGUID;
+ std::string CharName;
+ uint8 SexID = 0;
+ uint8 SkinID = 0;
+ uint8 HairColorID = 0;
+ uint8 HairStyleID = 0;
+ uint8 FacialHairStyleID = 0;
+ uint8 FaceID = 0;
+ };
+
+ class CharCustomizeFailed final : public ServerPacket
+ {
+ public:
+ CharCustomizeFailed() : ServerPacket(SMSG_CHAR_CUSTOMIZE_FAILED, 1 + 16) { }
+
+ WorldPacket const* Write() override;
+
+ uint8 Result = 0;
+ ObjectGuid CharGUID;
+ };
}
}
diff --git a/src/server/game/Server/Packets/ChatPackets.cpp b/src/server/game/Server/Packets/ChatPackets.cpp
index 260770e65fe..4204278d514 100644
--- a/src/server/game/Server/Packets/ChatPackets.cpp
+++ b/src/server/game/Server/Packets/ChatPackets.cpp
@@ -92,7 +92,7 @@ void WorldPackets::Chat::ChatMessageEmote::Read()
Text = _worldPacket.ReadString(len);
}
-void WorldPackets::Chat::Chat::Initalize(ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string message,
+void WorldPackets::Chat::Chat::Initialize(ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string message,
uint32 achievementId /*= 0*/, std::string channelName /*= ""*/, LocaleConstant locale /*= DEFAULT_LOCALE*/, std::string addonPrefix /*= ""*/)
{
// Clear everything because same packet can be used multiple times
@@ -233,3 +233,15 @@ WorldPacket const* WorldPackets::Chat::ChatServerMessage::Write()
return &_worldPacket;
}
+
+void WorldPackets::Chat::ChatRegisterAddonPrefixes::Read()
+{
+ int32 count;
+ _worldPacket >> count;
+
+ for (int32 i = 0; i < count; ++i)
+ {
+ uint32 lenghts = _worldPacket.ReadBits(5);
+ Prefixes.push_back(_worldPacket.ReadString(lenghts));
+ }
+}
diff --git a/src/server/game/Server/Packets/ChatPackets.h b/src/server/game/Server/Packets/ChatPackets.h
index 5bc55952168..c8bb038ce19 100644
--- a/src/server/game/Server/Packets/ChatPackets.h
+++ b/src/server/game/Server/Packets/ChatPackets.h
@@ -151,7 +151,7 @@ namespace WorldPackets
public:
Chat() : ServerPacket(SMSG_CHAT, 100) { }
- void Initalize(ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string message, uint32 achievementId = 0, std::string channelName = "", LocaleConstant locale = DEFAULT_LOCALE, std::string addonPrefix = "");
+ void Initialize(ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string message, uint32 achievementId = 0, std::string channelName = "", LocaleConstant locale = DEFAULT_LOCALE, std::string addonPrefix = "");
WorldPacket const* Write() override;
uint8 SlashCmd = 0; ///< @see enum ChatMsg
@@ -250,6 +250,24 @@ namespace WorldPackets
int32 MessageID = 0;
std::string StringParam;
};
+
+ class ChatRegisterAddonPrefixes final : public ClientPacket
+ {
+ public:
+ ChatRegisterAddonPrefixes(WorldPacket&& packet) : ClientPacket(CMSG_CHAT_REGISTER_ADDON_PREFIXES, std::move(packet)) { }
+
+ void Read() override;
+
+ std::vector<std::string> Prefixes;
+ };
+
+ class ChatUnregisterAllAddonPrefixes final : public ClientPacket
+ {
+ public:
+ ChatUnregisterAllAddonPrefixes(WorldPacket&& packet) : ClientPacket(CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES, std::move(packet)) { }
+
+ void Read() override { }
+ };
}
}
diff --git a/src/server/game/Server/Packets/CombatLogPackets.cpp b/src/server/game/Server/Packets/CombatLogPackets.cpp
index 0702ad63f05..6742e797c54 100644
--- a/src/server/game/Server/Packets/CombatLogPackets.cpp
+++ b/src/server/game/Server/Packets/CombatLogPackets.cpp
@@ -147,3 +147,40 @@ WorldPacket const* WorldPackets::CombatLog::SpellHealLog::Write()
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::CombatLog::SpellPeriodicAuraLog::Write()
+{
+ _worldPacket << TargetGUID;
+ _worldPacket << CasterGUID;
+ _worldPacket << SpellID;
+
+ _worldPacket << uint32(Effects.size());
+
+ for (SpellLogEffect const& effect : Effects)
+ {
+ _worldPacket << effect.Effect;
+ _worldPacket << int32(effect.Amount);
+ _worldPacket << int32(effect.OverHealOrKill);
+ _worldPacket << int32(effect.SchoolMaskOrPower);
+ _worldPacket << int32(effect.AbsorbedOrAmplitude);
+ _worldPacket << int32(effect.Resisted);
+
+ _worldPacket.WriteBit(effect.Crit);
+ _worldPacket.WriteBit(effect.Multistrike);
+
+ if (_worldPacket.WriteBit(effect.DebugInfo.is_initialized()))
+ {
+ _worldPacket << float(effect.DebugInfo->CritRollMade);
+ _worldPacket << float(effect.DebugInfo->CritRollNeeded);
+ }
+
+ _worldPacket.FlushBits();
+ }
+
+ _worldPacket.WriteBit(LogData.is_initialized());
+ _worldPacket.FlushBits();
+ if (LogData)
+ _worldPacket << *LogData;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/CombatLogPackets.h b/src/server/game/Server/Packets/CombatLogPackets.h
index c74e8112698..a931166ef80 100644
--- a/src/server/game/Server/Packets/CombatLogPackets.h
+++ b/src/server/game/Server/Packets/CombatLogPackets.h
@@ -91,7 +91,6 @@ namespace WorldPackets
class SpellHealLog final : public ServerPacket
{
public:
-
SpellHealLog() : ServerPacket(SMSG_SPELL_HEAL_LOG, 16 + 16 + 4 * 4 + 1) { }
WorldPacket const* Write() override;
@@ -108,6 +107,39 @@ namespace WorldPackets
Optional<float> CritRollNeeded;
Optional<Spells::SpellCastLogData> LogData; /// @todo: find the correct way where to use it, in sniff always false
};
+
+ class SpellPeriodicAuraLog final : public ServerPacket
+ {
+ public:
+ struct PeriodicalAuraLogEffectDebugInfo
+ {
+ float CritRollMade = 0.0f;
+ float CritRollNeeded = 0.0f;
+ };
+
+ struct SpellLogEffect
+ {
+ int32 Effect = 0;
+ int32 Amount = 0;
+ int32 OverHealOrKill = 0;
+ int32 SchoolMaskOrPower = 0;
+ int32 AbsorbedOrAmplitude = 0;
+ int32 Resisted = 0;
+ bool Crit = false;
+ bool Multistrike = false;
+ Optional<PeriodicalAuraLogEffectDebugInfo> DebugInfo;
+ };
+
+ SpellPeriodicAuraLog() : ServerPacket(SMSG_SPELL_PERIODIC_AURA_LOG, 16 + 16 + 4 + 4 + 1) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid TargetGUID;
+ ObjectGuid CasterGUID;
+ int32 SpellID = 0;
+ std::vector<SpellLogEffect> Effects;
+ Optional<Spells::SpellCastLogData> LogData; /// @todo: find the correct way where to use it, in sniff always false
+ };
}
}
diff --git a/src/server/game/Server/Packets/GarrisonPackets.cpp b/src/server/game/Server/Packets/GarrisonPackets.cpp
index 456149bbdbb..88374e7ce62 100644
--- a/src/server/game/Server/Packets/GarrisonPackets.cpp
+++ b/src/server/game/Server/Packets/GarrisonPackets.cpp
@@ -60,8 +60,8 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonFollowe
data << uint32(follower.CurrentMissionID);
data << uint32(follower.AbilityID.size());
data << uint32(follower.FollowerStatus);
- for (uint32 abilityId : follower.AbilityID)
- data << uint32(abilityId);
+ for (GarrAbilityEntry const* ability : follower.AbilityID)
+ data << uint32(ability->ID);
return data;
}
diff --git a/src/server/game/Server/Packets/GarrisonPackets.h b/src/server/game/Server/Packets/GarrisonPackets.h
index 5fc386ab72b..1bb04c7ba95 100644
--- a/src/server/game/Server/Packets/GarrisonPackets.h
+++ b/src/server/game/Server/Packets/GarrisonPackets.h
@@ -22,6 +22,7 @@
#include "ObjectGuid.h"
#include "Position.h"
#include "PacketUtilities.h"
+#include "DB2Structure.h"
namespace WorldPackets
{
@@ -74,7 +75,7 @@ namespace WorldPackets
uint32 Xp = 0;
uint32 CurrentBuildingID = 0;
uint32 CurrentMissionID = 0;
- std::list<uint32> AbilityID;
+ std::list<GarrAbilityEntry const*> AbilityID;
uint32 FollowerStatus;
};
diff --git a/src/server/game/Server/Packets/InstancePackets.cpp b/src/server/game/Server/Packets/InstancePackets.cpp
index 50b2a66a8b8..db5bdcbd9e8 100644
--- a/src/server/game/Server/Packets/InstancePackets.cpp
+++ b/src/server/game/Server/Packets/InstancePackets.cpp
@@ -30,3 +30,29 @@ WorldPacket const* WorldPackets::Instance::UpdateInstanceOwnership::Write()
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::Instance::InstanceInfo::Write()
+{
+ _worldPacket << int32(LockList.size());
+
+ for (InstanceLockInfos const& lockInfos : LockList)
+ _worldPacket << lockInfos;
+
+ return &_worldPacket;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Instance::InstanceLockInfos const& lockInfos)
+{
+ data << lockInfos.MapID;
+ data << lockInfos.DifficultyID;
+ data << lockInfos.InstanceID;
+ data << lockInfos.TimeRemaining;
+ data << lockInfos.CompletedMask;
+
+ data.WriteBit(lockInfos.Locked);
+ data.WriteBit(lockInfos.Extended);
+
+ data.FlushBits();
+
+ return data;
+}
diff --git a/src/server/game/Server/Packets/InstancePackets.h b/src/server/game/Server/Packets/InstancePackets.h
index 09f6c1efdcb..e38bcb97462 100644
--- a/src/server/game/Server/Packets/InstancePackets.h
+++ b/src/server/game/Server/Packets/InstancePackets.h
@@ -46,7 +46,31 @@ namespace WorldPackets
int32 IOwnInstance = 0; // Used to control whether "Reset all instances" button appears on the UI - Script_CanShowResetInstances()
// but it has been deperecated in favor of simply checking group leader, being inside an instance or using dungeon finder
};
+
+ struct InstanceLockInfos
+ {
+ uint64 InstanceID = 0u;
+ uint32 MapID = 0u;
+ uint32 DifficultyID = 0u;
+ int32 TimeRemaining = 0;
+ uint32 CompletedMask = 0u;
+
+ bool Locked = false;
+ bool Extended = false;
+ };
+
+ class InstanceInfo final : public ServerPacket
+ {
+ public:
+ InstanceInfo() : ServerPacket(SMSG_INSTANCE_INFO, 4) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<InstanceLockInfos> LockList;
+ };
}
}
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Instance::InstanceLockInfos const& lockInfos);
+
#endif // InstancePackets_h__
diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp
index a4da605ca08..8b0bec535b3 100644
--- a/src/server/game/Server/Packets/ItemPackets.cpp
+++ b/src/server/game/Server/Packets/ItemPackets.cpp
@@ -374,3 +374,21 @@ void WorldPackets::Item::CancelTempEnchantment::Read()
{
_worldPacket >> Slot;
}
+
+WorldPacket const* WorldPackets::Item::ItemCooldown::Write()
+{
+ _worldPacket << ItemGuid;
+ _worldPacket << uint32(SpellID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Item::ItemEnchantTimeUpdate::Write()
+{
+ _worldPacket << ItemGuid;
+ _worldPacket << uint32(DurationLeft);
+ _worldPacket << uint32(Slot);
+ _worldPacket << OwnerGuid;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h
index 7b0b9e41e4b..e73f42bcaf2 100644
--- a/src/server/game/Server/Packets/ItemPackets.h
+++ b/src/server/game/Server/Packets/ItemPackets.h
@@ -363,6 +363,30 @@ namespace WorldPackets
int32 Slot = 0;
};
+ class ItemCooldown final : public ServerPacket
+ {
+ public:
+ ItemCooldown() : ServerPacket(SMSG_ITEM_COOLDOWN, 20) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid ItemGuid;
+ uint32 SpellID = 0;
+ };
+
+ class ItemEnchantTimeUpdate final : public ServerPacket
+ {
+ public:
+ ItemEnchantTimeUpdate() : ServerPacket(SMSG_ITEM_ENCHANT_TIME_UPDATE, 40) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid OwnerGuid;
+ ObjectGuid ItemGuid;
+ uint32 DurationLeft = 0;
+ uint32 Slot = 0;
+ };
+
ByteBuffer& operator>>(ByteBuffer& data, InvUpdate& invUpdate);
}
}
diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp
index a12ff537050..bbd3fcb2ba7 100644
--- a/src/server/game/Server/Packets/MiscPackets.cpp
+++ b/src/server/game/Server/Packets/MiscPackets.cpp
@@ -451,3 +451,72 @@ WorldPacket const* WorldPackets::Misc::Dismount::Write()
return &_worldPacket;
}
+
+void WorldPackets::Misc::SaveCUFProfiles::Read()
+{
+ uint32 count;
+ _worldPacket >> count;
+
+ for (uint8 i = 0; i < count && i < MAX_CUF_PROFILES; i++)
+ {
+ std::unique_ptr<CUFProfile> cufProfile = Trinity::make_unique<CUFProfile>();
+
+ uint8 strLen = _worldPacket.ReadBits(7);
+
+ // Bool Options
+ for (uint8 option = 0; option < CUF_BOOL_OPTIONS_COUNT; option++)
+ cufProfile->BoolOptions.set(option, _worldPacket.ReadBit());
+
+ // Other Options
+ _worldPacket >> cufProfile->FrameHeight;
+ _worldPacket >> cufProfile->FrameWidth;
+
+ _worldPacket >> cufProfile->SortBy;
+ _worldPacket >> cufProfile->HealthText;
+
+ _worldPacket >> cufProfile->TopPoint;
+ _worldPacket >> cufProfile->BottomPoint;
+ _worldPacket >> cufProfile->LeftPoint;
+
+ _worldPacket >> cufProfile->TopOffset;
+ _worldPacket >> cufProfile->BottomOffset;
+ _worldPacket >> cufProfile->LeftOffset;
+
+ cufProfile->ProfileName = _worldPacket.ReadString(strLen);
+
+ CUFProfiles.push_back(std::move(cufProfile));
+ }
+}
+
+WorldPacket const* WorldPackets::Misc::LoadCUFProfiles::Write()
+{
+ _worldPacket << uint32(CUFProfiles.size());
+
+ for (CUFProfile const* cufProfile : CUFProfiles)
+ {
+ _worldPacket.WriteBits(cufProfile->ProfileName.size(), 7);
+
+ // Bool Options
+ for (uint8 option = 0; option < CUF_BOOL_OPTIONS_COUNT; option++)
+ _worldPacket.WriteBit(cufProfile->BoolOptions[option]);
+
+ // Other Options
+ _worldPacket << cufProfile->FrameHeight;
+ _worldPacket << cufProfile->FrameWidth;
+
+ _worldPacket << cufProfile->SortBy;
+ _worldPacket << cufProfile->HealthText;
+
+ _worldPacket << cufProfile->TopPoint;
+ _worldPacket << cufProfile->BottomPoint;
+ _worldPacket << cufProfile->LeftPoint;
+
+ _worldPacket << cufProfile->TopOffset;
+ _worldPacket << cufProfile->BottomOffset;
+ _worldPacket << cufProfile->LeftOffset;
+
+ _worldPacket.WriteString(cufProfile->ProfileName);
+ }
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h
index fda0e44990e..93bac0d208b 100644
--- a/src/server/game/Server/Packets/MiscPackets.h
+++ b/src/server/game/Server/Packets/MiscPackets.h
@@ -24,6 +24,7 @@
#include "G3D/Vector3.h"
#include "Object.h"
#include "Unit.h"
+#include "Player.h"
#include "Weather.h"
namespace WorldPackets
@@ -642,6 +643,26 @@ namespace WorldPackets
ObjectGuid Guid;
};
+
+ class SaveCUFProfiles final : public ClientPacket
+ {
+ public:
+ SaveCUFProfiles(WorldPacket&& packet) : ClientPacket(CMSG_SAVE_CUF_PROFILES, std::move(packet)) { }
+
+ void Read() override;
+
+ std::vector<std::unique_ptr<CUFProfile>> CUFProfiles;
+ };
+
+ class LoadCUFProfiles final : public ServerPacket
+ {
+ public:
+ LoadCUFProfiles() : ServerPacket(SMSG_LOAD_CUF_PROFILES, 20) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<CUFProfile const*> CUFProfiles;
+ };
}
}
diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h
index 6803bdf3b95..d4fb41cf330 100644
--- a/src/server/game/Server/Packets/MovementPackets.h
+++ b/src/server/game/Server/Packets/MovementPackets.h
@@ -398,7 +398,7 @@ namespace WorldPackets
void Read() override;
ObjectGuid MoverGUID;
- uint32 TimeSkipped;
+ uint32 TimeSkipped = 0;
};
}
diff --git a/src/server/game/Server/Packets/PartyPackets.cpp b/src/server/game/Server/Packets/PartyPackets.cpp
new file mode 100644
index 00000000000..f5cbfd7f5c2
--- /dev/null
+++ b/src/server/game/Server/Packets/PartyPackets.cpp
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "PartyPackets.h"
+
+#include "Player.h"
+#include "Pet.h"
+#include "Vehicle.h"
+#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
+#include "ObjectMgr.h"
+
+WorldPacket const* WorldPackets::Party::PartyCommandResult::Write()
+{
+ _worldPacket.WriteBits(Name.size(), 9);
+
+ _worldPacket.WriteBits(Command, 4);
+ _worldPacket.WriteBits(Result, 6);
+
+ _worldPacket << ResultData;
+ _worldPacket << ResultGUID;
+ _worldPacket.WriteString(Name);
+
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::PartyInviteClient::Read()
+{
+ uint32 targetNameLen, targetRealmLen;
+
+ _worldPacket >> PartyIndex;
+ _worldPacket >> ProposedRoles;
+ _worldPacket >> TargetGUID;
+ _worldPacket >> TargetCfgRealmID;
+
+ targetNameLen = _worldPacket.ReadBits(9);
+ targetRealmLen = _worldPacket.ReadBits(9);
+
+ TargetName = _worldPacket.ReadString(targetNameLen);
+ TargetRealm = _worldPacket.ReadString(targetRealmLen);
+}
+
+WorldPacket const* WorldPackets::Party::PartyInvite::Write()
+{
+ // Order guessed
+ _worldPacket.WriteBit(CanAccept);
+ _worldPacket.WriteBit(MightCRZYou);
+ _worldPacket.WriteBit(MustBeBNetFriend);
+ _worldPacket.WriteBit(AllowMultipleRoles);
+ _worldPacket.WriteBit(IsXRealm);
+
+ _worldPacket.WriteBits(InviterName.size(), 6);
+
+ _worldPacket << InviterGUID;
+ _worldPacket << InviterBNetAccountId;
+
+ _worldPacket << InviterVirtualRealmAddress;
+ _worldPacket << Unk1;
+
+ _worldPacket.WriteBit(IsLocal);
+ _worldPacket.WriteBit(Unk2);
+
+ _worldPacket.WriteBits(InviterRealmNameActual.size(), 8);
+ _worldPacket.WriteBits(InviterRealmNameNormalized.size(), 8);
+ _worldPacket.WriteString(InviterRealmNameActual);
+ _worldPacket.WriteString(InviterRealmNameNormalized);
+
+ _worldPacket << ProposedRoles;
+ _worldPacket << int32(LfgSlots.size());
+ _worldPacket << LfgCompletedMask;
+
+ _worldPacket.WriteString(InviterName);
+
+ for (int32 LfgSlot : LfgSlots)
+ _worldPacket << LfgSlot;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::PartyInvite::Initialize(Player* const inviter, int32 proposedRoles, bool canAccept)
+{
+ CanAccept = canAccept;
+
+ InviterName = inviter->GetName();
+ InviterGUID = inviter->GetGUID();
+ InviterBNetAccountId = inviter->GetSession()->GetAccountGUID();
+
+ ProposedRoles = proposedRoles;
+
+ std::string realmName = sObjectMgr->GetRealmName(realmHandle.Index);
+
+ InviterVirtualRealmAddress = GetVirtualRealmAddress();
+ InviterRealmNameActual = realmName;
+ InviterRealmNameNormalized = realmName;
+}
+
+void WorldPackets::Party::PartyInviteResponse::Read()
+{
+ _worldPacket >> PartyIndex;
+
+ Accept = _worldPacket.ReadBit();
+
+ bool hasRolesDesired = _worldPacket.ReadBit();
+ if (hasRolesDesired)
+ {
+ RolesDesired = boost::in_place();
+ _worldPacket >> *RolesDesired;
+ }
+}
+
+void WorldPackets::Party::PartyUninvite::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> TargetGUID;
+
+ uint8 reasonLen = _worldPacket.ReadBits(8);
+ Reason = _worldPacket.ReadString(reasonLen);
+}
+
+WorldPacket const* WorldPackets::Party::GroupDecline::Write()
+{
+ _worldPacket.WriteBits(Name.length(), 9);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(Name);
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::RequestPartyMemberStats::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> TargetGUID;
+}
+
+WorldPacket const* WorldPackets::Party::PartyMemberStats::Write()
+{
+ _worldPacket.WriteBit(ForEnemy);
+
+ _worldPacket << MemberStats;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::SetPartyLeader::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> TargetGUID;
+}
+
+void WorldPackets::Party::SetRole::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> TargetGUID;
+ _worldPacket >> Role;
+}
+
+WorldPacket const* WorldPackets::Party::RoleChangedInform::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << From;
+ _worldPacket << ChangedUnit;
+ _worldPacket << OldRole;
+ _worldPacket << NewRole;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::LeaveGroup::Read()
+{
+ _worldPacket >> PartyIndex;
+}
+
+void WorldPackets::Party::SetLootMethod::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> LootMethod;
+ _worldPacket >> LootMasterGUID;
+ _worldPacket >> LootThreshold;
+}
+
+void WorldPackets::Party::MinimapPingClient::Read()
+{
+ _worldPacket >> PositionX;
+ _worldPacket >> PositionY;
+ _worldPacket >> PartyIndex;
+}
+
+WorldPacket const* WorldPackets::Party::MinimapPing::Write()
+{
+ _worldPacket << Sender;
+ _worldPacket << PositionX;
+ _worldPacket << PositionY;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::UpdateRaidTarget::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> Target;
+ _worldPacket >> Symbol;
+}
+
+WorldPacket const* WorldPackets::Party::SendRaidTargetUpdateSingle::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << Symbol;
+ _worldPacket << Target;
+ _worldPacket << ChangedBy;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Party::SendRaidTargetUpdateAll::Write()
+{
+ _worldPacket << PartyIndex;
+
+ _worldPacket << int32(TargetIcons.size());
+
+ std::map<uint8, ObjectGuid>::const_iterator itr;
+ for (itr = TargetIcons.begin(); itr != TargetIcons.end(); itr++)
+ {
+ _worldPacket << itr->second;
+ _worldPacket << itr->first;
+ }
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::ConvertRaid::Read()
+{
+ Raid = _worldPacket.ReadBit();
+}
+
+void WorldPackets::Party::RequestPartyJoinUpdates::Read()
+{
+ _worldPacket >> PartyIndex;
+}
+
+void WorldPackets::Party::SetAssistantLeader::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> Target;
+ Apply = _worldPacket.ReadBit();
+}
+
+void WorldPackets::Party::DoReadyCheck::Read()
+{
+ _worldPacket >> PartyIndex;
+}
+
+WorldPacket const* WorldPackets::Party::ReadyCheckStarted::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << PartyGUID;
+ _worldPacket << InitiatorGUID;
+ _worldPacket << Duration;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::ReadyCheckResponseClient::Read()
+{
+ _worldPacket >> PartyIndex;
+ IsReady = _worldPacket.ReadBit();
+}
+
+WorldPacket const* WorldPackets::Party::ReadyCheckResponse::Write()
+{
+ _worldPacket << PartyGUID;
+ _worldPacket << Player;
+
+ _worldPacket.WriteBit(IsReady);
+
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Party::ReadyCheckCompleted::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << PartyGUID;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::OptOutOfLoot::Read()
+{
+ PassOnLoot = _worldPacket.ReadBit();
+}
+
+void WorldPackets::Party::InitiateRolePoll::Read()
+{
+ _worldPacket >> PartyIndex;
+}
+
+WorldPacket const* WorldPackets::Party::RolePollInform::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << From;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Party::GroupNewLeader::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket.WriteBits(Name.size(), 6);
+ _worldPacket.WriteString(Name);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Party::PartyUpdate::Write()
+{
+ _worldPacket << PartyType;
+ _worldPacket << PartyIndex;
+ _worldPacket << PartyFlags;
+
+ _worldPacket << MyIndex;
+ _worldPacket << PartyGUID;
+ _worldPacket << SequenceNum;
+ _worldPacket << LeaderGUID;
+
+ _worldPacket << PlayerList;
+
+ _worldPacket.WriteBit(LfgInfos.is_initialized());
+ _worldPacket.WriteBit(LootSettings.is_initialized());
+ _worldPacket.WriteBit(DifficultySettings.is_initialized());
+
+ _worldPacket.FlushBits();
+
+ if (LfgInfos.is_initialized())
+ _worldPacket << *LfgInfos;
+
+ if (LootSettings.is_initialized())
+ _worldPacket << *LootSettings;
+
+ if (DifficultySettings.is_initialized())
+ _worldPacket << *DifficultySettings;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::SetEveryoneIsAssistant::Read()
+{
+ _worldPacket >> PartyIndex;
+ EveryoneIsAssistant = _worldPacket.ReadBit();
+}
+
+void WorldPackets::Party::ChangeSubGroup::Read()
+{
+ _worldPacket >> TargetGUID;
+ _worldPacket >> PartyIndex;
+ _worldPacket >> NewSubGroup;
+}
+
+void WorldPackets::Party::SwapSubGroups::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> FirstTarget;
+ _worldPacket >> SecondTarget;
+}
+
+void WorldPackets::Party::ClearRaidMarker::Read()
+{
+ _worldPacket >> MarkerId;
+}
+
+WorldPacket const* WorldPackets::Party::RaidMarkersChanged::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << ActiveMarkers;
+
+ _worldPacket.WriteBits(RaidMarkers.size(), 4);
+ _worldPacket.FlushBits();
+
+ for (RaidMarker* raidMarker : RaidMarkers)
+ {
+ _worldPacket << raidMarker->TransportGUID;
+ _worldPacket << raidMarker->Location.GetMapId();
+ _worldPacket << raidMarker->Location.PositionXYZStream();
+ }
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::PartyMemberStats::Initialize(Player const* player)
+{
+ ForEnemy = false;
+
+ MemberStats.GUID = player->GetGUID();
+
+ // Status
+ MemberStats.Status = MEMBER_STATUS_ONLINE;
+
+ if (player->IsPvP())
+ MemberStats.Status |= MEMBER_STATUS_PVP;
+
+ if (!player->IsAlive())
+ {
+ if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
+ MemberStats.Status |= MEMBER_STATUS_GHOST;
+ else
+ MemberStats.Status |= MEMBER_STATUS_DEAD;
+ }
+
+ if (player->IsFFAPvP())
+ MemberStats.Status |= MEMBER_STATUS_PVP_FFA;
+
+ if (player->isAFK())
+ MemberStats.Status |= MEMBER_STATUS_AFK;
+
+ if (player->isDND())
+ MemberStats.Status |= MEMBER_STATUS_DND;
+
+ // Level
+ MemberStats.Level = player->getLevel();
+
+ // Health
+ MemberStats.CurrentHealth = player->GetHealth();
+ MemberStats.MaxHealth = player->GetMaxHealth();
+
+ // Power
+ MemberStats.PowerType = player->getPowerType();
+ MemberStats.CurrentPower = player->GetPower(player->getPowerType());
+ MemberStats.MaxPower = player->GetMaxPower(player->getPowerType());
+
+ // Position
+ MemberStats.ZoneID = player->GetZoneId();
+ MemberStats.PositionX = int16(player->GetPositionX());
+ MemberStats.PositionY = int16(player->GetPositionY());
+ MemberStats.PositionZ = int16(player->GetPositionZ());
+
+ // Unk
+ MemberStats.Unk322 = 0; // Always 0
+ MemberStats.Unk704[0] = 1; // Always 1
+ MemberStats.Unk704[1] = 0; // Always 0
+ MemberStats.Unk200000 = 0; // Always 0
+
+ MemberStats.Unk2000000 = 0;
+ MemberStats.Unk4000000 = 0;
+
+ // Vehicle
+ if (player->GetVehicle() && player->GetVehicle()->GetVehicleInfo())
+ MemberStats.VehicleSeat = player->GetVehicle()->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat];
+
+ // Auras
+ for (uint8 i = 0; i < MAX_AURAS; ++i)
+ {
+ if (AuraApplication const* aurApp = player->GetVisibleAura(i))
+ {
+ WorldPackets::Party::GroupAura aura;
+
+ aura.SpellId = aurApp->GetBase()->GetId();
+ aura.EffectMask = aurApp->GetEffectMask();
+ aura.Scalings = aurApp->GetFlags(); // ??
+
+ if (aurApp->GetFlags() & AFLAG_SCALABLE)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ float scale = 0.f;
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ scale = float(eff->GetAmount());
+ aura.EffectScales.push_back(scale);
+ }
+ }
+
+ MemberStats.AuraList.push_back(aura);
+ }
+ }
+
+ // Phases
+ std::set<uint32> const& phases = player->GetPhases();
+ MemberStats.Phases.PhaseShiftFlags = 0x08 | (phases.size() ? 0x10 : 0);
+ MemberStats.Phases.PersonalGUID = ObjectGuid::Empty;
+ for (uint32 phaseId : phases)
+ {
+ WorldPackets::Party::GroupPhase phase;
+ phase.Id = phaseId;
+ phase.Flags = 1;
+ MemberStats.Phases.List.push_back(phase);
+ }
+
+ // Pet
+ if (player->GetPet())
+ {
+ Pet* pet = player->GetPet();
+
+ MemberStats.PetStats = boost::in_place();
+
+ MemberStats.PetStats->GUID = pet->GetGUID();
+ MemberStats.PetStats->Name = pet->GetName();
+ MemberStats.PetStats->ModelId = pet->GetDisplayId();
+
+ MemberStats.PetStats->CurrentHealth = pet->GetHealth();
+ MemberStats.PetStats->MaxHealth = pet->GetMaxHealth();
+
+ for (uint8 i = 0; i < MAX_AURAS; ++i)
+ {
+ if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
+ {
+ WorldPackets::Party::GroupAura aura;
+
+ aura.SpellId = aurApp->GetBase()->GetId();
+ aura.EffectMask = aurApp->GetEffectMask();
+ aura.Scalings = aurApp->GetFlags(); // ??
+
+ if (aurApp->GetFlags() & AFLAG_SCALABLE)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ float scale = 0.f;
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ scale = float(eff->GetAmount());
+ aura.EffectScales.push_back(scale);
+ }
+ }
+
+ MemberStats.PetStats->AuraList.push_back(aura);
+ }
+ }
+ }
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPhase const& phase)
+{
+ data << phase.Flags;
+ data << phase.Id;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPhases const& phases)
+{
+ data << phases.PhaseShiftFlags;
+ data << int32(phases.List.size());
+ data << phases.PersonalGUID;
+
+ for (WorldPackets::Party::GroupPhase const& phase : phases.List)
+ data << phase;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupAura const& aura)
+{
+ data << aura.SpellId;
+ data << aura.Scalings;
+ data << aura.EffectMask;
+
+ data << int32(aura.EffectScales.size());
+ for (float scale : aura.EffectScales)
+ data << scale;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, std::vector<WorldPackets::Party::GroupAura> const& auraList)
+{
+ data << int32(auraList.size());
+ for (WorldPackets::Party::GroupAura const& aura : auraList)
+ data << aura;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPetStats const& petStats)
+{
+ data << petStats.GUID;
+
+ data << petStats.ModelId;
+
+ data << petStats.CurrentHealth;
+ data << petStats.MaxHealth;
+
+ data << petStats.AuraList;
+
+ data.WriteBits(petStats.Name.size(), 8);
+ data.FlushBits();
+ data.WriteString(petStats.Name);
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupMemberStats const& memberStats)
+{
+ data << memberStats.GUID;
+
+ for (uint8 i = 0; i < 2; i++)
+ data << memberStats.Unk704[i];
+
+ data << memberStats.Status;
+
+ data << memberStats.PowerType;
+
+ data << memberStats.Unk322;
+
+ data << memberStats.CurrentHealth;
+ data << memberStats.MaxHealth;
+
+ data << memberStats.CurrentPower;
+ data << memberStats.MaxPower;
+
+ data << memberStats.Level;
+
+ data << memberStats.Unk200000;
+
+ data << memberStats.ZoneID;
+
+ data << memberStats.Unk2000000;
+ data << memberStats.Unk4000000;
+
+ data << memberStats.PositionX;
+ data << memberStats.PositionY;
+ data << memberStats.PositionZ;
+
+ data << memberStats.VehicleSeat;
+
+ data << int32(memberStats.AuraList.size());
+
+ data << memberStats.Phases;
+
+ for (WorldPackets::Party::GroupAura const& aura : memberStats.AuraList)
+ data << aura;
+
+ data.WriteBit(memberStats.PetStats.is_initialized());
+ data.FlushBits();
+
+ if (memberStats.PetStats.is_initialized())
+ data << *memberStats.PetStats;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, std::vector<WorldPackets::Party::GroupPlayerInfos> const& playerList)
+{
+ data << int32(playerList.size());
+
+ for (WorldPackets::Party::GroupPlayerInfos const& playerInfos : playerList)
+ data << playerInfos;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPlayerInfos const& playerInfos)
+{
+ data.WriteBits(playerInfos.Name.size(), 6);
+ data.FlushBits();
+
+ data << playerInfos.GUID;
+ data << playerInfos.Status;
+ data << playerInfos.Subgroup;
+ data << playerInfos.Flags;
+ data << playerInfos.RolesAssigned;
+ data << playerInfos.Class;
+
+ data.WriteString(playerInfos.Name);
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupLfgInfos const& lfgInfos)
+{
+ data << lfgInfos.MyFlags;
+ data << lfgInfos.Slot;
+ data << lfgInfos.MyRandomSlot;
+ data << lfgInfos.MyPartialClear;
+ data << lfgInfos.MyGearDiff;
+ data << lfgInfos.MyStrangerCount;
+ data << lfgInfos.MyKickVoteCount;
+ data << lfgInfos.BootCount;
+
+ data.WriteBit(lfgInfos.Aborted);
+ data.WriteBit(lfgInfos.MyFirstReward);
+ data.FlushBits();
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupLootSettings const& lootSettings)
+{
+ data << lootSettings.Method;
+ data << lootSettings.LootMaster;
+ data << lootSettings.Threshold;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupDifficultySettings const& difficultySettings)
+{
+ data << difficultySettings.DungeonDifficultyID;
+ data << difficultySettings.RaidDifficultyID;
+ data << difficultySettings.LegacyRaidDifficultyID;
+
+ return data;
+}
diff --git a/src/server/game/Server/Packets/PartyPackets.h b/src/server/game/Server/Packets/PartyPackets.h
new file mode 100644
index 00000000000..ed3eed60ef4
--- /dev/null
+++ b/src/server/game/Server/Packets/PartyPackets.h
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PartyPackets_h__
+#define PartyPackets_h__
+
+#include "Packet.h"
+#include "ObjectGuid.h"
+#include "Group.h"
+
+namespace WorldPackets
+{
+ namespace Party
+ {
+ class PartyCommandResult final : public ServerPacket
+ {
+ public:
+ PartyCommandResult() : ServerPacket(SMSG_PARTY_COMMAND_RESULT, 23) { }
+
+ WorldPacket const* Write() override;
+
+ std::string Name;
+ uint8 Command = 0u;
+ uint8 Result = 0u;
+ uint32 ResultData = 0u;
+ ObjectGuid ResultGUID;
+ };
+
+ class PartyInviteClient final : public ClientPacket
+ {
+ public:
+ PartyInviteClient(WorldPacket&& packet) : ClientPacket(CMSG_PARTY_INVITE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ int32 ProposedRoles = 0;
+ int32 TargetCfgRealmID = 0;
+ std::string TargetName;
+ std::string TargetRealm;
+ ObjectGuid TargetGUID;
+ };
+
+ class PartyInvite final : public ServerPacket
+ {
+ public:
+ PartyInvite() : ServerPacket(SMSG_PARTY_INVITE, 55) { }
+
+ WorldPacket const* Write() override;
+ void Initialize(Player* const inviter, int32 proposedRoles, bool canAccept);
+
+ bool MightCRZYou = false;
+ bool MustBeBNetFriend = false;
+ bool AllowMultipleRoles = false;
+ bool Unk2 = false;
+ int16 Unk1 = 0;
+
+ bool CanAccept = false;
+
+ // Inviter
+ ObjectGuid InviterGUID;
+ ObjectGuid InviterBNetAccountId;
+ std::string InviterName;
+
+ // Realm
+ bool IsXRealm = false;
+ bool IsLocal = true;
+ uint32 InviterVirtualRealmAddress = 0u;
+ std::string InviterRealmNameActual;
+ std::string InviterRealmNameNormalized;
+
+ // Lfg
+ int32 ProposedRoles = 0;
+ int32 LfgCompletedMask = 0;
+ std::vector<int32> LfgSlots;
+ };
+
+ class PartyInviteResponse final : public ClientPacket
+ {
+ public:
+ PartyInviteResponse(WorldPacket&& packet) : ClientPacket(CMSG_PARTY_INVITE_RESPONSE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ bool Accept = false;
+ Optional<int32> RolesDesired;
+ };
+
+ class PartyUninvite final : public ClientPacket
+ {
+ public:
+ PartyUninvite(WorldPacket&& packet) : ClientPacket(CMSG_PARTY_UNINVITE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid TargetGUID;
+ std::string Reason;
+ };
+
+ class GroupDecline final : public ServerPacket
+ {
+ public:
+ GroupDecline(std::string const& name) : ServerPacket(SMSG_GROUP_DECLINE, 2 + name.size()), Name(name) { }
+
+ WorldPacket const* Write() override;
+
+ std::string Name;
+ };
+
+ class RequestPartyMemberStats final : public ClientPacket
+ {
+ public:
+ RequestPartyMemberStats(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_PARTY_MEMBER_STATS, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid TargetGUID;
+ };
+
+ struct GroupPhase
+ {
+ uint16 Flags = 0u;
+ uint16 Id = 0u;
+ };
+
+ struct GroupPhases
+ {
+ int32 PhaseShiftFlags = 0;
+ ObjectGuid PersonalGUID;
+ std::vector<GroupPhase> List;
+ };
+
+ struct GroupAura
+ {
+ uint32 SpellId = 0u;
+ uint8 Scalings = 0;
+ uint32 EffectMask = 0u;
+ std::vector<float> EffectScales;
+ };
+
+ struct GroupPetStats
+ {
+ ObjectGuid GUID;
+ std::string Name;
+ int16 ModelId = 0;
+
+ int32 CurrentHealth = 0;
+ int32 MaxHealth = 0;
+
+ std::vector<GroupAura> AuraList;
+ };
+
+ struct GroupMemberStats
+ {
+ ObjectGuid GUID;
+ int16 Level = 0;
+ int16 Status = 0;
+
+ int32 CurrentHealth = 0;
+ int32 MaxHealth;
+
+ uint8 PowerType = 0u;
+ int16 CurrentPower = 0;
+ int16 MaxPower = 0;
+
+ int16 ZoneID = 0;
+ int16 PositionX = 0;
+ int16 PositionY = 0;
+ int16 PositionZ = 0;
+
+ int32 VehicleSeat = 0;
+
+ GroupPhases Phases;
+ std::vector<GroupAura> AuraList;
+ Optional<GroupPetStats> PetStats;
+
+ int16 Unk322 = 0;
+ int16 Unk200000 = 0;
+ int16 Unk2000000 = 0;
+ int32 Unk4000000 = 0;
+ int8 Unk704[2];
+ };
+
+ class PartyMemberStats final : public ServerPacket
+ {
+ public:
+ PartyMemberStats() : ServerPacket(SMSG_PARTY_MEMBER_STATE, 80) { }
+
+ WorldPacket const* Write() override;
+ void Initialize(Player const* player);
+
+ GroupMemberStats MemberStats;
+ bool ForEnemy = false;
+ };
+
+ class SetPartyLeader final : public ClientPacket
+ {
+ public:
+ SetPartyLeader(WorldPacket&& packet) : ClientPacket(CMSG_SET_PARTY_LEADER, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid TargetGUID;
+ };
+
+ class SetRole final : public ClientPacket
+ {
+ public:
+ SetRole(WorldPacket&& packet) : ClientPacket(CMSG_SET_ROLE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid TargetGUID;
+ int32 Role = 0;
+ };
+
+ class RoleChangedInform final : public ServerPacket
+ {
+ public:
+ RoleChangedInform() : ServerPacket(SMSG_ROLE_CHANGED_INFORM, 41) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid From;
+ ObjectGuid ChangedUnit;
+ int32 OldRole = 0;
+ int32 NewRole = 0;
+ };
+
+ class LeaveGroup final : public ClientPacket
+ {
+ public:
+ LeaveGroup(WorldPacket&& packet) : ClientPacket(CMSG_LEAVE_GROUP, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ };
+
+ class SetLootMethod final : public ClientPacket
+ {
+ public:
+ SetLootMethod(WorldPacket&& packet) : ClientPacket(CMSG_SET_LOOT_METHOD, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid LootMasterGUID;
+ uint8 LootMethod = 0u;
+ uint32 LootThreshold = 0u;
+ };
+
+ class MinimapPingClient final : public ClientPacket
+ {
+ public:
+ MinimapPingClient(WorldPacket&& packet) : ClientPacket(CMSG_MINIMAP_PING, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ float PositionX = 0.f;
+ float PositionY = 0.f;
+ };
+
+ class MinimapPing final : public ServerPacket
+ {
+ public:
+ MinimapPing() : ServerPacket(SMSG_MINIMAP_PING, 24) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid Sender;
+ float PositionX = 0.f;
+ float PositionY = 0.f;
+ };
+
+ class UpdateRaidTarget final : public ClientPacket
+ {
+ public:
+ UpdateRaidTarget(WorldPacket&& packet) : ClientPacket(CMSG_UPDATE_RAID_TARGET, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid Target;
+ int8 Symbol = 0;
+ };
+
+ class SendRaidTargetUpdateSingle final : public ServerPacket
+ {
+ public:
+ SendRaidTargetUpdateSingle() : ServerPacket(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, 34) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid Target;
+ ObjectGuid ChangedBy;
+ int8 Symbol = 0;
+ };
+
+ class SendRaidTargetUpdateAll final : public ServerPacket
+ {
+ public:
+ SendRaidTargetUpdateAll() : ServerPacket(SMSG_SEND_RAID_TARGET_UPDATE_ALL, 1 + TARGET_ICONS_COUNT * (1 + 16)) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ std::map<uint8, ObjectGuid> TargetIcons;
+ };
+
+ class ConvertRaid final : public ClientPacket
+ {
+ public:
+ ConvertRaid(WorldPacket&& packet) : ClientPacket(CMSG_CONVERT_RAID, std::move(packet)) { }
+
+ void Read() override;
+
+ bool Raid = false;
+ };
+
+ class RequestPartyJoinUpdates final : public ClientPacket
+ {
+ public:
+ RequestPartyJoinUpdates(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_PARTY_JOIN_UPDATES, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ };
+
+ class SetAssistantLeader final : public ClientPacket
+ {
+ public:
+ SetAssistantLeader(WorldPacket&& packet) : ClientPacket(CMSG_SET_ASSISTANT_LEADER, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid Target;
+ int8 PartyIndex = 0;
+ bool Apply = false;
+ };
+
+ class DoReadyCheck final : public ClientPacket
+ {
+ public:
+ DoReadyCheck(WorldPacket&& packet) : ClientPacket(CMSG_DO_READY_CHECK, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ };
+
+ class ReadyCheckStarted final : public ServerPacket
+ {
+ public:
+ ReadyCheckStarted() : ServerPacket(SMSG_READY_CHECK_STARTED, 37) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid PartyGUID;
+ ObjectGuid InitiatorGUID;
+ uint32 Duration = 0u;
+ };
+
+ class ReadyCheckResponseClient final : public ClientPacket
+ {
+ public:
+ ReadyCheckResponseClient(WorldPacket&& packet) : ClientPacket(CMSG_READY_CHECK_RESPONSE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ bool IsReady = false;
+ };
+
+ class ReadyCheckResponse final : public ServerPacket
+ {
+ public:
+ ReadyCheckResponse() : ServerPacket(SMSG_READY_CHECK_RESPONSE, 19) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid PartyGUID;
+ ObjectGuid Player;
+ bool IsReady = false;
+ };
+
+ class ReadyCheckCompleted final : public ServerPacket
+ {
+ public:
+ ReadyCheckCompleted() : ServerPacket(SMSG_READY_CHECK_COMPLETED, 17) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid PartyGUID;
+ };
+
+ class RequestRaidInfo final : public ClientPacket
+ {
+ public:
+ RequestRaidInfo(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_RAID_INFO, std::move(packet)) { }
+
+ void Read() override { }
+ };
+
+ class OptOutOfLoot final : public ClientPacket
+ {
+ public:
+ OptOutOfLoot(WorldPacket&& packet) : ClientPacket(CMSG_OPT_OUT_OF_LOOT, std::move(packet)) { }
+
+ void Read() override;
+
+ bool PassOnLoot = false;
+ };
+
+ class InitiateRolePoll final : public ClientPacket
+ {
+ public:
+ InitiateRolePoll(WorldPacket&& packet) : ClientPacket(CMSG_INITIATE_ROLE_POLL, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ };
+
+ class RolePollInform final : public ServerPacket
+ {
+ public:
+ RolePollInform() : ServerPacket(SMSG_ROLE_POLL_INFORM, 17) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid From;
+ };
+
+ class GroupNewLeader final : public ServerPacket
+ {
+ public:
+ GroupNewLeader() : ServerPacket(SMSG_GROUP_NEW_LEADER, 14) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ std::string Name;
+ };
+
+ struct GroupPlayerInfos
+ {
+ ObjectGuid GUID;
+ std::string Name;
+ uint8 Class = 0;
+
+ uint8 Status = 0u;
+ uint8 Subgroup = 0u;
+ uint8 Flags = 0u;
+ uint8 RolesAssigned = 0u;
+ };
+
+ struct GroupLfgInfos
+ {
+ int32 Slot = 0u;
+ int8 BootCount = 0;
+
+ bool Aborted = false;
+
+ int32 MyRandomSlot = 0;
+ uint8 MyFlags = 0u;
+ uint8 MyPartialClear = 0u;
+ float MyGearDiff = 0.f;
+
+ int8 MyStrangerCount = 0;
+ int8 MyKickVoteCount = 0;
+
+ bool MyFirstReward = false;
+ };
+
+ struct GroupLootSettings
+ {
+ uint8 Method = 0u;
+ ObjectGuid LootMaster;
+ uint8 Threshold = 0u;
+ };
+
+ struct GroupDifficultySettings
+ {
+ uint32 DungeonDifficultyID = 0u;
+ uint32 RaidDifficultyID = 0u;
+ uint32 LegacyRaidDifficultyID = 0u;
+ };
+
+ class PartyUpdate final : public ServerPacket
+ {
+ public:
+ PartyUpdate() : ServerPacket(SMSG_PARTY_UPDATE, 200) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyFlags = 0;
+ int8 PartyIndex = 0;
+ int8 PartyType = 0;
+
+ ObjectGuid PartyGUID;
+ ObjectGuid LeaderGUID;
+
+ int32 MyIndex = 0;
+ int32 SequenceNum = 0;
+
+ std::vector<GroupPlayerInfos> PlayerList;
+
+ Optional<GroupLfgInfos> LfgInfos;
+ Optional<GroupLootSettings> LootSettings;
+ Optional<GroupDifficultySettings> DifficultySettings;
+ };
+
+ class SetEveryoneIsAssistant final : public ClientPacket
+ {
+ public:
+ SetEveryoneIsAssistant(WorldPacket&& packet) : ClientPacket(CMSG_SET_EVERYONE_IS_ASSISTANT, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ bool EveryoneIsAssistant = false;
+ };
+
+ class ChangeSubGroup final : public ClientPacket
+ {
+ public:
+ ChangeSubGroup(WorldPacket&& packet) : ClientPacket(CMSG_CHANGE_SUB_GROUP, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid TargetGUID;
+ int8 PartyIndex = 0;
+ uint8 NewSubGroup = 0u;
+ };
+
+ class SwapSubGroups final : public ClientPacket
+ {
+ public:
+ SwapSubGroups(WorldPacket&& packet) : ClientPacket(CMSG_SWAP_SUB_GROUPS, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid FirstTarget;
+ ObjectGuid SecondTarget;
+ int8 PartyIndex = 0;
+ };
+
+ class ClearRaidMarker final : public ClientPacket
+ {
+ public:
+ ClearRaidMarker(WorldPacket&& packet) : ClientPacket(CMSG_CLEAR_RAID_MARKER, std::move(packet)) { }
+
+ void Read() override;
+
+ uint8 MarkerId = 0u;
+ };
+
+ class RaidMarkersChanged final : public ServerPacket
+ {
+ public:
+ RaidMarkersChanged() : ServerPacket(SMSG_RAID_MARKERS_CHANGED, 6) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ uint32 ActiveMarkers = 0u;
+
+ std::vector<RaidMarker*> RaidMarkers;
+ };
+ }
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPhase const& phase);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPhases const& phases);
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupAura const& aura);
+ByteBuffer& operator<<(ByteBuffer& data, std::vector<WorldPackets::Party::GroupAura> const& auraList);
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPetStats const& petStats);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupMemberStats const& memberStats);
+
+ByteBuffer& operator<<(ByteBuffer& data, std::vector<WorldPackets::Party::GroupPlayerInfos> const& playerList);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPlayerInfos const& playerInfos);
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupLfgInfos const& lfgInfos);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupLootSettings const& lootSettings);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupDifficultySettings const& difficultySettings);
+
+#endif // PartyPackets_h__
diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp
index ad4001899fe..d792783cf9a 100644
--- a/src/server/game/Server/Packets/QuestPackets.cpp
+++ b/src/server/game/Server/Packets/QuestPackets.cpp
@@ -72,7 +72,7 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
_worldPacket << Info.SuggestedGroupNum;
_worldPacket << Info.RewardNextQuest;
_worldPacket << Info.RewardXPDifficulty;
- _worldPacket << Info.Float10; // Unk
+ _worldPacket << Info.RewardXPMultiplier;
_worldPacket << Info.RewardMoney;
_worldPacket << Info.RewardMoneyDifficulty;
_worldPacket << Info.Float13; // Unk
diff --git a/src/server/game/Server/Packets/QuestPackets.h b/src/server/game/Server/Packets/QuestPackets.h
index a83bcc219be..b2d7269ebb0 100644
--- a/src/server/game/Server/Packets/QuestPackets.h
+++ b/src/server/game/Server/Packets/QuestPackets.h
@@ -116,6 +116,7 @@ namespace WorldPackets
int32 SuggestedGroupNum = 0;
int32 RewardNextQuest = 0; // client will request this quest from NPC, if not 0
int32 RewardXPDifficulty = 0; // used for calculating rewarded experience
+ float RewardXPMultiplier = 1.0f;
int32 RewardMoney = 0; // reward money (below max lvl)
int32 RewardMoneyDifficulty = 0; // used in XP calculation at client
int32 RewardBonusMoney = 0;
@@ -163,8 +164,6 @@ namespace WorldPackets
int32 RewardCurrencyID[QUEST_REWARD_CURRENCY_COUNT] = {};
int32 RewardCurrencyQty[QUEST_REWARD_CURRENCY_COUNT] = {};
- // Non JAM data
- float Float10 = 1.0f;
float Float13 = 1.0f;
int32 AllowableRaces = -1;
};
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 4c87e00fc91..70a22f0b1bb 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -33,6 +33,7 @@
#include "Packets/GameObjectPackets.h"
#include "Packets/GarrisonPackets.h"
#include "Packets/GuildPackets.h"
+#include "Packets/PartyPackets.h"
#include "Packets/InspectPackets.h"
#include "Packets/InstancePackets.h"
#include "Packets/ItemPackets.h"
@@ -259,7 +260,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_CHALLENGE_MODE_REQUEST_MAP_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CHANGE_BAG_SLOT_FLAG, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CHANGE_MONUMENT_APPEARANCE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANGE_SUB_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupChangeSubGroupOpcode );
+ DEFINE_HANDLER(CMSG_CHANGE_SUB_GROUP, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::ChangeSubGroup, &WorldSession::HandleChangeSubGroupOpcode);
DEFINE_HANDLER(CMSG_CHARACTER_RENAME_REQUEST, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CharacterRenameRequest, &WorldSession::HandleCharRenameOpcode);
DEFINE_HANDLER(CMSG_CHAR_CUSTOMIZE, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CharCustomize, &WorldSession::HandleCharCustomizeOpcode);
DEFINE_HANDLER(CMSG_CHAR_DELETE, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CharDelete, &WorldSession::HandleCharDeleteOpcode);
@@ -308,14 +309,14 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_CHAT_MESSAGE_SAY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatMessage, &WorldSession::HandleChatMessageOpcode);
DEFINE_HANDLER(CMSG_CHAT_MESSAGE_WHISPER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatMessageWhisper, &WorldSession::HandleChatMessageWhisperOpcode);
DEFINE_HANDLER(CMSG_CHAT_MESSAGE_YELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatMessage, &WorldSession::HandleChatMessageOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAT_REGISTER_ADDON_PREFIXES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonRegisteredPrefixesOpcode);
+ DEFINE_HANDLER(CMSG_CHAT_REGISTER_ADDON_PREFIXES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatRegisterAddonPrefixes, &WorldSession::HandleAddonRegisteredPrefixesOpcode);
DEFINE_HANDLER(CMSG_CHAT_REPORT_FILTERED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAT_REPORT_IGNORED, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChatIgnoredOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUnregisterAddonPrefixesOpcode);
+ DEFINE_HANDLER(CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatUnregisterAllAddonPrefixes, &WorldSession::HandleUnregisterAllAddonPrefixesOpcode);
DEFINE_HANDLER(CMSG_CHECK_RAF_EMAIL_ENABLED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CHECK_WOW_TOKEN_VETERAN_ELIGIBILITY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CHOICE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_CLEAR_RAID_MARKER, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_CLEAR_RAID_MARKER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::ClearRaidMarker, &WorldSession::HandleClearRaidMarker);
DEFINE_HANDLER(CMSG_CLEAR_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::ClearTradeItem, &WorldSession::HandleClearTradeItemOpcode);
DEFINE_HANDLER(CMSG_CLIENT_PORT_GRAVEYARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::PortGraveyard, &WorldSession::HandlePortGraveyard);
DEFINE_HANDLER(CMSG_CLOSE_INTERACTION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -331,7 +332,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_COMPLETE_MOVIE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_CONFIRM_RESPEC_WIPE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleConfirmRespecWipeOpcode );
DEFINE_HANDLER(CMSG_CONNECT_TO_FAILED, STATUS_NEVER, PROCESS_INPLACE, WorldPacket, &WorldSession::Handle_EarlyProccess);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CONVERT_RAID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupRaidConvertOpcode );
+ DEFINE_HANDLER(CMSG_CONVERT_RAID, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::ConvertRaid, &WorldSession::HandleConvertRaidOpcode);
DEFINE_HANDLER(CMSG_CREATE_CHARACTER, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CreateCharacter, &WorldSession::HandleCharCreateOpcode);
DEFINE_HANDLER(CMSG_CREATE_SHIPMENT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_DB_QUERY_BULK, STATUS_AUTHED, PROCESS_INPLACE, WorldPackets::Query::DBQueryBulk, &WorldSession::HandleDBQueryBulk);
@@ -357,7 +358,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_DISCARDED_TIME_SYNC_ACKS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_DISMISS_CRITTER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissCritter );
DEFINE_HANDLER(CMSG_DO_MASTER_LOOT_ROLL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_DO_READY_CHECK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckOpcode );
+ DEFINE_HANDLER(CMSG_DO_READY_CHECK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::DoReadyCheck, &WorldSession::HandleDoReadyCheckOpcode);
DEFINE_HANDLER(CMSG_DUEL_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Duel::DuelResponse, &WorldSession::HandleDuelResponseOpcode);
DEFINE_HANDLER(CMSG_EJECT_PASSENGER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::EjectPassenger, &WorldSession::HandleEjectPassenger);
DEFINE_HANDLER(CMSG_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::EmoteClient, &WorldSession::HandleEmoteOpcode);
@@ -458,7 +459,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_HEARTH_AND_RESURRECT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Battleground::HearthAndResurrect, &WorldSession::HandleHearthAndResurrect);
DEFINE_HANDLER(CMSG_IGNORE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::IgnoreTrade, &WorldSession::HandleIgnoreTradeOpcode);
DEFINE_HANDLER(CMSG_INCREASE_CAST_TIME_FOR_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_INITIATE_ROLE_POLL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRolePollBeginOpcode);
+ DEFINE_HANDLER(CMSG_INITIATE_ROLE_POLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::InitiateRolePoll, &WorldSession::HandleInitiateRolePoll);
DEFINE_HANDLER(CMSG_INITIATE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::InitiateTrade, &WorldSession::HandleInitiateTradeOpcode);
DEFINE_HANDLER(CMSG_INSPECT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Inspect::Inspect, &WorldSession::HandleInspectOpcode);
DEFINE_HANDLER(CMSG_INSPECT_PVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Inspect::InspectPVPRequest, &WorldSession::HandleInspectPVP);
@@ -471,7 +472,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_KEYBOUND_OVERRIDE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_LEARN_PET_SPECIALIZATION_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_LEARN_TALENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Talent::LearnTalents, &WorldSession::HandleLearnTalentsOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_LEAVE_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupDisbandOpcode );
+ DEFINE_HANDLER(CMSG_LEAVE_GROUP, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::LeaveGroup, &WorldSession::HandleLeaveGroupOpcode);
DEFINE_HANDLER(CMSG_LEAVE_PET_BATTLE_QUEUE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_LFG_LIST_APPLY_TO_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_LFG_LIST_CANCEL_APPLICATION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -514,7 +515,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_MAIL_TAKE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailTakeItem, &WorldSession::HandleMailTakeItem);
DEFINE_HANDLER(CMSG_MAIL_TAKE_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailTakeMoney, &WorldSession::HandleMailTakeMoney);
DEFINE_OPCODE_HANDLER_OLD(CMSG_MASTER_LOOT_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMasterGiveOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_MINIMAP_PING, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMinimapPingOpcode );
+ DEFINE_HANDLER(CMSG_MINIMAP_PING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::MinimapPingClient, &WorldSession::HandleMinimapPingOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_MISSILE_TRAJECTORY_COLLISION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateProjectilePosition );
DEFINE_HANDLER(CMSG_MOUNT_SET_FAVORITE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_MOUNT_SPECIAL_ANIM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSpecialAnimOpcode );
@@ -590,10 +591,10 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_OPEN_MISSION_NPC, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_OPEN_SHIPMENT_NPC, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_OPEN_TRADESKILL_NPC, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_OPT_OUT_OF_LOOT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleOptOutOfLootOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_PARTY_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_PARTY_INVITE_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteResponseOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_PARTY_UNINVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteOpcode );
+ DEFINE_HANDLER(CMSG_OPT_OUT_OF_LOOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::OptOutOfLoot, &WorldSession::HandleOptOutOfLootOpcode);
+ DEFINE_HANDLER(CMSG_PARTY_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::PartyInviteClient, &WorldSession::HandlePartyInviteOpcode);
+ DEFINE_HANDLER(CMSG_PARTY_INVITE_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::PartyInviteResponse, &WorldSession::HandlePartyInviteResponseOpcode);
+ DEFINE_HANDLER(CMSG_PARTY_UNINVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::PartyUninvite, &WorldSession::HandlePartyUninviteOpcode);
DEFINE_HANDLER(CMSG_PETITION_BUY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::PetitionBuy, &WorldSession::HandlePetitionBuy);
DEFINE_HANDLER(CMSG_PETITION_RENAME_GUILD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::PetitionRenameGuild, &WorldSession::HandlePetitionRenameGuild);
DEFINE_HANDLER(CMSG_PETITION_SHOW_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::PetitionShowList, &WorldSession::HandlePetitionShowList);
@@ -655,7 +656,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEST_PUSH_RESULT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult );
DEFINE_HANDLER(CMSG_QUEUED_MESSAGES_END, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_RANDOM_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::RandomRollClient, &WorldSession::HandleRandomRollOpcode);
- DEFINE_HANDLER(CMSG_READY_CHECK_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_READY_CHECK_RESPONSE, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::ReadyCheckResponseClient, &WorldSession::HandleReadyCheckResponseOpcode);
DEFINE_HANDLER(CMSG_READ_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::ReadItem, &WorldSession::HandleReadItem);
DEFINE_HANDLER(CMSG_RECLAIM_CORPSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::ReclaimCorpse, &WorldSession::HandleReclaimCorpse);
DEFINE_HANDLER(CMSG_RECRUIT_A_FRIEND, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -676,12 +677,12 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_REQUEST_GUILD_REWARDS_LIST, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Guild::RequestGuildRewardsList, &WorldSession::HandleRequestGuildRewardsList);
DEFINE_HANDLER(CMSG_REQUEST_HONOR_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Inspect::RequestHonorStats, &WorldSession::HandleRequestHonorStatsOpcode);
DEFINE_HANDLER(CMSG_REQUEST_LFG_LIST_BLACKLIST, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_PARTY_JOIN_UPDATES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupRequestJoinUpdates);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_PARTY_MEMBER_STATS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPartyMemberStatsOpcode);
+ DEFINE_HANDLER(CMSG_REQUEST_PARTY_JOIN_UPDATES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::RequestPartyJoinUpdates, &WorldSession::HandleRequestPartyJoinUpdates);
+ DEFINE_HANDLER(CMSG_REQUEST_PARTY_MEMBER_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::RequestPartyMemberStats, &WorldSession::HandleRequestPartyMemberStatsOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_PET_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPetInfoOpcode );
DEFINE_HANDLER(CMSG_REQUEST_PLAYED_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::RequestPlayedTime, &WorldSession::HandlePlayedTime);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_PVP_REWARDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleRequestPvpReward );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_RAID_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode );
+ DEFINE_HANDLER(CMSG_REQUEST_RAID_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::RequestRaidInfo, &WorldSession::HandleRequestRaidInfoOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_RATED_BATTLEFIELD_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRatedBattlefieldInfo);
DEFINE_HANDLER(CMSG_REQUEST_RESEARCH_HISTORY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_STABLED_PETS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleListStabledPetsOpcode );
@@ -695,7 +696,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_RESURRECT_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::ResurrectResponse, &WorldSession::HandleResurrectResponse);
DEFINE_HANDLER(CMSG_REVERT_MONUMENT_APPEARANCE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_RIDE_VEHICLE_INTERACT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::RideVehicleInteract, &WorldSession::HandleRideVehicleInteract);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SAVE_CUF_PROFILES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleSaveCUFProfiles );
+ DEFINE_HANDLER(CMSG_SAVE_CUF_PROFILES, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Misc::SaveCUFProfiles, &WorldSession::HandleSaveCUFProfiles);
DEFINE_HANDLER(CMSG_SAVE_EQUIPMENT_SET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::EquipmentSet::SaveEquipmentSet, &WorldSession::HandleEquipmentSetSave);
DEFINE_HANDLER(CMSG_SAVE_GUILD_EMBLEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::SaveGuildEmblem, &WorldSession::HandleSaveGuildEmblem);
DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_CANCELED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Scenes::ScenePlaybackCanceled, &WorldSession::HandleScenePlaybackCanceled);
@@ -716,7 +717,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SET_ACTIVE_MOVER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Movement::SetActiveMover, &WorldSession::HandleSetActiveMoverOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ACTIVE_VOICE_CHANNEL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveVoiceChannel );
DEFINE_HANDLER(CMSG_SET_ADVANCED_COMBAT_LOGGING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ASSISTANT_LEADER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupAssistantLeaderOpcode);
+ DEFINE_HANDLER(CMSG_SET_ASSISTANT_LEADER, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetAssistantLeader, &WorldSession::HandleSetAssistantLeaderOpcode);
DEFINE_HANDLER(CMSG_SET_BACKPACK_AUTOSORT_DISABLED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_BANK_AUTOSORT_DISABLED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_BANK_BAG_SLOT_FLAG, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -724,22 +725,22 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SET_CURRENCY_FLAGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_DIFFICULTY_ID, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_DUNGEON_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetDungeonDifficulty, &WorldSession::HandleSetDungeonDifficultyOpcode);
- DEFINE_HANDLER(CMSG_SET_EVERYONE_IS_ASSISTANT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_SET_EVERYONE_IS_ASSISTANT, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetEveryoneIsAssistant, &WorldSession::HandleSetEveryoneIsAssistant);
DEFINE_HANDLER(CMSG_SET_FACTION_AT_WAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionAtWar, &WorldSession::HandleSetFactionAtWar);
DEFINE_HANDLER(CMSG_SET_FACTION_INACTIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionInactive, &WorldSession::HandleSetFactionInactiveOpcode);
DEFINE_HANDLER(CMSG_SET_FACTION_NOT_AT_WAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionNotAtWar, &WorldSession::HandleSetFactionNotAtWar);
DEFINE_HANDLER(CMSG_SET_INSERT_ITEMS_LEFT_TO_RIGHT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_LFG_BONUS_FACTION_ID, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_LOOT_METHOD, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMethodOpcode );
+ DEFINE_HANDLER(CMSG_SET_LOOT_METHOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::SetLootMethod, &WorldSession::HandleSetLootMethodOpcode);
DEFINE_HANDLER(CMSG_SET_LOOT_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PARTY_ASSIGNMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePartyAssignmentOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PARTY_LEADER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupSetLeaderOpcode );
+ DEFINE_HANDLER(CMSG_SET_PARTY_LEADER, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetPartyLeader, &WorldSession::HandleSetPartyLeaderOpcode);
DEFINE_HANDLER(CMSG_SET_PET_SLOT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames );
DEFINE_HANDLER(CMSG_SET_PREFERRED_CEMETERY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_PVP, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_RAID_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetRaidDifficulty, &WorldSession::HandleSetRaidDifficultyOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ROLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupSetRolesOpcode );
+ DEFINE_HANDLER(CMSG_SET_ROLE, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetRole, &WorldSession::HandleSetRoleOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SAVED_INSTANCE_EXTEND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend );
DEFINE_HANDLER(CMSG_SET_SELECTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetSelection, &WorldSession::HandleSetSelectionOpcode);
DEFINE_HANDLER(CMSG_SET_SHEATHED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Combat::SetSheathed, &WorldSession::HandleSetSheathedOpcode);
@@ -775,7 +776,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SWAP_INV_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SwapInvItem, &WorldSession::HandleSwapInvItemOpcode);
DEFINE_HANDLER(CMSG_SWAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SwapItem, &WorldSession::HandleSwapItem);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SWAP_SUB_GROUPS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupSwapSubGroupOpcode );
+ DEFINE_HANDLER(CMSG_SWAP_SUB_GROUPS, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SwapSubGroups, &WorldSession::HandleSwapSubGroupsOpcode);
DEFINE_HANDLER(CMSG_SWAP_VOID_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::VoidStorage::SwapVoidItem, &WorldSession::HandleVoidSwapItem);
DEFINE_HANDLER(CMSG_TABARD_VENDOR_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleTabardVendorActivateOpcode);
DEFINE_HANDLER(CMSG_TALK_TO_GOSSIP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleGossipHelloOpcode);
@@ -809,7 +810,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_UPDATE_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::ClientConfig::UserClientUpdateAccountData, &WorldSession::HandleUpdateAccountData);
DEFINE_HANDLER(CMSG_UPDATE_CLIENT_SETTINGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_UPDATE_MISSILE_TRAJECTORY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateMissileTrajectory );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_UPDATE_RAID_TARGET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidTargetUpdateOpcode );
+ DEFINE_HANDLER(CMSG_UPDATE_RAID_TARGET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::UpdateRaidTarget, &WorldSession::HandleUpdateRaidTargetOpcode);
DEFINE_HANDLER(CMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Token::UpdateListedAuctionableTokens, &WorldSession::HandleUpdateListedAuctionableTokens);
DEFINE_HANDLER(CMSG_UPDATE_WOW_TOKEN_COUNT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_UPGRADE_GARRISON, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -990,7 +991,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHALLENGE_MODE_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANGE_PLAYER_DIFFICULTY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_LIST, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY_JOINED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY_LEFT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1000,8 +1001,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_UPGRADE_COMPLETE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_UPGRADE_SPELL_TIER_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_UPGRADE_STARTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_FACTION_CHANGE_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_AUTO_RESPONDED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1169,10 +1170,10 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GOSSIP_MESSAGE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GOSSIP_POI, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_ACTION_THROTTLED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_DECLINE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_DESTROYED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_NEW_LEADER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_UNINVITE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_DECLINE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_DESTROYED, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_NEW_LEADER, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_UNINVITE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_DELETED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_EARNED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_MEMBERS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1248,7 +1249,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_ENCOUNTER_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_ENCOUNTER_TIMER_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_GROUP_SIZE_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_INFO, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_RESET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_RESET_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_SAVE_CREATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1257,12 +1258,12 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INVENTORY_CHANGE_FAILURE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_IS_QUEST_COMPLETE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_COOLDOWN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_ENCHANT_TIME_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_COOLDOWN, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_ENCHANT_TIME_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_EXPIRE_PURCHASE_REFUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_PURCHASE_REFUND_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_PUSH_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_KICK_REASON, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARN_TALENT_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1298,7 +1299,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LIVE_REGION_ACCOUNT_RESTORE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LIVE_REGION_CHARACTER_COPY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LIVE_REGION_GET_ACCOUNT_CHARACTER_LIST_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_EQUIPMENT_SET, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_SELECTED_TROPHY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGIN_SET_TIME_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
@@ -1327,7 +1328,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAP_OBJ_EVENTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MASTER_LOOT_CANDIDATE_LIST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MESSAGE_BOX, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_MINIMAP_PING, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MINIMAP_PING, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MIRROR_IMAGE_COMPONENTED_DATA, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MIRROR_IMAGE_CREATURE_DATA, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MISSILE_CANCEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1431,11 +1432,11 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_OPEN_SHIPMENT_NPC_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_OVERRIDE_LIGHT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PAGE_TEXT, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_COMMAND_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_INVITE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_COMMAND_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_INVITE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_KILL_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PAUSE_MIRROR_TIMER, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PENDING_RAID_LOCK, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PETITION_ALREADY_SIGNED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1539,12 +1540,12 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_DIFFICULTY_SET, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_GROUP_ONLY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_INSTANCE_MESSAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_MARKERS_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_MARKERS_CHANGED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RANDOM_ROLL, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RATED_BATTLEFIELD_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_COMPLETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_STARTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_COMPLETED, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_STARTED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_READ_ITEM_RESULT_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_READ_ITEM_RESULT_OK, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REALM_QUERY_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1573,9 +1574,9 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_TOKEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHANGED_INFORM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHANGED_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHOSEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_POLL_INFORM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_POLL_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RUNE_REGEN_DEBUG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_BOOT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_COMPLETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1594,8 +1595,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SELL_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_ITEM_PASSIVES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_KNOWN_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_ALL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_ALL, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_SPELL_CHARGES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_SPELL_HISTORY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_UNLEARN_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
@@ -1657,7 +1658,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_MULTISTRIKE_EFFECT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_NON_MELEE_DAMAGE_LOG, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_OR_DAMAGE_IMMUNE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_PERIODIC_AURA_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_PERIODIC_AURA_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_NEVER, CONNECTION_TYPE_REALM);
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index fa557616450..650e100f514 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -913,31 +913,23 @@ bool WorldSession::IsAddonRegistered(const std::string& prefix) const
return itr != _registeredAddonPrefixes.end();
}
-void WorldSession::HandleUnregisterAddonPrefixesOpcode(WorldPacket& /*recvPacket*/) // empty packet
+void WorldSession::HandleUnregisterAllAddonPrefixesOpcode(WorldPackets::Chat::ChatUnregisterAllAddonPrefixes& /*packet*/) // empty packet
{
_registeredAddonPrefixes.clear();
}
-void WorldSession::HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket)
+void WorldSession::HandleAddonRegisteredPrefixesOpcode(WorldPackets::Chat::ChatRegisterAddonPrefixes& packet)
{
- // This is always sent after CMSG_UNREGISTER_ALL_ADDON_PREFIXES
+ // This is always sent after CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES
- uint32 count = recvPacket.ReadBits(25);
-
- if (count > REGISTERED_ADDON_PREFIX_SOFTCAP)
+ if (packet.Prefixes.size() > REGISTERED_ADDON_PREFIX_SOFTCAP)
{
// if we have hit the softcap (64) nothing should be filtered
_filterAddonMessages = false;
- recvPacket.rfinish();
return;
}
- std::vector<uint8> lengths(count);
- for (uint32 i = 0; i < count; ++i)
- lengths[i] = recvPacket.ReadBits(5);
-
- for (uint32 i = 0; i < count; ++i)
- _registeredAddonPrefixes.push_back(recvPacket.ReadString(lengths[i]));
+ _registeredAddonPrefixes.insert(_registeredAddonPrefixes.end(), packet.Prefixes.begin(), packet.Prefixes.end());
if (_registeredAddonPrefixes.size() > REGISTERED_ADDON_PREFIX_SOFTCAP) // shouldn't happen
{
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 6cfa8202af4..8f74a8900b0 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -171,9 +171,6 @@ namespace WorldPackets
class ChannelPlayerCommand;
class JoinChannel;
class LeaveChannel;
- class UserlistAdd;
- class UserlistRemove;
- class UserlistUpdate;
}
namespace Chat
@@ -189,6 +186,8 @@ namespace WorldPackets
class ChatMessageEmote;
class CTextEmote;
class EmoteClient;
+ class ChatRegisterAddonPrefixes;
+ class ChatUnregisterAllAddonPrefixes;
}
namespace Combat
@@ -278,6 +277,11 @@ namespace WorldPackets
class RequestHonorStats;
}
+ namespace Instance
+ {
+ class InstanceInfo;
+ }
+
namespace Item
{
class AutoEquipItem;
@@ -341,6 +345,8 @@ namespace WorldPackets
class CompleteCinematic;
class NextCinematicCamera;
class FarSight;
+ class LoadCUFProfiles;
+ class SaveCUFProfiles;
}
namespace Movement
@@ -363,6 +369,47 @@ namespace WorldPackets
class TrainerBuySpell;
}
+ namespace Party
+ {
+ class PartyCommandResult;
+ class PartyInviteClient;
+ class PartyInvite;
+ class PartyInviteResponse;
+ class PartyUninvite;
+ class GroupDecline;
+ class RequestPartyMemberStats;
+ class PartyMemberStats;
+ class SetPartyLeader;
+ class SetRole;
+ class RoleChangedInform;
+ class SetLootMethod;
+ class LeaveGroup;
+ class MinimapPingClient;
+ class MinimapPing;
+ class UpdateRaidTarget;
+ class SendRaidTargetUpdateSingle;
+ class SendRaidTargetUpdateAll;
+ class ConvertRaid;
+ class RequestPartyJoinUpdates;
+ class SetAssistantLeader;
+ class DoReadyCheck;
+ class ReadyCheckStarted;
+ class ReadyCheckResponseClient;
+ class ReadyCheckResponse;
+ class ReadyCheckCompleted;
+ class RequestRaidInfo;
+ class OptOutOfLoot;
+ class InitiateRolePoll;
+ class RolePollInform;
+ class GroupNewLeader;
+ class PartyUpdate;
+ class SetEveryoneIsAssistant;
+ class ChangeSubGroup;
+ class SwapSubGroups;
+ class RaidMarkersChanged;
+ class ClearRaidMarker;
+ }
+
namespace Petition
{
class DeclinePetition;
@@ -858,8 +905,6 @@ class WorldSession
void SendNotInArenaTeamPacket(uint8 type);
void SendPetitionShowList(ObjectGuid guid);
- void BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data);
-
void DoLootRelease(ObjectGuid lguid);
// Account mute time
@@ -1054,28 +1099,31 @@ class WorldSession
void HandleMoveTimeSkippedOpcode(WorldPackets::Movement::MoveTimeSkipped& moveTimeSkipped);
void HandleMovementAckMessage(WorldPackets::Movement::MovementAckMessage& movementAck);
- void HandleRequestRaidInfoOpcode(WorldPacket& recvData);
+ void HandleRequestRaidInfoOpcode(WorldPackets::Party::RequestRaidInfo& packet);
- void HandleGroupInviteOpcode(WorldPacket& recvPacket);
+ void HandlePartyInviteOpcode(WorldPackets::Party::PartyInviteClient& packet);
//void HandleGroupCancelOpcode(WorldPacket& recvPacket);
- void HandleGroupInviteResponseOpcode(WorldPacket& recvPacket);
- void HandleGroupUninviteOpcode(WorldPacket& recvPacket);
- void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket);
- void HandleGroupSetRolesOpcode(WorldPacket& recvData);
- void HandleGroupDisbandOpcode(WorldPacket& recvPacket);
- void HandleOptOutOfLootOpcode(WorldPacket& recvData);
- void HandleLootMethodOpcode(WorldPacket& recvPacket);
+ void HandlePartyInviteResponseOpcode(WorldPackets::Party::PartyInviteResponse& packet);
+ void HandlePartyUninviteOpcode(WorldPackets::Party::PartyUninvite& packet);
+ void HandleSetPartyLeaderOpcode(WorldPackets::Party::SetPartyLeader& packet);
+ void HandleSetRoleOpcode(WorldPackets::Party::SetRole& packet);
+ void HandleLeaveGroupOpcode(WorldPackets::Party::LeaveGroup& packet);
+ void HandleOptOutOfLootOpcode(WorldPackets::Party::OptOutOfLoot& packet);
+ void HandleSetLootMethodOpcode(WorldPackets::Party::SetLootMethod& packet);
void HandleLootRoll(WorldPackets::Loot::LootRoll& packet);
- void HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData);
- void HandleRaidTargetUpdateOpcode(WorldPacket& recvData);
- void HandleRaidReadyCheckOpcode(WorldPacket& recvData);
- void HandleGroupRaidConvertOpcode(WorldPacket& recvData);
- void HandleGroupRequestJoinUpdates(WorldPacket& recvData);
- void HandleGroupChangeSubGroupOpcode(WorldPacket& recvData);
- void HandleGroupSwapSubGroupOpcode(WorldPacket& recvData);
- void HandleGroupAssistantLeaderOpcode(WorldPacket& recvData);
+ void HandleRequestPartyMemberStatsOpcode(WorldPackets::Party::RequestPartyMemberStats& packet);
+ void HandleUpdateRaidTargetOpcode(WorldPackets::Party::UpdateRaidTarget& packet);
+ void HandleDoReadyCheckOpcode(WorldPackets::Party::DoReadyCheck& packet);
+ void HandleReadyCheckResponseOpcode(WorldPackets::Party::ReadyCheckResponseClient& packet);
+ void HandleConvertRaidOpcode(WorldPackets::Party::ConvertRaid& packet);
+ void HandleRequestPartyJoinUpdates(WorldPackets::Party::RequestPartyJoinUpdates& packet);
+ void HandleChangeSubGroupOpcode(WorldPackets::Party::ChangeSubGroup& packet);
+ void HandleSwapSubGroupsOpcode(WorldPackets::Party::SwapSubGroups& packet);
+ void HandleSetAssistantLeaderOpcode(WorldPackets::Party::SetAssistantLeader& packet);
void HandlePartyAssignmentOpcode(WorldPacket& recvData);
- void HandleRolePollBeginOpcode(WorldPacket& recvData);
+ void HandleInitiateRolePoll(WorldPackets::Party::InitiateRolePoll& packet);
+ void HandleSetEveryoneIsAssistant(WorldPackets::Party::SetEveryoneIsAssistant& packet);
+ void HandleClearRaidMarker(WorldPackets::Party::ClearRaidMarker& packet);
void HandleDeclinePetition(WorldPackets::Petition::DeclinePetition& packet);
void HandleOfferPetition(WorldPackets::Petition::OfferPetition& packet);
@@ -1266,8 +1314,8 @@ class WorldSession
void HandleTextEmoteOpcode(WorldPackets::Chat::CTextEmote& packet);
void HandleChatIgnoredOpcode(WorldPacket& recvPacket);
- void HandleUnregisterAddonPrefixesOpcode(WorldPacket& recvPacket);
- void HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket);
+ void HandleUnregisterAllAddonPrefixesOpcode(WorldPackets::Chat::ChatUnregisterAllAddonPrefixes& packet);
+ void HandleAddonRegisteredPrefixesOpcode(WorldPackets::Chat::ChatRegisterAddonPrefixes& packet);
void HandleReclaimCorpse(WorldPackets::Misc::ReclaimCorpse& packet);
void HandleQueryCorpseLocation(WorldPackets::Query::QueryCorpseLocationFromClient& packet);
@@ -1340,7 +1388,7 @@ class WorldSession
void HandleWardenDataOpcode(WorldPacket& recvData);
void HandleWorldTeleportOpcode(WorldPacket& recvData);
- void HandleMinimapPingOpcode(WorldPacket& recvData);
+ void HandleMinimapPingOpcode(WorldPackets::Party::MinimapPingClient& packet);
void HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient& packet);
void HandleFarSightOpcode(WorldPackets::Misc::FarSight& packet);
void HandleSetDungeonDifficultyOpcode(WorldPackets::Misc::SetDungeonDifficulty& setDungeonDifficulty);
@@ -1473,7 +1521,7 @@ class WorldSession
void HandleRequestWowTokenMarketPrice(WorldPackets::Token::RequestWowTokenMarketPrice& requestWowTokenMarketPrice);
// Compact Unit Frames (4.x)
- void HandleSaveCUFProfiles(WorldPacket& recvPacket);
+ void HandleSaveCUFProfiles(WorldPackets::Misc::SaveCUFProfiles& packet);
void SendLoadCUFProfiles();
// Garrison
diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h
index 7e60ac9b5da..669b90e6392 100644
--- a/src/server/game/Spells/Auras/SpellAuraDefines.h
+++ b/src/server/game/Spells/Auras/SpellAuraDefines.h
@@ -524,7 +524,7 @@ enum AuraType
SPELL_AURA_464 = 464,
SPELL_AURA_465 = 465,
SPELL_AURA_466 = 466,
- SPELL_AURA_467 = 467,
+ SPELL_AURA_MOD_STAT_BONUS_PCT = 467, // Affects stat gain from all sources except base stats
SPELL_AURA_468 = 468,
SPELL_AURA_469 = 469,
SPELL_AURA_471 = 471,
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index a3b0c4788e7..5abf9d10375 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -527,7 +527,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //464
&AuraEffect::HandleNULL, //465
&AuraEffect::HandleNULL, //466
- &AuraEffect::HandleNULL, //467
+ &AuraEffect::HandleModStatBonusPercent, //467 SPELL_AURA_MOD_STAT_BONUS_PCT
&AuraEffect::HandleNULL, //468
&AuraEffect::HandleNULL, //469
&AuraEffect::HandleNULL, //470
@@ -3982,6 +3982,34 @@ void AuraEffect::HandleAuraModExpertise(AuraApplication const* aurApp, uint8 mod
target->ToPlayer()->UpdateExpertise(OFF_ATTACK);
}
+void AuraEffect::HandleModStatBonusPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
+ return;
+
+ Unit* target = aurApp->GetTarget();
+
+ if (GetMiscValue() < -1 || GetMiscValue() > 4)
+ {
+ TC_LOG_ERROR("spells", "WARNING: Misc Value for SPELL_AURA_MOD_STAT_BONUS_PCT not valid");
+ return;
+ }
+
+ // only players have base stats
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
+ {
+ if (GetMiscValue() == i || GetMiscValue() == -1)
+ {
+ target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply);
+ if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ target->ApplyStatPercentBuffMod(Stats(i), float(m_amount), apply);
+ }
+ }
+}
+
/********************************/
/*** HEAL & ENERGIZE ***/
/********************************/
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index e8431e202ba..b2519b4b78a 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -234,6 +234,7 @@ class AuraEffect
void HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModResistenceOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModExpertise(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleModStatBonusPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// heal and energize
void HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModPowerRegenPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index fb40de60048..6f2f761868e 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -857,12 +857,14 @@ void Spell::SelectSpellTargets()
// Do not check for selfcast
if (!ihit->scaleAura && ihit->targetGUID != m_caster->GetGUID())
{
- m_UniqueTargetInfo.erase(ihit++);
- continue;
+ ihit = m_UniqueTargetInfo.erase(ihit);
+ continue;
}
}
+
++ihit;
}
+
if (checkLvl && m_UniqueTargetInfo.empty())
{
SendCastResult(SPELL_FAILED_LOWLEVEL);
@@ -2326,6 +2328,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
return;
}
+ if (!unit)
+ return;
+
if (unit->IsAlive() != target->alive)
return;
@@ -2866,7 +2871,7 @@ bool Spell::UpdateChanneledTargetList()
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
}
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
if (ihit->missCondition == SPELL_MISS_NONE && (channelTargetEffectMask & ihit->effectMask))
{
@@ -3359,10 +3364,10 @@ void Spell::handle_immediate()
// process immediate effects (items, ground, etc.) also initialize some variables
_handle_immediate_phase();
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
- for (std::vector<GOTargetInfo>::iterator ihit= m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
+ for (std::vector<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
FinishTargetProcessing();
@@ -3402,7 +3407,7 @@ uint64 Spell::handle_delayed(uint64 t_offset)
bool single_missile = (m_targets.HasDst());
// now recheck units targeting correctness (need before any effects apply to prevent adding immunity at first effect not allow apply second spell effect and similar cases)
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
if (ihit->processed == false)
{
@@ -3417,7 +3422,7 @@ uint64 Spell::handle_delayed(uint64 t_offset)
}
// now recheck gameobject targeting correctness
- for (std::vector<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
+ for (std::vector<GOTargetInfo>::iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
{
if (ighit->processed == false)
{
@@ -3475,7 +3480,7 @@ void Spell::_handle_immediate_phase()
}
// process items
- for (std::vector<ItemTargetInfo>::iterator ihit= m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
+ for (std::vector<ItemTargetInfo>::iterator ihit = m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
if (!m_originalCaster)
@@ -5815,7 +5820,7 @@ bool Spell::CanAutoCast(Unit* target)
{
SelectSpellTargets();
//check if among target units, our WANTED target is as well (->only self cast spells return false)
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if (ihit->targetGUID == targetguid)
return true;
}
@@ -6832,7 +6837,7 @@ void Spell::HandleLaunchPhase()
if (effect && (m_applyMultiplierMask & (1 << effect->EffectIndex)))
multiplier[effect->EffectIndex] = effect->CalcDamageMultiplier(m_originalCaster, this);
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
TargetInfo& target = *ihit;
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 3ca8550b3ce..ec716a0e03d 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -338,6 +338,7 @@ class Spell
void EffectApplyGlyph(SpellEffIndex effIndex);
void EffectEnchantHeldItem(SpellEffIndex effIndex);
void EffectSummonObject(SpellEffIndex effIndex);
+ void EffectChangeRaidMarker(SpellEffIndex effIndex);
void EffectResurrect(SpellEffIndex effIndex);
void EffectParry(SpellEffIndex effIndex);
void EffectBlock(SpellEffIndex effIndex);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 9e4f0608a38..c640134f6e4 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -180,7 +180,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
&Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
&Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
- &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
+ &Spell::EffectChangeRaidMarker, //106 SPELL_EFFECT_CHANGE_RAID_MARKER
&Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
&Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
&Spell::EffectResurrectPet, //109 SPELL_EFFECT_RESURRECT_PET
@@ -241,7 +241,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectRemoveAura, //164 SPELL_EFFECT_REMOVE_AURA
&Spell::EffectDamageFromMaxHealthPCT, //165 SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT
&Spell::EffectGiveCurrency, //166 SPELL_EFFECT_GIVE_CURRENCY
- &Spell::EffectNULL, //167 SPELL_EFFECT_167
+ &Spell::EffectNULL, //167 SPELL_EFFECT_UPDATE_PLAYER_PHASE
&Spell::EffectNULL, //168 SPELL_EFFECT_ALLOW_CONTROL_PET
&Spell::EffectDestroyItem, //169 SPELL_EFFECT_DESTROY_ITEM
&Spell::EffectNULL, //170 SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES
@@ -421,7 +421,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE))
{
uint32 count = 0;
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if (ihit->effectMask & (1<<effIndex))
++count;
@@ -4648,6 +4648,25 @@ void Spell::EffectPullTowards(SpellEffIndex /*effIndex*/)
unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ);
}
+void Spell::EffectChangeRaidMarker(SpellEffIndex /*effIndex*/)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
+ return;
+
+ Player* player = m_caster->ToPlayer();
+ if (!player || !m_targets.HasDst())
+ return;
+
+ Group* group = player->GetGroup();
+ if (!group || (group->isRaidGroup() && !group->IsLeader(player->GetGUID()) && !group->IsAssistant(player->GetGUID())))
+ return;
+
+ float x, y, z;
+ destTarget->GetPosition(x, y, z);
+
+ group->AddRaidMarker(damage, player->GetMapId(), x, y, z);
+}
+
void Spell::EffectDispelMechanic(SpellEffIndex /*effIndex*/)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 4db7091f971..7b012d8a0f6 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -806,7 +806,7 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 103 SPELL_EFFECT_REPUTATION
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
- {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 106 SPELL_EFFECT_CHANGE_RAID_MARKER
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 108 SPELL_EFFECT_DISPEL_MECHANIC
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 109 SPELL_EFFECT_SUMMON_DEAD_PET
@@ -1822,6 +1822,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
if (!player->CanFlyInZone(map_id, zone_id))
return SPELL_FAILED_INCORRECT_AREA;
}
+ break;
}
case SPELL_AURA_MOUNTED:
{
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 2f74218ba7b..70b820aed96 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3030,6 +3030,10 @@ void SpellMgr::LoadSpellInfoCorrections()
switch (spellInfo->Id)
{
+ case 63026: // Force Cast (HACK: Target shouldn't be changed)
+ case 63171: // Force Cast (HACK: Target shouldn't be changed; summon position should be untied from spell destination)
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
+ break;
case 42436: // Drink! (Brewfest)
const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY);
break;
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 33773a57631..4fd8b5d8bf6 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -64,9 +64,9 @@ _SpellScript::EffectHook::EffectHook(uint8 _effIndex)
effIndex = _effIndex;
}
-uint8 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellEntry)
+uint32 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellEntry)
{
- uint8 mask = 0;
+ uint32 mask = 0;
if ((effIndex == EFFECT_ALL) || (effIndex == EFFECT_FIRST_FOUND))
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -74,13 +74,13 @@ uint8 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellEnt
if ((effIndex == EFFECT_FIRST_FOUND) && mask)
return mask;
if (CheckEffect(spellEntry, i))
- mask |= (uint8)1<<i;
+ mask |= 1 << i;
}
}
else
{
if (CheckEffect(spellEntry, effIndex))
- mask |= (uint8)1<<effIndex;
+ mask |= 1 << effIndex;
}
return mask;
}
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index fb9e1ed3937..f9a2f1ec847 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -74,7 +74,7 @@ class _SpellScript
EffectHook(uint8 _effIndex);
virtual ~EffectHook() { }
- uint8 GetAffectedEffectsMask(SpellInfo const* spellInfo);
+ uint32 GetAffectedEffectsMask(SpellInfo const* spellInfo);
bool IsEffectAffected(SpellInfo const* spellInfo, uint8 effIndex);
virtual bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) = 0;
std::string EffIndexToString();
diff --git a/src/server/game/Texts/ChatTextBuilder.h b/src/server/game/Texts/ChatTextBuilder.h
index dcee6f08ac3..167680f1cd2 100644
--- a/src/server/game/Texts/ChatTextBuilder.h
+++ b/src/server/game/Texts/ChatTextBuilder.h
@@ -34,7 +34,7 @@ namespace Trinity
{
BroadcastTextEntry const* bct = sBroadcastTextStore.LookupEntry(_textId);
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgType, bct ? Language(bct->Language) : LANG_UNIVERSAL, _source, _target, bct ? DB2Manager::GetBroadcastTextValue(bct, locale, _source->getGender()) : "", _achievementId, "", locale);
+ packet.Initialize(_msgType, bct ? Language(bct->Language) : LANG_UNIVERSAL, _source, _target, bct ? DB2Manager::GetBroadcastTextValue(bct, locale, _source->getGender()) : "", _achievementId, "", locale);
packet.Write();
data = packet.Move();
}
@@ -56,7 +56,7 @@ namespace Trinity
void operator()(WorldPacket& data, LocaleConstant locale)
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgType, _language, _source, _target, _text, 0, "", locale);
+ packet.Initialize(_msgType, _language, _source, _target, _text, 0, "", locale);
packet.Write();
data = packet.Move();
}
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index 281504b9aaf..c1ea235a3e2 100644
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -37,7 +37,7 @@ class CreatureTextBuilder
{
std::string const& text = sCreatureTextMgr->GetLocalizedChatString(_source->GetEntry(), _gender, _textGroup, _textId, locale);
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgType, Language(_language), _source, _target, text, 0, "", locale);
+ packet.Initialize(_msgType, Language(_language), _source, _target, text, 0, "", locale);
packet.Write();
data = packet.Move();
}
@@ -62,7 +62,7 @@ class PlayerTextBuilder
{
std::string const& text = sCreatureTextMgr->GetLocalizedChatString(_source->GetEntry(), _gender, _textGroup, _textId, locale);
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgType, Language(_language), _talker, _target, text, 0, "", locale);
+ packet.Initialize(_msgType, Language(_language), _talker, _target, text, 0, "", locale);
packet.Write();
data = packet.Move();
}
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 9b8c63000fc..d68da8fbc63 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2252,6 +2252,9 @@ void World::Update(uint32 diff)
sLFGMgr->Update(diff);
RecordTimeDiff("UpdateLFGMgr");
+ sGroupMgr->Update(diff);
+ RecordTimeDiff("GroupMgr");
+
// execute callbacks from sql queries that were queued recently
ProcessQueryCallbacks();
RecordTimeDiff("ProcessQueryCallbacks");
@@ -2381,7 +2384,7 @@ namespace Trinity
while (char* line = ChatHandler::LineFromMessage(text))
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
packet.Write();
dataList.emplace_back(new WorldPacket(packet.Move()));
}
@@ -2447,7 +2450,7 @@ void World::SendGlobalText(const char* text, WorldSession* self)
while (char* line = ChatHandler::LineFromMessage(pos))
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
SendGlobalMessage(packet.Write(), self);
}
@@ -2481,7 +2484,7 @@ bool World::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession
void World::SendZoneText(uint32 zone, const char* text, WorldSession* self, uint32 team)
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text);
SendZoneMessage(zone, packet.Write(), self, team);
}
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index ecd98595723..7f1a364fd57 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -485,7 +485,7 @@ public:
char const* msg = "testtest";
uint8 type = atoi(args);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), LANG_UNIVERSAL, handler->GetSession()->GetPlayer(), handler->GetSession()->GetPlayer(), msg, 0, "chan");
+ packet.Initialize(ChatMsg(type), LANG_UNIVERSAL, handler->GetSession()->GetPlayer(), handler->GetSession()->GetPlayer(), msg, 0, "chan");
handler->GetSession()->SendPacket(packet.Write());
return true;
}
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 61df922452f..b9765223add 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -1465,7 +1465,7 @@ public:
* Player %s %s (guid: %u) - I. LANG_PINFO_PLAYER
* ** GM Mode active, Phase: -1 - II. LANG_PINFO_GM_ACTIVE (if GM)
* ** Banned: (Type, Reason, Time, By) - III. LANG_PINFO_BANNED (if banned)
- * ** Muted: (Time, Reason, By) - IV. LANG_PINFO_MUTED (if muted)
+ * ** Muted: (Reason, Time, By) - IV. LANG_PINFO_MUTED (if muted)
* * Account: %s (id: %u), GM Level: %u - V. LANG_PINFO_ACC_ACCOUNT
* * Last Login: %u (Failed Logins: %u) - VI. LANG_PINFO_ACC_LASTLOGIN
* * Uses OS: %s - Latency: %u ms - VII. LANG_PINFO_ACC_OS
@@ -1716,7 +1716,7 @@ public:
// Output IV. LANG_PINFO_MUTED if mute is applied
if (muteTime > 0)
- handler->PSendSysMessage(LANG_PINFO_MUTED, secsToTimeString(muteTime - time(NULL), true).c_str(), muteReason.c_str(), muteBy.c_str());
+ handler->PSendSysMessage(LANG_PINFO_MUTED, muteReason.c_str(), secsToTimeString(muteTime - time(nullptr), true).c_str(), muteBy.c_str());
// Output V. LANG_PINFO_ACC_ACCOUNT
handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, userName.c_str(), accId, security);
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index 81cad2db188..2c91a9e6e3e 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -374,28 +374,13 @@ public:
ObjectGuid::LowType lowGuid = strtoull(guidStr, nullptr, 10);
- Creature* creature = NULL;
-
- /* FIXME: impossible without entry
- if (lowguid)
- creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT));
- */
-
// attempt check creature existence by DB data
- if (!creature)
- {
- CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid);
- if (!data)
- {
- handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid);
- handler->SetSentErrorMessage(true);
- return false;
- }
- }
- else
+ CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid);
+ if (!data)
{
- // obtain real GUID for DB operations
- lowGuid = creature->GetSpawnId();
+ handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid);
+ handler->SetSentErrorMessage(true);
+ return false;
}
int wait = waitStr ? atoi(waitStr) : 0;
@@ -411,18 +396,6 @@ public:
WorldDatabase.Execute(stmt);
- if (creature && creature->GetWaypointPath())
- {
- creature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
- creature->GetMotionMaster()->Initialize();
- if (creature->IsAlive()) // dead creature will reset movement generator at respawn
- {
- creature->setDeathState(JUST_DIED);
- creature->Respawn(true);
- }
- creature->SaveToDB();
- }
-
handler->SendSysMessage(LANG_WAYPOINT_ADDED);
return true;
@@ -836,34 +809,22 @@ public:
lowguid = strtoull(cId, nullptr, 10);
- /* FIXME: impossible without entry
- if (lowguid)
- creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT));
- */
-
// Attempting creature load from DB data
- if (!creature)
+ CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
+ if (!data)
{
- CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
- if (!data)
- {
- handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
- handler->SetSentErrorMessage(true);
- return false;
- }
+ handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
- uint32 map_id = data->mapid;
+ uint32 map_id = data->mapid;
- if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
- {
- handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
- handler->SetSentErrorMessage(true);
- return false;
- }
- }
- else
+ if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
{
- lowguid = creature->GetSpawnId();
+ handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
+ handler->SetSentErrorMessage(true);
+ return false;
}
}
else
diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
index 1d7e1594d05..ca944f7037b 100644
--- a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
+++ b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
@@ -102,7 +102,7 @@ public:
}
}
- virtual void Update(uint32 /*diff*/) // correct order goes form 1-6
+ virtual void Update(uint32 /*diff*/) override // correct order goes form 1-6
{
switch (State)
{
diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
index ec2f41cc625..15280bc7848 100644
--- a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
+++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
@@ -197,7 +197,7 @@ class boss_archaedas : public CreatureScript
DoMeleeAttackIfReady();
}
- void JustDied (Unit* /*killer*/)
+ void JustDied (Unit* /*killer*/) override
{
instance->SetData(DATA_ANCIENT_DOOR, DONE); // open the vault door
instance->SetData(DATA_MINIONS, SPECIAL); // deactivate his minions
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
index f027a98da9d..d261b7a623a 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -1064,7 +1064,7 @@ class npc_meteor_strike : public CreatureScript
}
}
- void IsSummonedBy(Unit* summoner) override
+ void IsSummonedBy(Unit* /*summoner*/) override
{
// Let Halion Controller count as summoner.
if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
@@ -1092,9 +1092,6 @@ class npc_meteor_strike : public CreatureScript
Position pos = me->GetNearPosition(5.0f, 0.0f);
if (Creature* flame = me->SummonCreature(NPC_METEOR_STRIKE_FLAME, pos, TEMPSUMMON_TIMED_DESPAWN, 25000))
{
- if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
- controller->AI()->JustSummoned(flame);
-
flame->SetOrientation(me->GetOrientation());
flame->AI()->SetGUID(GetGUID());
@@ -1128,7 +1125,7 @@ class npc_meteor_strike_flame : public CreatureScript
SetCombatMovement(false);
}
- void SetGUID(ObjectGuid guid, int32 id /* = 0 */)
+ void SetGUID(ObjectGuid guid, int32 /*id = 0 */)
{
_rootOwnerGuid = guid;
}
@@ -1149,9 +1146,6 @@ class npc_meteor_strike_flame : public CreatureScript
if (Creature* flame = me->SummonCreature(NPC_METEOR_STRIKE_FLAME, pos, TEMPSUMMON_TIMED_DESPAWN, 25000))
{
- if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
- controller->AI()->JustSummoned(flame);
-
flame->AI()->SetGUID(_rootOwnerGuid);
meteorStrike->AI()->SetData(DATA_SPAWNED_FLAMES, 1);
}
@@ -1164,7 +1158,7 @@ class npc_meteor_strike_flame : public CreatureScript
controller->AI()->JustSummoned(me);
}
- void UpdateAI(uint32 diff) override { }
+ void UpdateAI(uint32 /*diff*/) override { }
void EnterEvadeMode() override { }
private:
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 0fc4f1a4a8b..7f88a56f22c 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
@@ -196,7 +196,7 @@ class instance_halls_of_reflection : public InstanceMapScript
}
}
- uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override
+ uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override
{
if (!_teamInInstance)
{
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index faa448ef539..51756834e77 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -1059,8 +1059,8 @@ class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader
{
if (GetHitUnit()->HasAura(SPELL_VOLATILE_OOZE_ADHESIVE))
{
- GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true);
GetHitUnit()->RemoveAurasDueToSpell(SPELL_VOLATILE_OOZE_ADHESIVE, GetCaster()->GetGUID(), 0, AURA_REMOVE_BY_ENEMY_SPELL);
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true);
}
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index 7bd1dee15ca..423c1049452 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -348,7 +348,7 @@ class boss_sindragosa : public CreatureScript
events.ScheduleEvent(EVENT_AIR_MOVEMENT, 1);
break;
case POINT_AIR_PHASE:
- me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6), NULL);
+ me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6), NULL, TRIGGERED_FULL_MASK);
me->SetFacingTo(float(M_PI));
events.ScheduleEvent(EVENT_AIR_MOVEMENT_FAR, 1);
events.ScheduleEvent(EVENT_FROST_BOMB, 9000);
@@ -490,7 +490,7 @@ class boss_sindragosa : public CreatureScript
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, FrostBeaconSelector(me)))
{
Talk(EMOTE_WARN_FROZEN_ORB, target);
- DoCast(target, SPELL_ICE_TOMB_DUMMY, true);
+ me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, 1, nullptr, TRIGGERED_FULL_MASK);
}
events.ScheduleEvent(EVENT_ICE_TOMB, urand(16000, 23000));
break;
@@ -1630,7 +1630,7 @@ void AddSC_boss_sindragosa()
new spell_rimefang_icy_blast();
new spell_frostwarden_handler_order_whelp();
new spell_frostwarden_handler_focus_fire();
- new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY);
+ new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY, TRIGGERED_IGNORE_SET_FACING);
new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb_dummy", SPELL_FROST_BEACON);
new at_sindragosa_lair();
new achievement_all_you_can_eat();
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index 8bf8e5ee6fb..091190b6b4e 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -524,14 +524,16 @@ enum AreaIds
class spell_trigger_spell_from_caster : public SpellScriptLoader
{
public:
- spell_trigger_spell_from_caster(char const* scriptName, uint32 triggerId) : SpellScriptLoader(scriptName), _triggerId(triggerId) { }
+ spell_trigger_spell_from_caster(char const* scriptName, uint32 triggerId, TriggerCastFlags triggerFlags = TRIGGERED_FULL_MASK)
+ : SpellScriptLoader(scriptName), _triggerId(triggerId), _triggerFlags(triggerFlags) { }
class spell_trigger_spell_from_caster_SpellScript : public SpellScript
{
PrepareSpellScript(spell_trigger_spell_from_caster_SpellScript);
public:
- spell_trigger_spell_from_caster_SpellScript(uint32 triggerId) : SpellScript(), _triggerId(triggerId) { }
+ spell_trigger_spell_from_caster_SpellScript(uint32 triggerId, TriggerCastFlags triggerFlags)
+ : SpellScript(), _triggerId(triggerId), _triggerFlags(triggerFlags) { }
bool Validate(SpellInfo const* /*spell*/) override
{
@@ -542,7 +544,7 @@ class spell_trigger_spell_from_caster : public SpellScriptLoader
void HandleTrigger()
{
- GetCaster()->CastSpell(GetHitUnit(), _triggerId, true);
+ GetCaster()->CastSpell(GetHitUnit(), _triggerId, _triggerFlags);
}
void Register() override
@@ -551,15 +553,17 @@ class spell_trigger_spell_from_caster : public SpellScriptLoader
}
uint32 _triggerId;
+ TriggerCastFlags _triggerFlags;
};
SpellScript* GetSpellScript() const override
{
- return new spell_trigger_spell_from_caster_SpellScript(_triggerId);
+ return new spell_trigger_spell_from_caster_SpellScript(_triggerId, _triggerFlags);
}
private:
uint32 _triggerId;
+ TriggerCastFlags _triggerFlags;
};
template<class AI>
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index aee14edd0c3..d38d630f775 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -317,7 +317,7 @@ class instance_icecrown_citadel : public InstanceMapScript
}
// Weekly quest spawn prevention
- uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) override
+ uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
{
uint32 entry = data->id;
switch (entry)
@@ -372,7 +372,7 @@ class instance_icecrown_citadel : public InstanceMapScript
return entry;
}
- uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override
+ uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override
{
switch (entry)
{
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
index 134783ccf07..6a1ff6d4eea 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
@@ -903,17 +903,15 @@ class boss_yogg_saron : public CreatureScript
DoCast(me, SPELL_KNOCK_AWAY);
me->ResetLootMode();
- switch (_instance->GetData(DATA_KEEPERS_COUNT))
- {
- case 0:
- me->AddLootMode(LOOT_MODE_HARD_MODE_4);
- case 1:
- me->AddLootMode(LOOT_MODE_HARD_MODE_3);
- case 2:
- me->AddLootMode(LOOT_MODE_HARD_MODE_2);
- case 3:
- me->AddLootMode(LOOT_MODE_HARD_MODE_1);
- }
+ uint32 keepersCount = _instance->GetData(DATA_KEEPERS_COUNT);
+ if (keepersCount == 0)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_4);
+ if (keepersCount <= 1)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_3);
+ if (keepersCount <= 2)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_2);
+ if (keepersCount <= 3)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_1);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp
index 7f29a6621bd..2e426fd77cf 100644
--- a/src/server/scripts/Northrend/zone_icecrown.cpp
+++ b/src/server/scripts/Northrend/zone_icecrown.cpp
@@ -25,53 +25,6 @@
#include "CombatAI.h"
/*######
-## npc_squire_david
-######*/
-
-enum SquireDavid
-{
- QUEST_THE_ASPIRANT_S_CHALLENGE_H = 13680,
- QUEST_THE_ASPIRANT_S_CHALLENGE_A = 13679,
-
- NPC_ARGENT_VALIANT = 33448,
-
- GOSSIP_TEXTID_SQUIRE = 14407
-};
-
-#define GOSSIP_SQUIRE_ITEM_1 "I am ready to fight!"
-#define GOSSIP_SQUIRE_ITEM_2 "How do the Argent Crusader raiders fight?"
-
-class npc_squire_david : public CreatureScript
-{
-public:
- npc_squire_david() : CreatureScript("npc_squire_david") { }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- if (player->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_H) == QUEST_STATUS_INCOMPLETE ||
- player->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_A) == QUEST_STATUS_INCOMPLETE)//We need more info about it.
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
- }
-
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SQUIRE, creature->GetGUID());
- return true;
- }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF+1)
- {
- player->CLOSE_GOSSIP_MENU();
- creature->SummonCreature(NPC_ARGENT_VALIANT, 8575.451f, 952.472f, 547.554f, 0.38f);
- }
- return true;
- }
-};
-
-/*######
## npc_argent_valiant
######*/
@@ -837,7 +790,6 @@ class npc_frostbrood_skytalon : public CreatureScript
void AddSC_icecrown()
{
- new npc_squire_david;
new npc_argent_valiant;
new npc_guardian_pavilion;
new npc_tournament_training_dummy;
diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h
index c2dd71ce7cf..77a7c338118 100644
--- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h
+++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h
@@ -261,13 +261,13 @@ class OPvPCapturePointNA : public OPvPCapturePoint
public:
OPvPCapturePointNA(OutdoorPvP* pvp);
- bool Update(uint32 diff);
+ bool Update(uint32 diff) override;
- void ChangeState();
+ void ChangeState() override;
- void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet);
+ void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
- bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go);
+ bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go) override;
int32 HandleOpenGo(Player* player, GameObject* go) override;
diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt
index 24658dbc21f..42621b76941 100644
--- a/src/server/scripts/Outland/CMakeLists.txt
+++ b/src/server/scripts/Outland/CMakeLists.txt
@@ -27,6 +27,7 @@ set(scripts_STAT_SRCS
Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
+ Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
index fb44a403d86..dfc5f5992a6 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
@@ -108,6 +108,7 @@ class boss_grand_warlock_nethekurse : public CreatureScript
void Reset() override
{
+ _Reset();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
Initialize();
@@ -115,9 +116,8 @@ class boss_grand_warlock_nethekurse : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
+ _JustDied();
Talk(SAY_DIE);
-
- instance->SetBossState(DATA_NETHEKURSE, DONE);
}
void SetData(uint32 data, uint32 value) override
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
index 7d00cd97126..a950882eddd 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
@@ -160,6 +160,7 @@ class boss_warbringer_omrogg : public CreatureScript
void Reset() override
{
+ _Reset();
if (Unit* LeftHead = ObjectAccessor::GetUnit(*me, LeftHeadGUID))
{
LeftHead->setDeathState(JUST_DIED);
@@ -257,14 +258,14 @@ class boss_warbringer_omrogg : public CreatureScript
Creature* LeftHead = ObjectAccessor::GetCreature(*me, LeftHeadGUID);
Creature* RightHead = ObjectAccessor::GetCreature(*me, RightHeadGUID);
+ _JustDied();
+
if (!LeftHead || !RightHead)
return;
LeftHead->AI()->Talk(YELL_DIE_L);
RightHead->AI()->SetData(SETDATA_DATA, SETDATA_YELL);
-
- instance->SetBossState(DATA_OMROGG, DONE);
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
index b44ae46c78c..7f2e08b39ca 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
@@ -35,7 +35,10 @@ enum Says
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
- SAY_DEATH = 2
+ SAY_DEATH = 2,
+
+ SAY_CALL_EXECUTIONER_A = 3,
+ SAY_CALL_EXECUTIONER_H = 4
};
enum Spells
@@ -84,10 +87,28 @@ class boss_warchief_kargath_bladefist : public CreatureScript
resetcheck_timer = 5000;
}
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_EXECUTIONER_TAUNT)
+ {
+ switch (instance->GetData(DATA_TEAM_IN_INSTANCE))
+ {
+ case ALLIANCE:
+ Talk(SAY_CALL_EXECUTIONER_A);
+ break;
+ case HORDE:
+ Talk(SAY_CALL_EXECUTIONER_H);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
void Reset() override
{
removeAdds();
-
+ _Reset();
me->SetSpeed(MOVE_RUN, 2);
me->SetWalk(false);
@@ -96,10 +117,9 @@ class boss_warchief_kargath_bladefist : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
+ _JustDied();
Talk(SAY_DEATH);
removeAdds();
-
- instance->SetBossState(DATA_KARGATH, DONE);
}
void EnterCombat(Unit* /*who*/) override
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 c6b08bdada1..a781861d47f 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
@@ -26,6 +26,18 @@ EndScriptData */
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "shattered_halls.h"
+#include "Player.h"
+#include "SpellAuras.h"
+#include "CreatureAI.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+
+DoorData const doorData[] =
+{
+ { GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ { GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }
+};
class instance_shattered_halls : public InstanceMapScript
{
@@ -43,6 +55,41 @@ class instance_shattered_halls : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
+ LoadDoorData(doorData);
+ executionTimer = 0;
+ executed = 0;
+ _team = 0;
+ }
+
+ void OnPlayerEnter(Player* player) override
+ {
+ Aura* ex = nullptr;
+
+ if (!_team)
+ _team = player->GetTeam();
+
+ player->CastSpell(player, SPELL_REMOVE_KARGATH_EXECUTIONER, true);
+
+ if (!executionTimer || executionerGUID.IsEmpty())
+ return;
+
+ switch (executed)
+ {
+ case 0:
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_1, player);
+ break;
+ case 1:
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_2, player);
+ break;
+ case 2:
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_3, player);
+ break;
+ default:
+ break;
+ }
+
+ if (ex)
+ ex->SetDuration(executionTimer);
}
void OnGameObjectCreate(GameObject* go) override
@@ -50,21 +97,65 @@ class instance_shattered_halls : public InstanceMapScript
switch (go->GetEntry())
{
case GO_GRAND_WARLOCK_CHAMBER_DOOR_1:
- nethekurseDoor1GUID = go->GetGUID();
+ case GO_GRAND_WARLOCK_CHAMBER_DOOR_2:
+ AddDoor(go, true);
+ default:
break;
+ }
+ }
+
+ void OnGameObjectRemove(GameObject* go) override
+ {
+ switch (go->GetEntry())
+ {
+ case GO_GRAND_WARLOCK_CHAMBER_DOOR_1:
case GO_GRAND_WARLOCK_CHAMBER_DOOR_2:
- nethekurseDoor2GUID = go->GetGUID();
+ AddDoor(go, false);
+ default:
break;
}
}
void OnCreatureCreate(Creature* creature) override
{
+ if (!_team)
+ {
+ Map::PlayerList const &players = instance->GetPlayers();
+ if (!players.isEmpty())
+ if (Player* player = players.begin()->GetSource())
+ _team = player->GetTeam();
+ }
+
switch (creature->GetEntry())
{
case NPC_GRAND_WARLOCK_NETHEKURSE:
nethekurseGUID = creature->GetGUID();
break;
+ case NPC_KARGATH_BLADEFIST:
+ kargathGUID = creature->GetGUID();
+ break;
+ case NPC_RANDY_WHIZZLESPROCKET:
+ if (_team == HORDE)
+ creature->UpdateEntry(NPC_DRISELLA);
+ break;
+ case NPC_SHATTERED_EXECUTIONER:
+ executionTimer = 55 * MINUTE * IN_MILLISECONDS;
+ DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_1);
+ executionerGUID = creature->GetGUID();
+ SaveToDB();
+ break;
+ case NPC_CAPTAIN_ALINA:
+ case NPC_CAPTAIN_BONESHATTER:
+ victimsGUID[0] = creature->GetGUID();
+ break;
+ case NPC_ALLIANCE_VICTIM_1:
+ case NPC_HORDE_VICTIM_1:
+ victimsGUID[1] = creature->GetGUID();
+ break;
+ case NPC_ALLIANCE_VICTIM_2:
+ case NPC_HORDE_VICTIM_2:
+ victimsGUID[2] = creature->GetGUID();
+ break;
}
}
@@ -75,18 +166,18 @@ class instance_shattered_halls : public InstanceMapScript
switch (type)
{
- case DATA_NETHEKURSE:
- if (state == IN_PROGRESS)
- {
- HandleGameObject(nethekurseDoor1GUID, false);
- HandleGameObject(nethekurseDoor2GUID, false);
- }
- else
+ case DATA_SHATTERED_EXECUTIONER:
+ if (state == DONE)
{
- HandleGameObject(nethekurseDoor1GUID, true);
- HandleGameObject(nethekurseDoor2GUID, true);
+ DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
+ executionTimer = 0;
+ SaveToDB();
}
break;
+ case DATA_KARGATH:
+ if (Creature* executioner = instance->GetCreature(executionerGUID))
+ executioner->AI()->Reset(); // trigger removal of IMMUNE_TO_PC flag
+ break;
case DATA_OMROGG:
break;
}
@@ -99,24 +190,120 @@ class instance_shattered_halls : public InstanceMapScript
{
case NPC_GRAND_WARLOCK_NETHEKURSE:
return nethekurseGUID;
- break;
- case GO_GRAND_WARLOCK_CHAMBER_DOOR_1:
- return nethekurseDoor1GUID;
- break;
- case GO_GRAND_WARLOCK_CHAMBER_DOOR_2:
- return nethekurseDoor2GUID;
- break;
+ case NPC_KARGATH_BLADEFIST:
+ return kargathGUID;
+ case NPC_SHATTERED_EXECUTIONER:
+ return executionerGUID;
+ case DATA_FIRST_PRISONER:
+ case DATA_SECOND_PRISONER:
+ case DATA_THIRD_PRISONER:
+ return victimsGUID[data - DATA_FIRST_PRISONER];
+ default:
+ return ObjectGuid::Empty;
}
- return ObjectGuid::Empty;
}
- protected:
+ void WriteSaveDataMore(std::ostringstream& data) override
+ {
+ if (!instance->IsHeroic())
+ return;
+
+ data << uint32(executed) << ' '
+ << executionTimer << ' ';
+ }
+
+ void ReadSaveDataMore(std::istringstream& data) override
+ {
+ if (!instance->IsHeroic())
+ return;
+
+ uint32 readbuff;
+ data >> readbuff;
+ executed = uint8(readbuff);
+ data >> readbuff;
+
+ if (executed > VictimCount)
+ {
+ executed = VictimCount;
+ executionTimer = 0;
+ return;
+ }
+
+ if (!readbuff)
+ return;
+
+ Creature* executioner = nullptr;
+
+ instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY());
+ if (Creature* kargath = instance->GetCreature(kargathGUID))
+ if (executionerGUID.IsEmpty())
+ executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner);
+
+ if (executioner)
+ for (uint8 i = executed; i < VictimCount; ++i)
+ executioner->SummonCreature(executionerVictims[i](GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos());
+
+ executionTimer = readbuff;
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_PRISONERS_EXECUTED:
+ return executed;
+ case DATA_TEAM_IN_INSTANCE:
+ return _team;
+ default:
+ return 0;
+ }
+ }
+
+ void Update(uint32 diff) override
+ {
+ if (!executionTimer)
+ return;
+
+ if (executionTimer <= diff)
+ {
+ DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
+ switch (++executed)
+ {
+ case 1:
+ DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_2);
+ executionTimer = 10 * MINUTE * IN_MILLISECONDS;
+ break;
+ case 2:
+ DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_3);
+ executionTimer = 15 * MINUTE * IN_MILLISECONDS;
+ break;
+ default:
+ executionTimer = 0;
+ break;
+ }
+
+ if (Creature* executioner = instance->GetCreature(executionerGUID))
+ executioner->AI()->SetData(DATA_PRISONERS_EXECUTED, executed);
+
+ SaveToDB();
+ }
+ else
+ executionTimer -= diff;
+ }
+
+ private:
ObjectGuid nethekurseGUID;
- ObjectGuid nethekurseDoor1GUID;
- ObjectGuid nethekurseDoor2GUID;
+ ObjectGuid kargathGUID;
+ ObjectGuid executionerGUID;
+ ObjectGuid victimsGUID[3];
+
+ uint8 executed;
+ uint32 executionTimer;
+ uint32 _team;
};
};
+
void AddSC_instance_shattered_halls()
{
new instance_shattered_halls();
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
new file mode 100644
index 00000000000..d31fa4c4f09
--- /dev/null
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "InstanceScript.h"
+#include "Player.h"
+#include "SpellAuras.h"
+#include "shattered_halls.h"
+
+class at_nethekurse_exit : public AreaTriggerScript
+{
+ public:
+ at_nethekurse_exit() : AreaTriggerScript("at_nethekurse_exit") { };
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const*, bool /*entered*/) override
+ {
+ if (InstanceScript* is = player->GetInstanceScript())
+ {
+ if (is->instance->IsHeroic())
+ {
+ Creature* executioner = nullptr;
+
+ is->instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY());
+ if (Creature* kargath = ObjectAccessor::GetCreature(*player, is->GetGuidData(NPC_KARGATH_BLADEFIST)))
+ {
+ if (is->GetGuidData(NPC_SHATTERED_EXECUTIONER).IsEmpty())
+ {
+ executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner);
+ kargath->AI()->DoAction(ACTION_EXECUTIONER_TAUNT);
+ }
+ }
+
+ if (executioner)
+ for (uint8 i = 0; i < VictimCount; ++i)
+ executioner->SummonCreature(executionerVictims[i](is->GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos());
+ }
+ }
+
+ return false;
+ }
+};
+
+enum Spells
+{
+ SPELL_CLEAVE = 15284
+};
+
+class boss_shattered_executioner : public CreatureScript
+{
+ public:
+ boss_shattered_executioner() : CreatureScript("boss_shattered_executioner") { }
+
+ struct boss_shattered_executionerAI : public BossAI
+ {
+ boss_shattered_executionerAI(Creature* creature) : BossAI(creature, DATA_SHATTERED_EXECUTIONER)
+ {
+ Initialize();
+ };
+
+ void Initialize()
+ {
+ cleaveTimer = 500;
+ }
+
+ void Reset() override
+ {
+ _Reset();
+
+ // _Reset() resets the loot mode, so we add them again, if any
+ uint32 prisonersExecuted = instance->GetData(DATA_PRISONERS_EXECUTED);
+ if (prisonersExecuted == 0)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_3);
+ if (prisonersExecuted <= 1)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_2);
+ if (prisonersExecuted <= 2)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_1);
+
+ if (instance->GetBossState(DATA_KARGATH) == DONE)
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ else
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+
+ Initialize();
+ }
+
+ void JustSummoned(Creature*) override { } // avoid despawn of prisoners on death/reset
+
+ void JustDied(Unit*) override
+ {
+ _JustDied();
+
+ if (instance->GetData(DATA_PRISONERS_EXECUTED) > 0)
+ return;
+
+ Map::PlayerList const &players = instance->instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ Player* pl = itr->GetSource();
+ uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
+ if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE)
+ pl->CompleteQuest(qId);
+ }
+ }
+
+ void SetData(uint32 type, uint32 data) override
+ {
+ if (type == DATA_PRISONERS_EXECUTED && data <= 3)
+ {
+ if (Creature* victim = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FIRST_PRISONER + data - 1)))
+ me->Kill(victim);
+
+ if (data == 1)
+ {
+ Map::PlayerList const &players = instance->instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ Player* pl = itr->GetSource();
+ uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
+ if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE)
+ pl->FailQuest(qId);
+ }
+ }
+
+ switch (data)
+ {
+ case 3:
+ me->RemoveLootMode(LOOT_MODE_HARD_MODE_1);
+ case 2:
+ me->RemoveLootMode(LOOT_MODE_HARD_MODE_2);
+ case 1:
+ me->RemoveLootMode(LOOT_MODE_HARD_MODE_3);
+ default:
+ break;
+ }
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (cleaveTimer <= diff)
+ {
+ DoCast(SPELL_CLEAVE);
+ cleaveTimer = urand(5000, 7000);
+ }
+ else
+ cleaveTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+ private:
+ uint32 cleaveTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_shattered_executionerAI>(creature);
+ }
+};
+
+class spell_kargath_executioner : public SpellScriptLoader
+{
+ public:
+ spell_kargath_executioner() : SpellScriptLoader("spell_kargath_executioner") { }
+
+ class spell_kargath_executioner_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_kargath_executioner_AuraScript);
+
+ bool AreaCheck(Unit* target)
+ {
+ if (target->GetMap()->GetId() != 540)
+ return false;
+
+ return true;
+ }
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void Register() override
+ {
+ DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_kargath_executioner_AuraScript::AreaCheck);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_kargath_executioner_AuraScript();
+ }
+};
+
+class spell_remove_kargath_executioner : public SpellScriptLoader
+{
+ public:
+ spell_remove_kargath_executioner() : SpellScriptLoader("spell_remove_kargath_executioner") { }
+
+ class spell_remove_kargath_executioner_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_remove_kargath_executioner_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetCaster();
+
+ target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_1);
+ target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_2);
+ target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_3);
+ }
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_remove_kargath_executioner_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_remove_kargath_executioner_SpellScript();
+ }
+};
+
+void AddSC_shattered_halls()
+{
+ new at_nethekurse_exit();
+ new boss_shattered_executioner();
+ new spell_kargath_executioner();
+ new spell_remove_kargath_executioner();
+}
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
index 90cbbe2a438..894cc9c40a6 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
@@ -21,18 +21,45 @@
#define DataHeader "SH"
-uint32 const EncounterCount = 3;
+uint32 const EncounterCount = 4;
+uint32 const VictimCount = 3;
enum DataTypes
{
- DATA_NETHEKURSE = 1,
- DATA_OMROGG = 2,
- DATA_KARGATH = 3
+ DATA_NETHEKURSE = 0,
+ DATA_OMROGG = 1,
+ DATA_KARGATH = 2,
+
+ DATA_SHATTERED_EXECUTIONER = 3,
+ DATA_PRISONERS_EXECUTED = 4,
+
+ DATA_TEAM_IN_INSTANCE = 5,
+
+ DATA_FIRST_PRISONER,
+ DATA_SECOND_PRISONER,
+ DATA_THIRD_PRISONER
};
enum CreatureIds
{
- NPC_GRAND_WARLOCK_NETHEKURSE = 16807
+ NPC_GRAND_WARLOCK_NETHEKURSE = 16807,
+ NPC_KARGATH_BLADEFIST = 16808,
+
+ NPC_SHATTERED_EXECUTIONER = 17301,
+
+ // Alliance Ids
+ NPC_RANDY_WHIZZLESPROCKET = 17288,
+
+ NPC_CAPTAIN_ALINA = 17290,
+ NPC_ALLIANCE_VICTIM_1 = 17289,
+ NPC_ALLIANCE_VICTIM_2 = 17292,
+
+ // Horde Ids
+ NPC_DRISELLA = 17294,
+
+ NPC_CAPTAIN_BONESHATTER = 17296,
+ NPC_HORDE_VICTIM_1 = 17295,
+ NPC_HORDE_VICTIM_2 = 17297
};
enum GameobjectIds
@@ -41,4 +68,47 @@ enum GameobjectIds
GO_GRAND_WARLOCK_CHAMBER_DOOR_2 = 182540
};
+enum QuestIds
+{
+ QUEST_IMPRISONED_A = 9524,
+ QUEST_IMPRISONED_H = 9525
+};
+
+enum InstanceSpells
+{
+ SPELL_KARGATH_EXECUTIONER_1 = 39288,
+ SPELL_KARGATH_EXECUTIONER_2 = 39289,
+ SPELL_KARGATH_EXECUTIONER_3 = 39290,
+
+ SPELL_REMOVE_KARGATH_EXECUTIONER = 39291
+};
+
+enum Actions
+{
+ ACTION_EXECUTIONER_TAUNT = 1
+};
+
+const Position Executioner = { 152.8524f, -83.63912f, 2.021005f, 0.06981317f };
+
+struct FactionSpawnerHelper
+{
+ FactionSpawnerHelper(uint32 allianceEntry, uint32 hordeEntry, const Position& pos) : _allianceNPC(allianceEntry), _hordeNPC(hordeEntry), _spawnPos(pos) { }
+
+ inline uint32 operator()(uint32 teamID) const { return teamID == ALLIANCE ? _allianceNPC : _hordeNPC; }
+ inline Position const& GetPos() const { return _spawnPos; }
+
+private:
+ const uint32 _allianceNPC;
+ const uint32 _hordeNPC;
+ const Position _spawnPos;
+};
+
+const FactionSpawnerHelper executionerVictims[VictimCount] =
+{
+ { NPC_CAPTAIN_ALINA, NPC_CAPTAIN_BONESHATTER, { 138.8807f, -84.22707f, 1.992269f, 0.06981317f } },
+ { NPC_ALLIANCE_VICTIM_1, NPC_HORDE_VICTIM_1, { 151.2411f, -91.02930f, 2.019741f, 1.57079600f } },
+ { NPC_ALLIANCE_VICTIM_2, NPC_HORDE_VICTIM_2, { 151.0459f, -77.51981f, 2.021008f, 4.74729500f } }
+};
+
+
#endif
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index f3c8396832c..87bd5923c8f 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -338,7 +338,7 @@ class spell_q11396_11399_scourging_crystal_controller : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q11396_11399_scourging_crystal_controller_SpellScript();
- };
+ }
};
// 43882 Scourging Crystal Controller Dummy
@@ -374,7 +374,7 @@ class spell_q11396_11399_scourging_crystal_controller_dummy : public SpellScript
SpellScript* GetSpellScript() const override
{
return new spell_q11396_11399_scourging_crystal_controller_dummy_SpellScript();
- };
+ }
};
// http://www.wowhead.com/quest=11515 Blood for Blood
@@ -855,7 +855,7 @@ class spell_symbol_of_life_dummy : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_symbol_of_life_dummy_SpellScript();
- };
+ }
};
// http://www.wowhead.com/quest=12659 Scalps!
@@ -898,7 +898,7 @@ class spell_q12659_ahunaes_knife : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q12659_ahunaes_knife_SpellScript();
- };
+ }
};
enum StoppingTheSpread
@@ -944,7 +944,7 @@ class spell_q9874_liquid_fire : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q9874_liquid_fire_SpellScript();
- };
+ }
};
enum SalvagingLifesStength
@@ -988,7 +988,7 @@ class spell_q12805_lifeblood_dummy : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q12805_lifeblood_dummy_SpellScript();
- };
+ }
};
/*
diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h
index dc9e948966d..e83340bdd84 100644
--- a/src/server/shared/Common.h
+++ b/src/server/shared/Common.h
@@ -38,6 +38,7 @@
#include <queue>
#include <sstream>
#include <algorithm>
+#include <memory>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
@@ -164,4 +165,14 @@ struct LocalizedString
template <typename T>
using Optional = boost::optional<T>;
+namespace Trinity
+{
+ //! std::make_unique implementation (TODO: remove this once C++14 is supported)
+ template<typename T, typename ...Args>
+ std::unique_ptr<T> make_unique(Args&& ...args)
+ {
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+ }
+}
+
#endif
diff --git a/src/server/shared/Cryptography/SHA1.h b/src/server/shared/Cryptography/SHA1.h
index ebd9f721d4a..f59bdc25556 100644
--- a/src/server/shared/Cryptography/SHA1.h
+++ b/src/server/shared/Cryptography/SHA1.h
@@ -39,8 +39,8 @@ class SHA1Hash
void Initialize();
void Finalize();
- uint8 *GetDigest(void) { return mDigest; };
- int GetLength(void) const { return SHA_DIGEST_LENGTH; };
+ uint8 *GetDigest(void) { return mDigest; }
+ int GetLength(void) const { return SHA_DIGEST_LENGTH; }
private:
SHA_CTX mC;
diff --git a/src/server/shared/Cryptography/SHA256.h b/src/server/shared/Cryptography/SHA256.h
index 659236f9495..1d85545b2e0 100644
--- a/src/server/shared/Cryptography/SHA256.h
+++ b/src/server/shared/Cryptography/SHA256.h
@@ -38,8 +38,8 @@ class SHA256Hash
void Initialize();
void Finalize();
- uint8 *GetDigest(void) { return mDigest; };
- int GetLength(void) const { return SHA256_DIGEST_LENGTH; };
+ uint8 *GetDigest(void) { return mDigest; }
+ int GetLength(void) const { return SHA256_DIGEST_LENGTH; }
private:
SHA256_CTX mC;
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index e9ce253d1cf..277ccd4569a 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -690,7 +690,12 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS, "SELECT buildingId FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS, "INSERT INTO character_garrison_blueprints (guid, buildingId) VALUES (?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS, "DELETE FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, "SELECT plotInstanceId, buildingId, timeBuilt, active FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, "SELECT plotInstanceId, buildingId, timeBuilt, active FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS, "INSERT INTO character_garrison_buildings (guid, plotInstanceId, buildingId, timeBuilt, active) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS, "DELETE FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS, "SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status FROM character_garrison_followers WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS, "INSERT INTO character_garrison_followers (dbId, guid, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS, "DELETE gfab, gf FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE gf.guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "SELECT gfab.dbId, gfab.abilityId FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE guid = ? ORDER BY gfab.slot", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "INSERT INTO character_garrison_follower_abilities (dbId, abilityId, slot) VALUES (?, ?, ?)", CONNECTION_ASYNC);
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index 53c42a0b852..fc9c930e6b1 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -608,6 +608,11 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHARACTER_GARRISON_BUILDINGS,
CHAR_INS_CHARACTER_GARRISON_BUILDINGS,
CHAR_DEL_CHARACTER_GARRISON_BUILDINGS,
+ CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS,
+ CHAR_INS_CHARACTER_GARRISON_FOLLOWERS,
+ CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS,
+ CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
+ CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
MAX_CHARACTERDATABASE_STATEMENTS
};
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index 70350f3136c..99d6cb7af50 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -46,7 +46,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_INS_IP_BANNED, "INSERT INTO ip_banned (ip, bandate, unbandate, bannedby, banreason) VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_IP_NOT_BANNED, "DELETE FROM ip_banned WHERE ip = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_ACCOUNT_BANNED, "INSERT INTO account_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?, 1)", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED, "UPDATE account_banned SET active = 0 WHERE id = ? AND active != 0", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED, "UPDATE account_banned SET unbandate = UNIX_TIMESTAMP(), active = 0 WHERE id = ? AND active != 0", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM, "DELETE FROM realmcharacters WHERE acctid = ? AND realmid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_REALM_CHARACTERS, "DELETE FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_REALM_CHARACTERS, "INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (?, ?, ?)", CONNECTION_ASYNC);
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp
index f8f641a9ea7..e50cf42e439 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.cpp
+++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp
@@ -61,6 +61,7 @@ HANDLE WheatyExceptionReport::m_hDumpFile;
HANDLE WheatyExceptionReport::m_hProcess;
SymbolPairs WheatyExceptionReport::symbols;
std::stack<SymbolDetail> WheatyExceptionReport::symbolDetails;
+bool WheatyExceptionReport::stackOverflowException;
// Declare global instance of class
WheatyExceptionReport g_WheatyExceptionReport;
@@ -72,6 +73,7 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor
// Install the unhandled exception filter function
m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter);
m_hProcess = GetCurrentProcess();
+ stackOverflowException = false;
if (!IsDebuggerPresent())
{
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
@@ -97,6 +99,9 @@ WheatyExceptionReport::~WheatyExceptionReport()
LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
PEXCEPTION_POINTERS pExceptionInfo)
{
+ if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
+ stackOverflowException = true;
+
TCHAR module_folder_name[MAX_PATH];
GetModuleFileName(0, module_folder_name, MAX_PATH);
TCHAR* pos = _tcsrchr(module_folder_name, '\\');
@@ -419,107 +424,114 @@ void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
void WheatyExceptionReport::GenerateExceptionReport(
PEXCEPTION_POINTERS pExceptionInfo)
{
- SYSTEMTIME systime;
- GetLocalTime(&systime);
-
- // Start out with a banner
- _tprintf(_T("Revision: %s\r\n"), _FULLVERSION);
- _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
- PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
-
- PrintSystemInfo();
- // First print information about the type of fault
- _tprintf(_T("\r\n//=====================================================\r\n"));
- _tprintf(_T("Exception code: %08X %s\r\n"),
- pExceptionRecord->ExceptionCode,
- GetExceptionString(pExceptionRecord->ExceptionCode));
-
- // Now print information about where the fault occured
- TCHAR szFaultingModule[MAX_PATH];
- DWORD section;
- DWORD_PTR offset;
- GetLogicalAddress(pExceptionRecord->ExceptionAddress,
- szFaultingModule,
- sizeof(szFaultingModule),
- section, offset);
+ __try
+ {
+ SYSTEMTIME systime;
+ GetLocalTime(&systime);
+
+ // Start out with a banner
+ _tprintf(_T("Revision: %s\r\n"), _FULLVERSION);
+ _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
+ PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
+
+ PrintSystemInfo();
+ // First print information about the type of fault
+ _tprintf(_T("\r\n//=====================================================\r\n"));
+ _tprintf(_T("Exception code: %08X %s\r\n"),
+ pExceptionRecord->ExceptionCode,
+ GetExceptionString(pExceptionRecord->ExceptionCode));
+
+ // Now print information about where the fault occured
+ TCHAR szFaultingModule[MAX_PATH];
+ DWORD section;
+ DWORD_PTR offset;
+ GetLogicalAddress(pExceptionRecord->ExceptionAddress,
+ szFaultingModule,
+ sizeof(szFaultingModule),
+ section, offset);
#ifdef _M_IX86
- _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"),
- pExceptionRecord->ExceptionAddress,
- section, offset, szFaultingModule);
+ _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"),
+ pExceptionRecord->ExceptionAddress,
+ section, offset, szFaultingModule);
#endif
#ifdef _M_X64
- _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"),
- pExceptionRecord->ExceptionAddress,
- section, offset, szFaultingModule);
+ _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"),
+ pExceptionRecord->ExceptionAddress,
+ section, offset, szFaultingModule);
#endif
- PCONTEXT pCtx = pExceptionInfo->ContextRecord;
+ PCONTEXT pCtx = pExceptionInfo->ContextRecord;
- // Show the registers
- #ifdef _M_IX86 // X86 Only!
- _tprintf(_T("\r\nRegisters:\r\n"));
+ // Show the registers
+#ifdef _M_IX86 // X86 Only!
+ _tprintf(_T("\r\nRegisters:\r\n"));
- _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
- , pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx,
- pCtx->Esi, pCtx->Edi);
+ _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
+ , pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx,
+ pCtx->Esi, pCtx->Edi);
- _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip);
- _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
- pCtx->SegSs, pCtx->Esp, pCtx->Ebp);
- _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
- pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
- _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
- #endif
+ _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip);
+ _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
+ pCtx->SegSs, pCtx->Esp, pCtx->Ebp);
+ _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
+ pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
+ _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
+#endif
- #ifdef _M_X64
- _tprintf(_T("\r\nRegisters:\r\n"));
- _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n")
- _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n")
- , pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx,
- pCtx->Rsi, pCtx->Rdi, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15);
- _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip);
- _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"),
- pCtx->SegSs, pCtx->Rsp, pCtx->Rbp);
- _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
- pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
- _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
- #endif
+#ifdef _M_X64
+ _tprintf(_T("\r\nRegisters:\r\n"));
+ _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n")
+ _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n")
+ , pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx,
+ pCtx->Rsi, pCtx->Rdi, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15);
+ _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip);
+ _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"),
+ pCtx->SegSs, pCtx->Rsp, pCtx->Rbp);
+ _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
+ pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
+ _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
+#endif
- SymSetOptions(SYMOPT_DEFERRED_LOADS);
+ SymSetOptions(SYMOPT_DEFERRED_LOADS);
- // Initialize DbgHelp
- if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
- {
- _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"),
- ErrorMessage(GetLastError()));
- }
+ // Initialize DbgHelp
+ if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
+ {
+ _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"),
+ ErrorMessage(GetLastError()));
+ }
- CONTEXT trashableContext = *pCtx;
+ CONTEXT trashableContext = *pCtx;
- WriteStackDetails(&trashableContext, false, NULL);
- printTracesForAllThreads(false);
+ WriteStackDetails(&trashableContext, false, NULL);
+ printTracesForAllThreads(false);
-// #ifdef _M_IX86 // X86 Only!
+ // #ifdef _M_IX86 // X86 Only!
- _tprintf(_T("========================\r\n"));
- _tprintf(_T("Local Variables And Parameters\r\n"));
+ _tprintf(_T("========================\r\n"));
+ _tprintf(_T("Local Variables And Parameters\r\n"));
- trashableContext = *pCtx;
- WriteStackDetails(&trashableContext, true, NULL);
- printTracesForAllThreads(true);
+ trashableContext = *pCtx;
+ WriteStackDetails(&trashableContext, true, NULL);
+ printTracesForAllThreads(true);
- /*_tprintf(_T("========================\r\n"));
- _tprintf(_T("Global Variables\r\n"));
+ /*_tprintf(_T("========================\r\n"));
+ _tprintf(_T("Global Variables\r\n"));
- SymEnumSymbols(GetCurrentProcess(),
+ SymEnumSymbols(GetCurrentProcess(),
(UINT_PTR)GetModuleHandle(szFaultingModule),
0, EnumerateSymbolsCallback, 0);*/
- // #endif // X86 Only!
+ // #endif // X86 Only!
- SymCleanup(GetCurrentProcess());
+ SymCleanup(GetCurrentProcess());
- _tprintf(_T("\r\n"));
+ _tprintf(_T("\r\n"));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ _tprintf(_T("Error writing the crash log\r\n"));
+ }
}
//======================================================================
@@ -1313,16 +1325,43 @@ DWORD_PTR WheatyExceptionReport::DereferenceUnsafePointer(DWORD_PTR address)
//============================================================================
int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...)
{
- TCHAR szBuff[WER_LARGE_BUFFER_SIZE];
int retValue;
- DWORD cbWritten;
va_list argptr;
-
va_start(argptr, format);
+ if (stackOverflowException)
+ {
+ retValue = heapprintf(format, argptr);
+ va_end(argptr);
+ }
+ else
+ {
+ retValue = stackprintf(format, argptr);
+ va_end(argptr);
+ }
+
+ return retValue;
+}
+
+int __cdecl WheatyExceptionReport::stackprintf(const TCHAR * format, va_list argptr)
+{
+ int retValue;
+ DWORD cbWritten;
+
+ TCHAR szBuff[WER_LARGE_BUFFER_SIZE];
retValue = vsprintf(szBuff, format, argptr);
- va_end(argptr);
+ WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0);
+ return retValue;
+}
+
+int __cdecl WheatyExceptionReport::heapprintf(const TCHAR * format, va_list argptr)
+{
+ int retValue;
+ DWORD cbWritten;
+ TCHAR* szBuff = (TCHAR*)malloc(sizeof(TCHAR) * WER_LARGE_BUFFER_SIZE);
+ retValue = vsprintf(szBuff, format, argptr);
WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0);
+ free(szBuff);
return retValue;
}
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h
index b7731daaa2b..101b6187f2b 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.h
+++ b/src/server/shared/Debugging/WheatyExceptionReport.h
@@ -178,6 +178,8 @@ class WheatyExceptionReport
static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
static int __cdecl _tprintf(const TCHAR * format, ...);
+ static int __cdecl stackprintf(const TCHAR * format, va_list argptr);
+ static int __cdecl heapprintf(const TCHAR * format, va_list argptr);
static bool StoreSymbol(DWORD type , DWORD_PTR offset);
static void ClearSymbols();
@@ -191,6 +193,7 @@ class WheatyExceptionReport
static HANDLE m_hProcess;
static SymbolPairs symbols;
static std::stack<SymbolDetail> symbolDetails;
+ static bool stackOverflowException;
static char* PushSymbolDetail(char* pszCurrBuffer);
static char* PopSymbolDetail(char* pszCurrBuffer);
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index e22a06e635e..5b3782fce55 100644
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -23,6 +23,7 @@
#include "Appender.h"
#include "Logger.h"
#include "StringFormat.h"
+#include "Common.h"
#include <boost/asio/io_service.hpp>
#include <boost/asio/strand.hpp>
@@ -64,7 +65,7 @@ class Log
template<typename... Args>
inline void outMessage(std::string const& filter, LogLevel const level, const char* fmt, Args const&... args)
{
- write(std::unique_ptr<LogMessage>(new LogMessage(level, filter, Trinity::StringFormat(fmt, args...))));
+ write(Trinity::make_unique<LogMessage>(level, filter, Trinity::StringFormat(fmt, args...)));
}
template<typename... Args>
@@ -73,7 +74,7 @@ class Log
if (!ShouldLog("commands.gm", LOG_LEVEL_INFO))
return;
- std::unique_ptr<LogMessage> msg(new LogMessage(LOG_LEVEL_INFO, "commands.gm", std::move(Trinity::StringFormat(fmt, args...))));
+ std::unique_ptr<LogMessage> msg = Trinity::make_unique<LogMessage>(LOG_LEVEL_INFO, "commands.gm", std::move(Trinity::StringFormat(fmt, args...)));
msg->param1 = std::to_string(account);
diff --git a/src/server/shared/PrecompiledHeaders/sharedPCH.h b/src/server/shared/PrecompiledHeaders/sharedPCH.h
index d0c15b17f0c..87af9f44eb7 100644
--- a/src/server/shared/PrecompiledHeaders/sharedPCH.h
+++ b/src/server/shared/PrecompiledHeaders/sharedPCH.h
@@ -6,3 +6,4 @@
#include "SQLOperation.h"
#include "Errors.h"
#include "TypeList.h"
+#include "TaskScheduler.h"
diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp
index 9806151b4c4..10c8c163ec4 100644
--- a/src/server/shared/Updater/DBUpdater.cpp
+++ b/src/server/shared/Updater/DBUpdater.cpp
@@ -381,8 +381,27 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
args.push_back("-h" + host);
args.push_back("-u" + user);
args.push_back("-p" + password);
+
+ // Check if we want to connect through ip or socket (Unix only)
+#ifdef _WIN32
+
args.push_back("-P" + port_or_socket);
+#else
+
+ if (!std::isdigit(port_or_socket[0]))
+ {
+ // We can't check here if host == "." because is named localhost if socket option is enabled
+ args.push_back("-P0");
+ args.push_back("--protocol=SOCKET");
+ args.push_back("-S" + port_or_socket);
+ }
+ else
+ // generic case
+ args.push_back("-P" + port_or_socket);
+
+#endif
+
// Set the default charset to utf8
args.push_back("--default-character-set=utf8");
diff --git a/src/server/shared/Utilities/TaskScheduler.cpp b/src/server/shared/Utilities/TaskScheduler.cpp
new file mode 100644
index 00000000000..c945ad4dab0
--- /dev/null
+++ b/src/server/shared/Utilities/TaskScheduler.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "TaskScheduler.h"
+
+TaskScheduler& TaskScheduler::Update()
+{
+ _now = clock_t::now();
+ Dispatch();
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::Update(size_t const milliseconds)
+{
+ return Update(std::chrono::milliseconds(milliseconds));
+}
+
+TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable)
+{
+ _asyncHolder.push(callable);
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::CancelAll()
+{
+ /// Clear the task holder
+ _task_holder.Clear();
+ _asyncHolder = AsyncHolder();
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::CancelGroup(group_t const group)
+{
+ _task_holder.RemoveIf([group](TaskContainer const& task) -> bool
+ {
+ return task->IsInGroup(group);
+ });
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::CancelGroupsOf(std::vector<group_t> const& groups)
+{
+ std::for_each(groups.begin(), groups.end(),
+ std::bind(&TaskScheduler::CancelGroup, this, std::placeholders::_1));
+
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::InsertTask(TaskContainer task)
+{
+ _task_holder.Push(std::forward<TaskContainer>(task));
+ return *this;
+}
+
+void TaskScheduler::Dispatch()
+{
+ // Process all asyncs
+ while (!_asyncHolder.empty())
+ {
+ _asyncHolder.front()();
+ _asyncHolder.pop();
+ }
+
+ while (!_task_holder.IsEmpty())
+ {
+ if (_task_holder.First()->_end > _now)
+ break;
+
+ // Perfect forward the context to the handler
+ // Use weak references to catch destruction before callbacks.
+ TaskContext context(new TaskContextInstance(_task_holder.Pop(),
+ std::weak_ptr<TaskScheduler>(self_reference)));
+
+ // Invoke the context
+ context->Invoke();
+ }
+}
+
+void TaskScheduler::TaskQueue::Push(TaskContainer&& task)
+{
+ container.insert(task);
+}
+
+auto TaskScheduler::TaskQueue::Pop() -> TaskContainer
+{
+ TaskContainer result = *container.begin();
+ container.erase(container.begin());
+ return result;
+}
+
+auto TaskScheduler::TaskQueue::First() const -> TaskContainer const&
+{
+ return *container.begin();
+}
+
+void TaskScheduler::TaskQueue::Clear()
+{
+ container.clear();
+}
+
+void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)> const& filter)
+{
+ for (auto itr = container.begin(); itr != container.end();)
+ if (filter(*itr))
+ itr = container.erase(itr);
+ else
+ ++itr;
+}
+
+void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter)
+{
+ std::vector<TaskContainer> cache;
+ for (auto itr = container.begin(); itr != container.end();)
+ if (filter(*itr))
+ {
+ cache.push_back(*itr);
+ itr = container.erase(itr);
+ }
+ else
+ ++itr;
+
+ container.insert(cache.begin(), cache.end());
+}
+
+bool TaskScheduler::TaskQueue::IsEmpty() const
+{
+ return container.empty();
+}
+
+TaskContextInstance& TaskContextInstance::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply)
+{
+ if (auto const owner = _owner.lock())
+ apply(*owner);
+
+ return *this;
+}
+
+bool TaskContextInstance::IsInGroup(TaskScheduler::group_t const group) const
+{
+ return _task->IsInGroup(group);
+}
+
+TaskContextInstance& TaskContextInstance::SetGroup(TaskScheduler::group_t const group)
+{
+ _task->_group = group;
+ return *this;
+}
+
+TaskContextInstance& TaskContextInstance::ClearGroup()
+{
+ _task->_group = boost::none;
+ return *this;
+}
+
+TaskScheduler::repeated_t TaskContextInstance::GetRepeatCounter() const
+{
+ return _task->_repeated;
+}
+
+TaskContextInstance& TaskContextInstance::Async(std::function<void()> const& callable)
+{
+ return Dispatch(std::bind(&TaskScheduler::Async, std::placeholders::_1, callable));
+}
+
+TaskContextInstance& TaskContextInstance::CancelAll()
+{
+ return Dispatch(std::mem_fn(&TaskScheduler::CancelAll));
+}
+
+TaskContextInstance& TaskContextInstance::CancelGroup(TaskScheduler::group_t const group)
+{
+ return Dispatch(std::bind(&TaskScheduler::CancelGroup, std::placeholders::_1, group));
+}
+
+TaskContextInstance& TaskContextInstance::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups)
+{
+ return Dispatch(std::bind(&TaskScheduler::CancelGroupsOf, std::placeholders::_1, groups));
+}
+
+void TaskContextInstance::AssertOnConsumed()
+{
+ // This was adapted to TC to prevent static analysis tools from complaining.
+ // If you encounter this assertion check if you repeat a TaskContext more then 1 time!
+ ASSERT(_task && "Bad task logic, task context was consumed already!");
+}
+
+void TaskContextInstance::Invoke()
+{
+ _task->_task(shared_from_this());
+}
diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/server/shared/Utilities/TaskScheduler.h
new file mode 100644
index 00000000000..3498a9bcf6c
--- /dev/null
+++ b/src/server/shared/Utilities/TaskScheduler.h
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TASK_SCHEDULER_H_
+#define _TASK_SCHEDULER_H_
+
+#include <algorithm>
+#include <chrono>
+#include <vector>
+#include <queue>
+#include <memory>
+#include <utility>
+#include <set>
+
+#include <boost/optional.hpp>
+
+#include "Util.h"
+
+class TaskContextInstance;
+
+typedef std::shared_ptr<TaskContextInstance> TaskContext;
+
+/// The TaskScheduler class provides the ability to schedule std::function's in the near future.
+/// Use TaskScheduler::Update to update the scheduler.
+/// Popular methods are:
+/// * Schedule (Schedules a std::function which will be executed in the near future).
+/// * Schedules an asynchronous function which will be executed at the next update tick.
+/// * Cancel, Delay & Reschedule (Methods to manipulate already scheduled tasks).
+/// Tasks are organized in groups (uint), multiple tasks can have the same group id,
+/// you can provide a group or not, but keep in mind that you can only manipulate specific tasks through its group id!
+/// Tasks callbacks use the function signature void(TaskContext) where TaskContext provides
+/// access to the function schedule plan which makes it possible to repeat the task
+/// with the same duration or a new one.
+/// It also provides access to the repeat counter which is useful for task that repeat itself often
+/// but behave different every time (spoken event dialogs for example).
+class TaskScheduler
+{
+ friend class TaskContextInstance;
+
+ // Time definitions (use steady clock)
+ typedef std::chrono::steady_clock clock_t;
+ typedef clock_t::time_point timepoint_t;
+ typedef clock_t::duration duration_t;
+
+ // Task group type
+ typedef uint32 group_t;
+ // Task repeated type
+ typedef uint32 repeated_t;
+ // Task handle type
+ typedef std::function<void(TaskContext)> task_handler_t;
+
+ class Task
+ {
+ friend class TaskContextInstance;
+ friend class TaskScheduler;
+
+ timepoint_t _end;
+ duration_t _duration;
+ boost::optional<group_t> _group;
+ repeated_t _repeated;
+ task_handler_t _task;
+
+ public:
+ // All Argument construct
+ Task(timepoint_t const& end, duration_t const& duration, boost::optional<group_t> const& group,
+ repeated_t const repeated, task_handler_t const& task)
+ : _end(end), _duration(duration), _group(group), _repeated(repeated), _task(task) { }
+
+ // Minimal Argument construct
+ Task(timepoint_t const& end, duration_t const& duration, task_handler_t const& task)
+ : _end(end), _duration(duration), _group(boost::none), _repeated(0), _task(task) { }
+
+ // Copy construct
+ Task(Task const&) = delete;
+ // Move construct
+ Task(Task&&) = delete;
+ // Copy Assign
+ Task& operator= (Task const&) = default;
+ // Move Assign
+ Task& operator= (Task&& right) = delete;
+
+ // Order tasks by its end
+ inline bool operator< (Task const& other) const
+ {
+ return _end < other._end;
+ }
+
+ inline bool operator> (Task const& other) const
+ {
+ return _end > other._end;
+ }
+
+ // Compare tasks with its end
+ inline bool operator== (Task const& other)
+ {
+ return _end == other._end;
+ }
+
+ // Returns true if the task is in the given group
+ inline bool IsInGroup(group_t const group) const
+ {
+ return _group == group;
+ }
+ };
+
+ typedef std::shared_ptr<Task> TaskContainer;
+
+ /// Container which provides Task order, insert and reschedule operations.
+ struct Compare
+ {
+ bool operator() (TaskContainer const& left, TaskContainer const& right)
+ {
+ return (*left.get()) < (*right.get());
+ };
+ };
+
+ class TaskQueue
+ {
+ std::multiset<TaskContainer, Compare> container;
+
+ public:
+ // Pushes the task in the container
+ void Push(TaskContainer&& task);
+
+ /// Pops the task out of the container
+ TaskContainer Pop();
+
+ TaskContainer const& First() const;
+
+ void Clear();
+
+ void RemoveIf(std::function<bool(TaskContainer const&)> const& filter);
+
+ void ModifyIf(std::function<bool(TaskContainer const&)> const& filter);
+
+ bool IsEmpty() const;
+ };
+
+ /// Contains a self reference to track if this object was deleted or not.
+ std::shared_ptr<TaskScheduler> self_reference;
+
+ /// The current time point (now)
+ timepoint_t _now;
+
+ /// The Task Queue which contains all task objects.
+ TaskQueue _task_holder;
+
+ typedef std::queue<std::function<void()>> AsyncHolder;
+
+ /// Contains all asynchronous tasks which will be invoked at
+ /// the next update tick.
+ AsyncHolder _asyncHolder;
+
+public:
+ TaskScheduler() : self_reference(this, [](TaskScheduler const*) { }),
+ _now(clock_t::now()) { }
+
+ TaskScheduler(TaskScheduler const&) = delete;
+ TaskScheduler(TaskScheduler&&) = delete;
+ TaskScheduler& operator= (TaskScheduler const&) = delete;
+ TaskScheduler& operator= (TaskScheduler&&) = delete;
+
+ /// Update the scheduler to the current time.
+ TaskScheduler& Update();
+
+ /// Update the scheduler with a difftime in ms.
+ TaskScheduler& Update(size_t const milliseconds);
+
+ /// Update the scheduler with a difftime.
+ template<class _Rep, class _Period>
+ TaskScheduler& Update(std::chrono::duration<_Rep, _Period> const& difftime)
+ {
+ _now += difftime;
+ Dispatch();
+ return *this;
+ }
+
+ /// Schedule an callable function that is executed at the next update tick.
+ /// Its safe to modify the TaskScheduler from within the callable.
+ TaskScheduler& Async(std::function<void()> const& callable);
+
+ /// Schedule an event with a fixed rate.
+ /// Never call this from within a task context! Use TaskContext::Schedule instead!
+ template<class _Rep, class _Period>
+ TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> const& time,
+ task_handler_t const& task)
+ {
+ return ScheduleAt(_now, time, task);
+ }
+
+ /// Schedule an event with a fixed rate.
+ /// Never call this from within a task context! Use TaskContext::Schedule instead!
+ template<class _Rep, class _Period>
+ TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> const& time,
+ group_t const group, task_handler_t const& task)
+ {
+ return ScheduleAt(_now, time, group, task);
+ }
+
+ /// Schedule an event with a randomized rate between min and max rate.
+ /// Never call this from within a task context! Use TaskContext::Schedule instead!
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max, task_handler_t const& task)
+ {
+ return Schedule(RandomDurationBetween(min, max), task);
+ }
+
+ /// Schedule an event with a fixed rate.
+ /// Never call this from within a task context! Use TaskContext::Schedule instead!
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max, group_t const group,
+ task_handler_t const& task)
+ {
+ return Schedule(RandomDurationBetween(min, max), group, task);
+ }
+
+ /// Cancels all tasks.
+ /// Never call this from within a task context! Use TaskContext::CancelAll instead!
+ TaskScheduler& CancelAll();
+
+ /// Cancel all tasks of a single group.
+ /// Never call this from within a task context! Use TaskContext::CancelGroup instead!
+ TaskScheduler& CancelGroup(group_t const group);
+
+ /// Cancels all groups in the given std::vector.
+ /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}"
+ TaskScheduler& CancelGroupsOf(std::vector<group_t> const& groups);
+
+ /// Delays all tasks with the given duration.
+ template<class _Rep, class _Period>
+ TaskScheduler& DelayAll(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ _task_holder.ModifyIf([&duration](TaskContainer const& task) -> bool
+ {
+ task->_end += duration;
+ return true;
+ });
+ return *this;
+ }
+
+ /// Delays all tasks with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return DelayAll(RandomDurationBetween(min, max));
+ }
+
+ /// Delays all tasks of a group with the given duration.
+ template<class _Rep, class _Period>
+ TaskScheduler& DelayGroup(group_t const group, std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ _task_holder.ModifyIf([&duration, group](TaskContainer const& task) -> bool
+ {
+ if (task->IsInGroup(group))
+ {
+ task->_end += duration;
+ return true;
+ }
+ else
+ return false;
+ });
+ return *this;
+ }
+
+ /// Delays all tasks of a group with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& DelayGroup(group_t const group,
+ std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return DelayGroup(group, RandomDurationBetween(min, max));
+ }
+
+ /// Reschedule all tasks with a given duration.
+ template<class _Rep, class _Period>
+ TaskScheduler& RescheduleAll(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ auto const end = _now + duration;
+ _task_holder.ModifyIf([end](TaskContainer const& task) -> bool
+ {
+ task->_end = end;
+ return true;
+ });
+ return *this;
+ }
+
+ /// Reschedule all tasks with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return RescheduleAll(RandomDurationBetween(min, max));
+ }
+
+ /// Reschedule all tasks of a group with the given duration.
+ template<class _Rep, class _Period>
+ TaskScheduler& RescheduleGroup(group_t const group, std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ auto const end = _now + duration;
+ _task_holder.ModifyIf([end, group](TaskContainer const& task) -> bool
+ {
+ if (task->IsInGroup(group))
+ {
+ task->_end = end;
+ return true;
+ }
+ else
+ return false;
+ });
+ return *this;
+ }
+
+ /// Reschedule all tasks of a group with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& RescheduleGroup(group_t const group,
+ std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return RescheduleGroup(group, RandomDurationBetween(min, max));
+ }
+
+private:
+ /// Insert a new task to the enqueued tasks.
+ TaskScheduler& InsertTask(TaskContainer task);
+
+ template<class _Rep, class _Period>
+ TaskScheduler& ScheduleAt(timepoint_t const& end,
+ std::chrono::duration<_Rep, _Period> const& time, task_handler_t const& task)
+ {
+ return InsertTask(TaskContainer(new Task(end + time, time, task)));
+ }
+
+ /// Schedule an event with a fixed rate.
+ /// Never call this from within a task context! Use TaskContext::schedule instead!
+ template<class _Rep, class _Period>
+ TaskScheduler& ScheduleAt(timepoint_t const& end,
+ std::chrono::duration<_Rep, _Period> const& time,
+ group_t const group, task_handler_t const& task)
+ {
+ static repeated_t const DEFAULT_REPEATED = 0;
+ return InsertTask(TaskContainer(new Task(end + time, time, group, DEFAULT_REPEATED, task)));
+ }
+
+ // Returns a random duration between min and max
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ std::chrono::milliseconds
+ static RandomDurationBetween(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ auto const milli_min = std::chrono::duration_cast<std::chrono::milliseconds>(min);
+ auto const milli_max = std::chrono::duration_cast<std::chrono::milliseconds>(max);
+
+ // TC specific: use SFMT URandom
+ return std::chrono::milliseconds(urand(milli_min.count(), milli_max.count()));
+ }
+
+ /// Dispatch remaining tasks
+ void Dispatch();
+};
+
+class TaskContextInstance
+ : public std::enable_shared_from_this<TaskContextInstance>
+{
+ friend class TaskScheduler;
+
+ /// Associated task
+ TaskScheduler::TaskContainer _task;
+
+ /// Owner
+ std::weak_ptr<TaskScheduler> const _owner;
+
+ /// Dispatches an action safe on the TaskScheduler
+ TaskContextInstance& Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply);
+
+public:
+ explicit TaskContextInstance(TaskScheduler::TaskContainer task, std::weak_ptr<TaskScheduler>&& owner)
+ : _task(task), _owner(owner) { }
+
+ /// Returns true if the event is in the given group
+ bool IsInGroup(TaskScheduler::group_t const group) const;
+
+ /// Sets the event in the given group
+ TaskContextInstance& SetGroup(TaskScheduler::group_t const group);
+
+ /// Removes the group from the event
+ TaskContextInstance& ClearGroup();
+
+ /// Returns the repeat counter which increases every time the task is repeated.
+ TaskScheduler::repeated_t GetRepeatCounter() const;
+
+ /// Repeats the event and sets a new duration.
+ /// std::chrono::seconds(5) for example.
+ /// This will consume the task context, its not possible to repeat the task again
+ /// from the same task context!
+ template<class _Rep, class _Period>
+ TaskContextInstance& Repeat(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ AssertOnConsumed();
+
+ // Set new duration, in-context timing and increment repeat counter
+ _task->_duration = duration;
+ _task->_end += duration;
+ _task->_repeated += 1;
+ return Dispatch(std::bind(&TaskScheduler::InsertTask, std::placeholders::_1, _task));
+ }
+
+ /// Repeats the event with the same duration.
+ /// This will consume the task context, its not possible to repeat the task again
+ /// from the same task context!
+ TaskContextInstance& Repeat()
+ {
+ return Repeat(_task->_duration);
+ }
+
+ /// Repeats the event and set a new duration that is randomized between min and max.
+ /// std::chrono::seconds(5) for example.
+ /// This will consume the task context, its not possible to repeat the task again
+ /// from the same task context!
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContextInstance& Repeat(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return Repeat(TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+ /// Schedule a callable function that is executed at the next update tick from within the context.
+ /// Its safe to modify the TaskScheduler from within the callable.
+ TaskContextInstance& Async(std::function<void()> const& callable);
+
+ /// Schedule an event with a fixed rate from within the context.
+ /// Its possible that the new event is executed immediately!
+ /// Use TaskScheduler::Async to create a task
+ /// which will be called at the next update tick.
+ template<class _Rep, class _Period>
+ TaskContextInstance& Schedule(std::chrono::duration<_Rep, _Period> const& time,
+ TaskScheduler::task_handler_t const& task)
+ {
+ auto const end = _task->_end;
+ return Dispatch([end, time, task](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.ScheduleAt<_Rep, _Period>(end, time, task);
+ });
+ }
+
+ /// Schedule an event with a fixed rate from within the context.
+ /// Its possible that the new event is executed immediately!
+ /// Use TaskScheduler::Async to create a task
+ /// which will be called at the next update tick.
+ template<class _Rep, class _Period>
+ TaskContextInstance& Schedule(std::chrono::duration<_Rep, _Period> const& time,
+ TaskScheduler::group_t const group, TaskScheduler::task_handler_t const& task)
+ {
+ auto const end = _task->_end;
+ return Dispatch([end, time, group, task](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.ScheduleAt<_Rep, _Period>(end, time, group, task);
+ });
+ }
+
+ /// Schedule an event with a randomized rate between min and max rate from within the context.
+ /// Its possible that the new event is executed immediately!
+ /// Use TaskScheduler::Async to create a task
+ /// which will be called at the next update tick.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContextInstance& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max, TaskScheduler::task_handler_t const& task)
+ {
+ return Schedule(TaskScheduler::RandomDurationBetween(min, max), task);
+ }
+
+ /// Schedule an event with a randomized rate between min and max rate from within the context.
+ /// Its possible that the new event is executed immediately!
+ /// Use TaskScheduler::Async to create a task
+ /// which will be called at the next update tick.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContextInstance& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max, TaskScheduler::group_t const group,
+ TaskScheduler::task_handler_t const& task)
+ {
+ return Schedule(TaskScheduler::RandomDurationBetween(min, max), group, task);
+ }
+
+ /// Cancels all tasks from within the context.
+ TaskContextInstance& CancelAll();
+
+ /// Cancel all tasks of a single group from within the context.
+ TaskContextInstance& CancelGroup(TaskScheduler::group_t const group);
+
+ /// Cancels all groups in the given std::vector from within the context.
+ /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}"
+ TaskContextInstance& CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups);
+
+ /// Delays all tasks with the given duration from within the context.
+ template<class _Rep, class _Period>
+ TaskContextInstance& DelayAll(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ return Dispatch(std::bind(&TaskScheduler::DelayAll<_Rep, _Period>, std::placeholders::_1, duration));
+ }
+
+ /// Delays all tasks with a random duration between min and max from within the context.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContextInstance& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return DelayAll(TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+ /// Delays all tasks of a group with the given duration from within the context.
+ template<class _Rep, class _Period>
+ TaskContextInstance& DelayGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ return Dispatch(std::bind(&TaskScheduler::DelayGroup<_Rep, _Period>, std::placeholders::_1, group, duration));
+ }
+
+ /// Delays all tasks of a group with a random duration between min and max from within the context.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContextInstance& DelayGroup(TaskScheduler::group_t const group,
+ std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return DelayGroup(group, TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+ /// Reschedule all tasks with the given duration.
+ template<class _Rep, class _Period>
+ TaskContextInstance& RescheduleAll(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ return Dispatch(std::bind(&TaskScheduler::RescheduleAll, std::placeholders::_1, duration));
+ }
+
+ /// Reschedule all tasks with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContextInstance& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return RescheduleAll(TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+ /// Reschedule all tasks of a group with the given duration.
+ template<class _Rep, class _Period>
+ TaskContextInstance& RescheduleGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ return Dispatch(std::bind(&TaskScheduler::RescheduleGroup<_Rep, _Period>, std::placeholders::_1, group, duration));
+ }
+
+ /// Reschedule all tasks of a group with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContextInstance& RescheduleGroup(TaskScheduler::group_t const group,
+ std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return RescheduleGroup(group, TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+private:
+ void AssertOnConsumed();
+
+ /// Invokes the associated hook of the task.
+ void Invoke();
+};
+
+/// Milliseconds shorthand typedef.
+typedef std::chrono::milliseconds Milliseconds;
+
+/// Seconds shorthand typedef.
+typedef std::chrono::seconds Seconds;
+
+/// Minutes shorthand typedef.
+typedef std::chrono::minutes Minutes;
+
+/// Hours shorthand typedef.
+typedef std::chrono::hours Hours;
+
+#endif /// _TASK_SCHEDULER_H_
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index c59b845e454..668cec43aca 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1018,7 +1018,7 @@ OffhandCheckAtSpellUnlearn = 1
# ClientCacheVersion
# Description: Client cache version for client cache data reset. Use any value different
# from DB and not recently been used to trigger client side cache reset.
-# Default: 0 - (Use DB value from world DB db_version.cache_id field)
+# Default: 0 - (Use DB value from world DB version.cache_id field)
ClientCacheVersion = 0