aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorForesterDev <forester.manv@gmail.com>2017-10-29 13:15:22 +0400
committerAokromes <Aokromes@users.noreply.github.com>2017-10-29 10:15:22 +0100
commita64d1ec51eb11fd01a26d08a09de3d8d7dd89675 (patch)
treed596fc0956ea1ff59493d5f41d9a789a73be733f /src
parentbbd339370ed2eea5f12e79a977fd9e0e93543101 (diff)
Core/Quests: implement Quest Greeting (DB table quest_greeting)
* Core/Quests: implement Quest Greetings. Partial port https://github.com/TrinityCore/TrinityCore/commit/22e230ecec1c7ce4eb4daeb60adfa03098271f34
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Accounts/RBAC.h3
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp42
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp128
-rw-r--r--src/server/game/Globals/ObjectMgr.h30
-rw-r--r--src/server/game/World/World.cpp4
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp20
6 files changed, 214 insertions, 13 deletions
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 05747f96739..0f8e031ba20 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -748,7 +748,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_SERVER_RESTART_FORCE = 840,
RBAC_PERM_COMMAND_NEARGRAVEYARD = 841,
RBAC_PERM_COMMAND_RELOAD_CHARACTER_TEMPLATE = 842, // not on 3.3.5a
- RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING = 843, // not on 3.3.5a
+ RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING = 843,
RBAC_PERM_COMMAND_SCENE = 844, // not on 3.3.5a
RBAC_PERM_COMMAND_SCENE_DEBUG = 845, // not on 3.3.5a
RBAC_PERM_COMMAND_SCENE_PLAY = 846, // not on 3.3.5a
@@ -772,6 +772,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_GROUP_MAINASSIST = 864,
RBAC_PERM_COMMAND_NPC_SHOWLOOT = 865,
RBAC_PERM_COMMAND_LIST_SPAWNPOINTS = 866,
+ RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING_LOCALE = 867,
// custom permissions 1000+
RBAC_PERM_MAX
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index caa700f6672..4a39c233fc2 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -323,16 +323,33 @@ void QuestMenu::ClearMenu()
_questMenuItems.clear();
}
-void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string& Title, ObjectGuid npcGUID)
+void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string& Title, ObjectGuid guid)
{
WorldPacket data(SMSG_QUESTGIVER_QUEST_LIST, 100); // guess size
- data << uint64(npcGUID);
- data << Title;
- data << uint32(eEmote._Delay); // player emote
- data << uint32(eEmote._Emote); // NPC emote
+ data << uint64(guid);
+
+ if (QuestGreeting const* questGreeting = sObjectMgr->GetQuestGreeting(guid))
+ {
+ std::string strGreeting = questGreeting->greeting;
+
+ LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
+ if (localeConstant != LOCALE_enUS)
+ if (QuestGreetingLocale const* questGreetingLocale = sObjectMgr->GetQuestGreetingLocale(MAKE_PAIR32(guid.GetEntry(), guid.GetTypeId())))
+ ObjectMgr::GetLocaleString(questGreetingLocale->greeting, localeConstant, strGreeting);
+
+ data << strGreeting;
+ data << uint32(questGreeting->greetEmoteDelay);
+ data << uint32(questGreeting->greetEmoteType);
+ }
+ else
+ {
+ data << Title;
+ data << uint32(eEmote._Delay); // player emote
+ data << uint32(eEmote._Emote); // NPC emote
+ }
size_t count_pos = data.wpos();
- data << uint8 (0);
+ data << uint8(0);
uint32 count = 0;
// Store this instead of checking the Singleton every loop iteration
@@ -340,9 +357,9 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
for (uint32 i = 0; i < _questMenu.GetMenuItemCount(); ++i)
{
- QuestMenuItem const& qmi = _questMenu.GetItem(i);
+ QuestMenuItem const& questMenuItem = _questMenu.GetItem(i);
- uint32 questID = qmi.QuestId;
+ uint32 questID = questMenuItem.QuestId;
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questID))
{
@@ -351,14 +368,14 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
if (localeConstant != LOCALE_enUS)
- if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(questID))
- ObjectMgr::GetLocaleString(localeData->Title, localeConstant, title);
+ if (QuestLocale const* questTemplateLocaleData = sObjectMgr->GetQuestLocale(questID))
+ ObjectMgr::GetLocaleString(questTemplateLocaleData->Title, localeConstant, title);
if (questLevelInTitle)
Quest::AddQuestLevelToTitle(title, quest->GetQuestLevel());
data << uint32(questID);
- data << uint32(qmi.QuestIcon);
+ data << uint32(questMenuItem.QuestIcon);
data << int32(quest->GetQuestLevel());
data << uint32(quest->GetFlags()); // 3.3.3 quest flags
data << uint8(0); // 3.3.3 changes icon: blue question or yellow exclamation
@@ -368,7 +385,8 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
data.put<uint8>(count_pos, count);
_session->SendPacket(&data);
- TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC=%s", npcGUID.ToString().c_str());
+
+ TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST (QuestGiver: %s)", guid.ToString().c_str());
}
void PlayerMenu::SendQuestGiverStatus(uint8 questStatus, ObjectGuid npcGUID) const
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 974916a66fe..c7e083a66ee 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -5982,6 +5982,134 @@ void ObjectMgr::LoadQuestAreaTriggers()
TC_LOG_INFO("server.loading", ">> Loaded %u quest trigger points in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+QuestGreeting const* ObjectMgr::GetQuestGreeting(ObjectGuid guid) const
+{
+ auto itr = _questGreetingStore.find(guid.GetTypeId());
+ if (itr == _questGreetingStore.end())
+ return nullptr;
+
+ auto questItr = itr->second.find(guid.GetEntry());
+ if (questItr == itr->second.end())
+ return nullptr;
+
+ return questItr->second;
+}
+
+void ObjectMgr::LoadQuestGreetings()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _questGreetingStore.clear(); // need for reload case
+
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT ID, Type, GreetEmoteType, GreetEmoteDelay, Greeting FROM quest_greeting");
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quest greetings. DB table `quest_greeting` is empty.");
+ return;
+ }
+
+ _questGreetingStore.rehash(result->GetRowCount());
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 id = fields[0].GetUInt32();
+ uint8 type = fields[1].GetUInt8();
+ // overwrite
+ switch (type)
+ {
+ case 0: // Creature
+ type = TYPEID_UNIT;
+ if (!sObjectMgr->GetCreatureTemplate(id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `quest_greeting`: creature template (entry: %u) does not exist.", id);
+ continue;
+ }
+ break;
+ case 1: // GameObject
+ type = TYPEID_GAMEOBJECT;
+ if (!sObjectMgr->GetGameObjectTemplate(id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `quest_greeting`: gameobject template (entry: %u) does not exist.", id);
+ continue;
+ }
+ break;
+ default:
+ TC_LOG_ERROR("sql.sql", "Table `quest_greeting`: unknown type = %u for entry = %u. Skipped.", type, id);
+ continue;
+ }
+
+ uint16 greetEmoteType = fields[2].GetUInt16();
+
+ if (greetEmoteType > 0 && !sEmotesStore.LookupEntry(greetEmoteType))
+ {
+ TC_LOG_DEBUG("sql.sql", "Table `quest_greeting`: entry %u has greetEmoteType = %u but emote does not exist. Set to 0.", id, greetEmoteType);
+ greetEmoteType = 0;
+ }
+
+ uint32 greetEmoteDelay = fields[3].GetUInt32();
+ std::string greeting = fields[4].GetString();
+
+ _questGreetingStore[type][id] = new QuestGreeting(greetEmoteType, greetEmoteDelay, greeting);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u quest_greeting in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ObjectMgr::LoadQuestGreetingsLocales()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _questGreetingLocaleStore.clear(); // need for reload case
+
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT ID, Type, Locale, Greeting FROM quest_greeting_locale");
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quest_greeting locales. DB table `quest_greeting_locale` is empty.");
+ return;
+ }
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 id = fields[0].GetUInt32();
+ uint8 type = fields[1].GetUInt8();
+ // overwrite
+ switch (type)
+ {
+ case 0: // Creature
+ type = TYPEID_UNIT;
+ break;
+ case 1: // GameObject
+ type = TYPEID_GAMEOBJECT;
+ break;
+ default:
+ break;
+ }
+
+ std::string localeName = fields[2].GetString();
+ std::string greeting = fields[3].GetString();
+
+ QuestGreetingLocale& data = _questGreetingLocaleStore[MAKE_PAIR32(id, type)];
+ LocaleConstant locale = GetLocaleByName(localeName);
+ if (locale == LOCALE_enUS)
+ continue;
+
+ AddLocaleString(greeting, locale, data.greeting);
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u quest greeting locale strings in %u ms", uint32(_questGreetingLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime));
+}
+
void ObjectMgr::LoadTavernAreaTriggers()
{
uint32 oldMSTime = getMSTime();
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 3f52a2f77a6..8a07723a34e 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -532,6 +532,11 @@ struct TrinityString
std::vector<std::string> Content;
};
+struct QuestGreetingLocale
+{
+ std::vector<std::string> greeting;
+};
+
typedef std::map<ObjectGuid, ObjectGuid> LinkedRespawnContainer;
typedef std::unordered_map<uint32, CreatureTemplate> CreatureTemplateContainer;
typedef std::unordered_map<uint32, CreatureAddon> CreatureTemplateAddonContainer;
@@ -574,6 +579,7 @@ struct PointOfInterestLocale
};
typedef std::unordered_map<uint32, PointOfInterestLocale> PointOfInterestLocaleContainer;
+typedef std::unordered_map<uint32, QuestGreetingLocale> QuestGreetingLocaleContainer;
typedef std::unordered_map<uint32, TrinityString> TrinityStringContainer;
@@ -794,6 +800,19 @@ struct QuestPOIWrapper
typedef std::unordered_map<uint32, QuestPOIWrapper> QuestPOIContainer;
+struct QuestGreeting
+{
+ uint16 greetEmoteType;
+ uint32 greetEmoteDelay;
+ std::string greeting;
+
+ QuestGreeting() : greetEmoteType(0), greetEmoteDelay(0) { }
+ QuestGreeting(uint16 _greetEmoteType, uint32 _greetEmoteDelay, std::string _greeting)
+ : greetEmoteType(_greetEmoteType), greetEmoteDelay(_greetEmoteDelay), greeting(_greeting) { }
+};
+
+typedef std::unordered_map<uint8, std::unordered_map<uint32, QuestGreeting const*>> QuestGreetingContainer;
+
struct GraveyardData
{
uint32 safeLocId;
@@ -998,6 +1017,7 @@ class TC_GAME_API ObjectMgr
}
GossipText const* GetGossipText(uint32 Text_ID) const;
+ QuestGreeting const* GetQuestGreeting(ObjectGuid guid) const;
WorldSafeLocsEntry const* GetDefaultGraveyard(uint32 team) const;
WorldSafeLocsEntry const* GetClosestGraveyard(float x, float y, float z, uint32 MapId, uint32 team) const;
@@ -1155,6 +1175,7 @@ class TC_GAME_API ObjectMgr
void LoadPageTextLocales();
void LoadGossipMenuItemsLocales();
void LoadPointOfInterestLocales();
+ void LoadQuestGreetingsLocales();
void LoadInstanceTemplate();
void LoadInstanceEncounters();
void LoadMailLevelRewards();
@@ -1166,6 +1187,7 @@ class TC_GAME_API ObjectMgr
void LoadAreaTriggerTeleports();
void LoadAccessRequirements();
void LoadQuestAreaTriggers();
+ void LoadQuestGreetings();
void LoadAreaTriggerScripts();
void LoadTavernAreaTriggers();
void LoadGameObjectForQuests();
@@ -1374,6 +1396,12 @@ class TC_GAME_API ObjectMgr
if (itr == _pointOfInterestLocaleStore.end()) return nullptr;
return &itr->second;
}
+ QuestGreetingLocale const* GetQuestGreetingLocale(uint32 id) const
+ {
+ QuestGreetingLocaleContainer::const_iterator itr = _questGreetingLocaleStore.find(id);
+ if (itr == _questGreetingLocaleStore.end()) return nullptr;
+ return &itr->second;
+ }
TrinityString const* GetTrinityString(uint32 entry) const
{
@@ -1527,6 +1555,7 @@ class TC_GAME_API ObjectMgr
TavernAreaTriggerContainer _tavernAreaTriggerStore;
GameObjectForQuestContainer _gameObjectForQuestStore;
GossipTextContainer _gossipTextStore;
+ QuestGreetingContainer _questGreetingStore;
AreaTriggerContainer _areaTriggerStore;
AreaTriggerScriptContainer _areaTriggerScriptStore;
AccessRequirementContainer _accessRequirementStore;
@@ -1637,6 +1666,7 @@ class TC_GAME_API ObjectMgr
PageTextLocaleContainer _pageTextLocaleStore;
GossipMenuItemsLocaleContainer _gossipMenuItemsLocaleStore;
PointOfInterestLocaleContainer _pointOfInterestLocaleStore;
+ QuestGreetingLocaleContainer _questGreetingLocaleStore;
TrinityStringContainer _trinityStringStore;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index f4e1a7b2d74..7e34a4ae91f 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1611,6 +1611,7 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadPageTextLocales();
sObjectMgr->LoadGossipMenuItemsLocales();
sObjectMgr->LoadPointOfInterestLocales();
+ sObjectMgr->LoadQuestGreetingsLocales();
sObjectMgr->SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
TC_LOG_INFO("server.loading", ">> Localization strings loaded in %u ms", GetMSTimeDiffToNow(oldMSTime));
@@ -1762,6 +1763,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Quests Starters and Enders...");
sObjectMgr->LoadQuestStartersAndEnders(); // must be after quest load
+ TC_LOG_INFO("server.loading", "Loading Quests Greetings...");
+ sObjectMgr->LoadQuestGreetings(); // must be loaded after creature_template, gameobject_template tables
+
TC_LOG_INFO("server.loading", "Loading Objects Pooling Data...");
sPoolMgr->LoadFromDB();
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index faeb77cccec..d40d67fc859 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -129,6 +129,8 @@ public:
{ "pickpocketing_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_PICKPOCKETING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesPickpocketingCommand, "" },
{ "points_of_interest", rbac::RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST, true, &HandleReloadPointsOfInterestCommand, "" },
{ "prospecting_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_PROSPECTING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesProspectingCommand, "" },
+ { "quest_greeting", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING, true, &HandleReloadQuestGreetingCommand, "" },
+ { "quest_greeting_locale", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING_LOCALE, true, &HandleReloadLocalesQuestGreetingCommand, "" },
{ "quest_poi", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_POI, true, &HandleReloadQuestPOICommand, "" },
{ "quest_template", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE, true, &HandleReloadQuestTemplateCommand, "" },
{ "rbac", rbac::RBAC_PERM_COMMAND_RELOAD_RBAC, true, &HandleReloadRBACCommand, "" },
@@ -243,6 +245,7 @@ public:
static bool HandleReloadAllQuestCommand(ChatHandler* handler, char const* /*args*/)
{
+ HandleReloadQuestGreetingCommand(handler, "");
HandleReloadQuestAreaTriggersCommand(handler, "a");
HandleReloadQuestPOICommand(handler, "a");
HandleReloadQuestTemplateCommand(handler, "a");
@@ -317,6 +320,7 @@ public:
HandleReloadLocalesPageTextCommand(handler, "a");
HandleReloadLocalesPointsOfInterestCommand(handler, "a");
HandleReloadLocalesQuestCommand(handler, "a");
+ HandleReloadLocalesQuestGreetingCommand(handler, "");
return true;
}
@@ -523,6 +527,22 @@ public:
return true;
}
+ static bool HandleReloadQuestGreetingCommand(ChatHandler* handler, char const* /*args*/)
+ {
+ TC_LOG_INFO("misc", "Re-Loading Quest Greeting ...");
+ sObjectMgr->LoadQuestGreetings();
+ handler->SendGlobalGMSysMessage("DB table `quest_greeting` reloaded.");
+ return true;
+ }
+
+ static bool HandleReloadLocalesQuestGreetingCommand(ChatHandler* handler, char const* /*args*/)
+ {
+ TC_LOG_INFO("misc", "Re-Loading Quest Greeting locales...");
+ sObjectMgr->LoadQuestGreetingsLocales();
+ handler->SendGlobalGMSysMessage("DB table `quest_greeting_locale` reloaded.");
+ return true;
+ }
+
static bool HandleReloadQuestTemplateCommand(ChatHandler* handler, char const* /*args*/)
{
TC_LOG_INFO("misc", "Re-Loading Quest Templates...");