28 std::unordered_map<uint32, ConversationTemplate> _conversationTemplateStore;
29 std::unordered_map<uint32, ConversationLineTemplate> _conversationLineTemplateStore;
34 _conversationLineTemplateStore.clear();
35 _conversationTemplateStore.clear();
37 std::unordered_map<uint32, std::vector<ConversationActorTemplate>> actorsByConversation;
39 if (
QueryResult lineTemplates =
WorldDatabase.Query(
"SELECT Id, UiCameraID, ActorIdx, Flags, ChatType FROM conversation_line_template"))
45 Field* fields = lineTemplates->Fetch();
51 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_line_template` has template for non existing ConversationLine (ID: {}), skipped",
id);
56 conversationLine.
Id = id;
62 while (lineTemplates->NextRow());
64 TC_LOG_INFO(
"server.loading",
">> Loaded {} Conversation line templates in {} ms", _conversationLineTemplateStore.size(),
GetMSTimeDiffToNow(oldMSTime));
68 TC_LOG_INFO(
"server.loading",
">> Loaded 0 Conversation line templates. DB table `conversation_line_template` is empty.");
71 if (
QueryResult actors =
WorldDatabase.Query(
"SELECT ConversationId, ConversationActorId, ConversationActorGuid, Idx, CreatureId, CreatureDisplayInfoId, NoActorObject, ActivePlayerObject FROM conversation_actors"))
76 struct ConversationActorDbRow
83 uint32 CreatureDisplayInfoId = 0;
89 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` references an invalid creature guid (GUID: {}) for Conversation {} and Idx {}, skipped.", SpawnId, ConversationId, ActorIndex);
94 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` with ConversationActorGuid cannot have CreatureId ({}). Conversation {} and Idx {}.",
CreatureId, ConversationId, ActorIndex);
96 if (CreatureDisplayInfoId)
97 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` with ConversationActorGuid cannot have CreatureDisplayInfoId ({}). Conversation {} and Idx {}.", CreatureDisplayInfoId, ConversationId, ActorIndex);
107 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` references an invalid creature id ({}) for Conversation {} and Idx {}, skipped.",
CreatureId, ConversationId, ActorIndex);
113 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` references an invalid creature display id ({}) for Conversation {} and Idx {}, skipped.", CreatureDisplayInfoId, ConversationId, ActorIndex);
118 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` with NoActorObject cannot have ConversationActorGuid ({}). Conversation {} and Idx {}.", SpawnId, ConversationId, ActorIndex);
128 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` with ActivePlayerObject cannot have ConversationActorGuid ({}). Conversation {} and Idx {}.", SpawnId, ConversationId, ActorIndex);
131 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` with ActivePlayerObject cannot have CreatureId ({}). Conversation {} and Idx {}.",
CreatureId, ConversationId, ActorIndex);
133 if (CreatureDisplayInfoId)
134 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` with ActivePlayerObject cannot have CreatureDisplayInfoId ({}). Conversation {} and Idx {}.", CreatureDisplayInfoId, ConversationId, ActorIndex);
143 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` references an invalid creature id ({}) for Conversation {} and Idx {}, skipped.",
CreatureId, ConversationId, ActorIndex);
149 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` references an invalid creature display id ({}) for Conversation {} and Idx {}, skipped.", CreatureDisplayInfoId, ConversationId, ActorIndex);
154 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_actors` with TalkingHead cannot have ConversationActorGuid ({}). Conversation {} and Idx {}.", SpawnId, ConversationId, ActorIndex);
164 Field* fields = actors->Fetch();
166 ConversationActorDbRow data;
168 data.ConversationId = fields[0].
GetUInt32();
173 data.CreatureDisplayInfoId = fields[5].
GetUInt32();
174 bool noActorObject = fields[6].
GetUInt8() == 1;
175 bool activePlayerObject = fields[7].
GetUInt8() == 1;
177 if (activePlayerObject)
179 else if (noActorObject)
181 else if (data.SpawnId || !data.CreatureId)
186 bool valid = std::visit(data, actor.
Data);
190 actorsByConversation[data.ConversationId].push_back(actor);
192 }
while (actors->NextRow());
198 TC_LOG_INFO(
"server.loading",
">> Loaded 0 Conversation actors. DB table `conversation_actors` is empty.");
202 std::unordered_map<uint32, uint32> prevConversationLineIds;
204 if (conversationLine->NextConversationLineID)
205 prevConversationLineIds[conversationLine->NextConversationLineID] = conversationLine->ID;
207 auto getFirstLineIdFromAnyLineId = [&](
uint32 lineId)
210 lineId = *prevLineId;
215 if (
QueryResult templates =
WorldDatabase.Query(
"SELECT Id, FirstLineId, TextureKitId, Flags, ScriptName FROM conversation_template"))
221 Field* fields = templates->Fetch();
230 conversationTemplate.
Actors = std::move(actorsByConversation[conversationTemplate.
Id]);
232 uint32 correctedFirstLineId = getFirstLineIdFromAnyLineId(conversationTemplate.
FirstLineId);
233 if (conversationTemplate.
FirstLineId != correctedFirstLineId)
235 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_template` has incorrect FirstLineId {}, it should be {} for Conversation {}, corrected",
236 conversationTemplate.
FirstLineId, correctedFirstLineId, conversationTemplate.
Id);
237 conversationTemplate.
FirstLineId = correctedFirstLineId;
241 if (!currentConversationLine)
242 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_template` references an invalid line (ID: {}) for Conversation {}, skipped", conversationTemplate.
FirstLineId, conversationTemplate.
Id);
244 while (currentConversationLine !=
nullptr)
247 conversationTemplate.
Lines.push_back(conversationLineTemplate);
249 TC_LOG_ERROR(
"sql.sql",
"Table `conversation_line_template` has missing template for line (ID: {}) in Conversation {}, skipped", currentConversationLine->
ID, conversationTemplate.
Id);
257 _conversationTemplateStore[conversationTemplate.
Id] = std::move(conversationTemplate);
259 while (templates->NextRow());
261 TC_LOG_INFO(
"server.loading",
">> Loaded {} Conversation templates in {} ms", _conversationTemplateStore.size(),
GetMSTimeDiffToNow(oldMSTime));
265 TC_LOG_INFO(
"server.loading",
">> Loaded 0 Conversation templates. DB table `conversation_template` is empty.");
DB2Storage< ConversationLineEntry > sConversationLineStore("ConversationLine.db2", &ConversationLineLoadInfo::Instance)
DB2Storage< CreatureDisplayInfoEntry > sCreatureDisplayInfoStore("CreatureDisplayInfo.db2", &CreatureDisplayInfoLoadInfo::Instance)
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
#define TC_LOG_ERROR(filterType__,...)
#define TC_LOG_INFO(filterType__,...)
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
static ConversationDataStore * Instance()
void LoadConversationTemplates()
ConversationLineTemplate const * GetConversationLineTemplate(uint32 conversationLineId) const
ConversationTemplate const * GetConversationTemplate(uint32 conversationId) const
Class used to access individual fields of database query result.
auto MapGetValuePtr(M &map, typename M::key_type const &key)
TC_PROTO_API ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::FieldOptions, ::google::protobuf::internal::MessageTypeTraits< ::bgs::protocol::FieldRestriction >, 11, false > valid
uint32 CreatureDisplayInfoId
uint32 CreatureDisplayInfoId
std::variant< ConversationActorWorldObjectTemplate, ConversationActorNoObjectTemplate, ConversationActorActivePlayerTemplate, ConversationActorTalkingHeadTemplate > Data
ObjectGuid::LowType SpawnId
uint16 NextConversationLineID
EnumFlag< ConversationFlags > Flags
std::vector< ConversationLineTemplate const * > Lines
std::vector< ConversationActorTemplate > Actors