aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.cpp7
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.h4
-rw-r--r--src/server/game/DataStores/DB2LoadInfo.h25
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp2
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/DataStores/DB2Structure.h17
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp17
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp40
-rw-r--r--src/server/game/Globals/ObjectMgr.h17
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.cpp9
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.h12
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/World/World.cpp7
15 files changed, 158 insertions, 6 deletions
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp
index 4e2fce8cec3..3af206c0644 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp
@@ -688,6 +688,13 @@ void HotfixDatabaseConnection::DoPrepareStatements()
" FROM garr_site_level_plot_inst WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST, "SELECT MAX(ID) + 1 FROM garr_site_level_plot_inst", CONNECTION_SYNCH);
+ // GarrTalentTree.db2
+ PrepareStatement(HOTFIX_SEL_GARR_TALENT_TREE, "SELECT ID, Name, GarrTypeID, ClassID, MaxTiers, UiOrder, Flags, UiTextureKitID, "
+ "GarrTalentTreeType, PlayerConditionID, FeatureTypeIndex, FeatureSubtypeIndex, CurrencyID FROM garr_talent_tree"
+ " WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
+ PREPARE_MAX_ID_STMT(HOTFIX_SEL_GARR_TALENT_TREE, "SELECT MAX(ID) + 1 FROM garr_talent_tree", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_TALENT_TREE, "SELECT ID, Name_lang FROM garr_talent_tree_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?", CONNECTION_SYNCH);
+
// GemProperties.db2
PrepareStatement(HOTFIX_SEL_GEM_PROPERTIES, "SELECT ID, EnchantId, Type FROM gem_properties WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_GEM_PROPERTIES, "SELECT MAX(ID) + 1 FROM gem_properties", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h
index befc2fbfbd5..2bc899c79c7 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.h
+++ b/src/server/database/Database/Implementation/HotfixDatabase.h
@@ -393,6 +393,10 @@ enum HotfixDatabaseStatements : uint32
HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST,
HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST_MAX_ID,
+ HOTFIX_SEL_GARR_TALENT_TREE,
+ HOTFIX_SEL_GARR_TALENT_TREE_MAX_ID,
+ HOTFIX_SEL_GARR_TALENT_TREE_LOCALE,
+
HOTFIX_SEL_GEM_PROPERTIES,
HOTFIX_SEL_GEM_PROPERTIES_MAX_ID,
diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h
index 211c620922a..c85f469e7b3 100644
--- a/src/server/game/DataStores/DB2LoadInfo.h
+++ b/src/server/game/DataStores/DB2LoadInfo.h
@@ -2456,6 +2456,31 @@ struct GarrSiteLevelPlotInstLoadInfo
}
};
+struct GarrTalentTreeLoadInfo
+{
+ static DB2LoadInfo const* Instance()
+ {
+ static constexpr DB2FieldMeta fields[] =
+ {
+ { false, FT_INT, "ID" },
+ { false, FT_STRING, "Name" },
+ { false, FT_BYTE, "GarrTypeID" },
+ { true, FT_INT, "ClassID" },
+ { true, FT_BYTE, "MaxTiers" },
+ { true, FT_BYTE, "UiOrder" },
+ { true, FT_INT, "Flags" },
+ { false, FT_SHORT, "UiTextureKitID" },
+ { true, FT_INT, "GarrTalentTreeType" },
+ { true, FT_INT, "PlayerConditionID" },
+ { true, FT_BYTE, "FeatureTypeIndex" },
+ { true, FT_BYTE, "FeatureSubtypeIndex" },
+ { true, FT_INT, "CurrencyID" },
+ };
+ static DB2LoadInfo const loadInfo(&fields[0], std::size(fields), GarrTalentTreeMeta::Instance(), HOTFIX_SEL_GARR_TALENT_TREE);
+ return &loadInfo;
+ }
+};
+
struct GemPropertiesLoadInfo
{
static DB2LoadInfo const* Instance()
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 4751b6c1177..3f78e9371b4 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -148,6 +148,7 @@ DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore("GarrPlot
DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore("GarrPlotInstance.db2", GarrPlotInstanceLoadInfo::Instance());
DB2Storage<GarrSiteLevelEntry> sGarrSiteLevelStore("GarrSiteLevel.db2", GarrSiteLevelLoadInfo::Instance());
DB2Storage<GarrSiteLevelPlotInstEntry> sGarrSiteLevelPlotInstStore("GarrSiteLevelPlotInst.db2", GarrSiteLevelPlotInstLoadInfo::Instance());
+DB2Storage<GarrTalentTreeEntry> sGarrTalentTreeStore("GarrTalentTree.db2", GarrTalentTreeLoadInfo::Instance());
DB2Storage<GemPropertiesEntry> sGemPropertiesStore("GemProperties.db2", GemPropertiesLoadInfo::Instance());
DB2Storage<GlobalCurveEntry> sGlobalCurveStore("GlobalCurve.db2", GlobalCurveLoadInfo::Instance());
DB2Storage<GlyphBindableSpellEntry> sGlyphBindableSpellStore("GlyphBindableSpell.db2", GlyphBindableSpellLoadInfo::Instance());
@@ -722,6 +723,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
LOAD_DB2(sGarrPlotInstanceStore);
LOAD_DB2(sGarrSiteLevelStore);
LOAD_DB2(sGarrSiteLevelPlotInstStore);
+ LOAD_DB2(sGarrTalentTreeStore);
LOAD_DB2(sGemPropertiesStore);
LOAD_DB2(sGlobalCurveStore);
LOAD_DB2(sGlyphBindableSpellStore);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 3fba87f73b6..49b2f551f5a 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -117,6 +117,7 @@ TC_GAME_API extern DB2Storage<GarrPlotBuildingEntry> sGarrPlotBui
TC_GAME_API extern DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore;
TC_GAME_API extern DB2Storage<GarrSiteLevelEntry> sGarrSiteLevelStore;
TC_GAME_API extern DB2Storage<GarrSiteLevelPlotInstEntry> sGarrSiteLevelPlotInstStore;
+TC_GAME_API extern DB2Storage<GarrTalentTreeEntry> sGarrTalentTreeStore;
TC_GAME_API extern DB2Storage<GemPropertiesEntry> sGemPropertiesStore;
TC_GAME_API extern DB2Storage<GlyphPropertiesEntry> sGlyphPropertiesStore;
TC_GAME_API extern DB2Storage<GuildColorBackgroundEntry> sGuildColorBackgroundStore;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 9e08a04866d..e52a14eaa30 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -1759,6 +1759,23 @@ struct GarrSiteLevelPlotInstEntry
uint8 UiMarkerSize;
};
+struct GarrTalentTreeEntry
+{
+ uint32 ID;
+ LocalizedString Name;
+ uint8 GarrTypeID;
+ int32 ClassID;
+ int8 MaxTiers;
+ int8 UiOrder;
+ int32 Flags;
+ uint16 UiTextureKitID;
+ int32 GarrTalentTreeType;
+ int32 PlayerConditionID;
+ int8 FeatureTypeIndex;
+ int8 FeatureSubtypeIndex;
+ int32 CurrencyID;
+};
+
struct GemPropertiesEntry
{
uint32 ID;
diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h
index 3a77d0f2a7f..25da6049f1c 100644
--- a/src/server/game/Entities/Creature/GossipDef.h
+++ b/src/server/game/Entities/Creature/GossipDef.h
@@ -64,7 +64,7 @@ enum class GossipOptionNpc : uint8
GarrisonTradeskill = 29, /*NYI*/ // White chat bubble
GarrisonRecruitment = 30, /*NYI*/ // White chat bubble
AdventureMap = 31, /*NYI*/ // White chat bubble
- GarrisonTalent = 32, /*NYI*/ // White chat bubble
+ GarrisonTalent = 32, // White chat bubble
ContributionCollector = 33, /*NYI*/ // White chat bubble
Transmogrify = 34, // Purple helm
AzeriteRespec = 35, /*NYI*/ // White chat bubble
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 9d7ff5c40a2..037ae501aae 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -56,6 +56,7 @@
#include "GameEventMgr.h"
#include "GameObjectAI.h"
#include "Garrison.h"
+#include "GarrisonMgr.h"
#include "GitRevision.h"
#include "GossipDef.h"
#include "GridNotifiers.h"
@@ -13937,6 +13938,13 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men
PlayerTalkClass->SendCloseGossip();
SendRespecWipeConfirm(guid, 0, SPEC_RESET_GLYPHS);
break;
+ case GossipOptionNpc::GarrisonTalent:
+ {
+ GossipMenuAddon const* addon = sObjectMgr->GetGossipMenuAddon(menuId);
+ GossipMenuItemAddon const* itemAddon = sObjectMgr->GetGossipMenuItemAddon(menuId, gossipListId);
+ SendGarrisonOpenTalentNpc(guid, itemAddon ? itemAddon->GarrTalentTreeID.value_or(0) : 0, addon ? addon->FriendshipFactionID : 0);
+ break;
+ }
case GossipOptionNpc::Transmogrify:
GetSession()->SendOpenTransmogrifier(guid);
break;
@@ -28156,3 +28164,12 @@ void Player::SendDisplayToast(uint32 entry, DisplayToastType type, bool isBonusR
SendDirectMessage(displayToast.Write());
}
+
+void Player::SendGarrisonOpenTalentNpc(ObjectGuid guid, int32 garrTalentTreeId, int32 friendshipFactionId)
+{
+ WorldPackets::Garrison::GarrisonOpenTalentNpc openTalentNpc;
+ openTalentNpc.NpcGUID = guid;
+ openTalentNpc.GarrTalentTreeID = garrTalentTreeId;
+ openTalentNpc.FriendshipFactionID = friendshipFactionId;
+ SendDirectMessage(openTalentNpc.Write());
+}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 67cb3f97b22..cbbacf92c49 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2772,6 +2772,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool CanEnableWarModeInArea() const;
void UpdateWarModeAuras();
+ void SendGarrisonOpenTalentNpc(ObjectGuid guid, int32 garrTalentTreeId, int32 friendshipFactionId);
+
std::string GetDebugInfo() const override;
UF::UpdateField<UF::PlayerData, 0, TYPEID_PLAYER> m_playerData;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 96db3bfa064..08763fe8aeb 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -9701,7 +9701,7 @@ void ObjectMgr::LoadGossipMenuItems()
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " gossip_menu_option entries in %u ms", _gossipMenuItemsStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::LoadGossipMenuFriendshipFactions()
+void ObjectMgr::LoadGossipMenuAddon()
{
uint32 oldMSTime = getMSTime();
@@ -9744,6 +9744,44 @@ void ObjectMgr::LoadGossipMenuFriendshipFactions()
TC_LOG_INFO("server.loading", ">> Loaded %u gossip_menu_addon IDs in %u ms", uint32(_gossipMenuAddonStore.size()), GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadGossipMenuItemAddon()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _gossipMenuItemAddonStore.clear();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT MenuID, OptionId, GarrTalentTreeID FROM gossip_menu_option_addon");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 gossip_menu_option_addon IDs. DB table `gossip_menu_option_addon` is empty!");
+ return;
+ }
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 menuId = fields[0].GetUInt32();
+ uint32 optionId = fields[1].GetUInt32();
+ GossipMenuItemAddon& addon = _gossipMenuItemAddonStore[{ menuId, optionId }];
+ if (!fields[2].IsNull())
+ {
+ addon.GarrTalentTreeID = fields[2].GetInt32();
+
+ if (!sGarrTalentTreeStore.LookupEntry(*addon.GarrTalentTreeID))
+ {
+ TC_LOG_ERROR("sql.sql", "Table gossip_menu_option_addon: MenuID %u OptionID %u is using non-existing GarrTalentTree %d",
+ menuId, optionId, *addon.GarrTalentTreeID);
+ addon.GarrTalentTreeID.reset();
+ }
+ }
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u gossip_menu_option_addon IDs in %u ms", uint32(_gossipMenuItemAddonStore.size()), GetMSTimeDiffToNow(oldMSTime));
+}
+
Trainer::Trainer const* ObjectMgr::GetTrainer(uint32 trainerId) const
{
return Trinity::Containers::MapGetValuePtr(_trainers, trainerId);
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 6919992f228..e898b5a9e42 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -757,6 +757,11 @@ struct GossipMenuItems
ConditionContainer Conditions;
};
+struct GossipMenuItemAddon
+{
+ Optional<int32> GarrTalentTreeID;
+};
+
struct GossipMenus
{
uint32 MenuID;
@@ -774,6 +779,7 @@ typedef std::pair<GossipMenusContainer::const_iterator, GossipMenusContainer::co
typedef std::pair<GossipMenusContainer::iterator, GossipMenusContainer::iterator> GossipMenusMapBoundsNonConst;
typedef std::multimap<uint32, GossipMenuItems> GossipMenuItemsContainer;
typedef std::unordered_map<uint32, GossipMenuAddon> GossipMenuAddonContainer;
+typedef std::unordered_map<std::pair<uint32, uint32>, GossipMenuItemAddon> GossipMenuItemAddonContainer;
struct QuestPOIBlobPoint
{
@@ -1394,7 +1400,8 @@ class TC_GAME_API ObjectMgr
void LoadGossipMenu();
void LoadGossipMenuItems();
- void LoadGossipMenuFriendshipFactions();
+ void LoadGossipMenuAddon();
+ void LoadGossipMenuItemAddon();
void LoadVendors();
void LoadTrainers();
@@ -1697,6 +1704,13 @@ class TC_GAME_API ObjectMgr
return &itr->second;
return nullptr;
}
+ GossipMenuItemAddon const* GetGossipMenuItemAddon(uint32 menuId, uint32 optionId) const
+ {
+ auto itr = _gossipMenuItemAddonStore.find({ menuId, optionId });
+ if (itr != _gossipMenuItemAddonStore.end())
+ return &itr->second;
+ return nullptr;
+ }
// for wintergrasp only
GraveyardContainer GraveyardStore;
@@ -1831,6 +1845,7 @@ class TC_GAME_API ObjectMgr
GossipMenusContainer _gossipMenusStore;
GossipMenuItemsContainer _gossipMenuItemsStore;
GossipMenuAddonContainer _gossipMenuAddonStore;
+ GossipMenuItemAddonContainer _gossipMenuItemAddonStore;
PointOfInterestContainer _pointsOfInterestStore;
QuestPOIContainer _questPOIStore;
diff --git a/src/server/game/Server/Packets/GarrisonPackets.cpp b/src/server/game/Server/Packets/GarrisonPackets.cpp
index 0796748d877..234ce345462 100644
--- a/src/server/game/Server/Packets/GarrisonPackets.cpp
+++ b/src/server/game/Server/Packets/GarrisonPackets.cpp
@@ -481,4 +481,13 @@ WorldPacket const* GarrisonBuildingActivated::Write()
return &_worldPacket;
}
+
+WorldPacket const* GarrisonOpenTalentNpc::Write()
+{
+ _worldPacket << NpcGUID;
+ _worldPacket << int32(GarrTalentTreeID);
+ _worldPacket << int32(FriendshipFactionID);
+
+ return &_worldPacket;
+}
}
diff --git a/src/server/game/Server/Packets/GarrisonPackets.h b/src/server/game/Server/Packets/GarrisonPackets.h
index 983982842f8..9b1367a5819 100644
--- a/src/server/game/Server/Packets/GarrisonPackets.h
+++ b/src/server/game/Server/Packets/GarrisonPackets.h
@@ -437,6 +437,18 @@ namespace WorldPackets
uint32 GarrPlotInstanceID = 0;
};
+
+ class GarrisonOpenTalentNpc final : public ServerPacket
+ {
+ public:
+ GarrisonOpenTalentNpc() : ServerPacket(SMSG_GARRISON_OPEN_TALENT_NPC, 16 + 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid NpcGUID;
+ int32 GarrTalentTreeID = 0;
+ int32 FriendshipFactionID = 0; // Always 0 except on The Deaths of Chromie Scenario
+ };
}
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 9782e06dc85..3c3226e16e8 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1330,7 +1330,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_CRAFTER, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_MISSION_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_RECRUITMENT_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_TALENT_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_TALENT_NPC, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLACE_BUILDING_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_PLACED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_REMOVED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 0a9f1a144e3..13259d7a258 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2250,8 +2250,11 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Gossip menu options...");
sObjectMgr->LoadGossipMenuItems();
- TC_LOG_INFO("server.loading", "Loading Gossip menu friendship factions...");
- sObjectMgr->LoadGossipMenuFriendshipFactions();
+ TC_LOG_INFO("server.loading", "Loading Gossip menu addon...");
+ sObjectMgr->LoadGossipMenuAddon();
+
+ TC_LOG_INFO("server.loading", "Loading Gossip menu item addon...");
+ sObjectMgr->LoadGossipMenuItemAddon();
TC_LOG_INFO("server.loading", "Loading Creature trainers...");
sObjectMgr->LoadCreatureTrainers(); // must be after LoadGossipMenuItems