TrinityCore
Loading...
Searching...
No Matches
CreatureTextMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "CreatureTextMgr.h"
19#include "CreatureTextMgrImpl.h"
20#include "CellImpl.h"
21#include "ChatPackets.h"
22#include "Common.h"
23#include "Containers.h"
24#include "DatabaseEnv.h"
25#include "DBCStores.h"
26#include "GridNotifiersImpl.h"
27#include "Log.h"
28#include "MiscPackets.h"
29#include "ObjectMgr.h"
30#include "World.h"
31
33{
34 public:
35 CreatureTextBuilder(WorldObject const* obj, uint8 gender, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, WorldObject const* target)
36 : _source(obj), _gender(gender), _msgType(msgtype), _textGroup(textGroup), _textId(id), _language(language), _target(target) { }
37
38 size_t operator()(WorldPacket* data, LocaleConstant locale) const
39 {
40 std::string const& text = sCreatureTextMgr->GetLocalizedChatString(_source->GetEntry(), _gender, _textGroup, _textId, locale);
41
43 packet.Initialize(_msgType, Language(_language), _source, _target, text, 0, "", locale);
44 packet.Write();
45
46 *data = packet.Move();
47
48 return packet.TargetGUIDPos;
49 }
50
51 private:
59};
60
62{
63 public:
64 PlayerTextBuilder(WorldObject const* obj, WorldObject const* speaker, uint8 gender, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, WorldObject const* target)
65 : _source(obj), _talker(speaker), _gender(gender), _msgType(msgtype), _textGroup(textGroup), _textId(id), _language(language), _target(target) { }
66
67 size_t operator()(WorldPacket* data, LocaleConstant locale) const
68 {
69 std::string const& text = sCreatureTextMgr->GetLocalizedChatString(_source->GetEntry(), _gender, _textGroup, _textId, locale);
70
72 packet.Initialize(_msgType, Language(_language), _talker, _target, text, 0, "", locale);
73 packet.Write();
74
75 *data = packet.Move();
76
77 return packet.TargetGUIDPos;
78 }
79
80 private:
89};
90
96
98{
99 uint32 oldMSTime = getMSTime();
100
101 mTextMap.clear(); // for reload case
102 //all currently used temp texts are NOT reset
103
105 PreparedQueryResult result = WorldDatabase.Query(stmt);
106
107 if (!result)
108 {
109 TC_LOG_INFO("server.loading", ">> Loaded 0 ceature texts. DB table `creature_text` is empty.");
110
111 return;
112 }
113
114 uint32 textCount = 0;
115
116 do
117 {
118 Field* fields = result->Fetch();
120
121 temp.creatureId = fields[0].GetUInt32();
122 temp.groupId = fields[1].GetUInt8();
123 temp.id = fields[2].GetUInt8();
124 temp.text = fields[3].GetString();
125 temp.type = ChatMsg(fields[4].GetUInt8());
126 temp.lang = Language(fields[5].GetUInt8());
127 temp.probability = fields[6].GetFloat();
128 temp.emote = Emote(fields[7].GetUInt32());
129 temp.duration = fields[8].GetUInt32();
130 temp.sound = fields[9].GetUInt32();
131 temp.BroadcastTextId = fields[10].GetUInt32();
132 temp.TextRange = CreatureTextRange(fields[11].GetUInt8());
133
134 if (temp.sound)
135 {
136 if (!sSoundEntriesStore.LookupEntry(temp.sound))
137 {
138 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry {}, Group {} in table `creature_text` has Sound {} but sound does not exist.", temp.creatureId, temp.groupId, temp.sound);
139 temp.sound = 0;
140 }
141 }
142
143 if (!GetLanguageDescByID(temp.lang))
144 {
145 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry {}, Group {} in table `creature_text` using Language {} but Language does not exist.", temp.creatureId, temp.groupId, uint32(temp.lang));
146 temp.lang = LANG_UNIVERSAL;
147 }
148
149 if (temp.type >= MAX_CHAT_MSG_TYPE)
150 {
151 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry {}, Group {} in table `creature_text` has Type {} but this Chat Type does not exist.", temp.creatureId, temp.groupId, uint32(temp.type));
152 temp.type = CHAT_MSG_SAY;
153 }
154
155 if (temp.emote)
156 {
157 if (!sEmotesStore.LookupEntry(temp.emote))
158 {
159 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry {}, Group {} in table `creature_text` has Emote {} but emote does not exist.", temp.creatureId, temp.groupId, uint32(temp.emote));
161 }
162 }
163
164 if (temp.BroadcastTextId)
165 {
166 if (!sObjectMgr->GetBroadcastText(temp.BroadcastTextId))
167 {
168 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry {}, Group {}, Id {} in table `creature_text` has non-existing or incompatible BroadcastTextId {}.", temp.creatureId, temp.groupId, temp.id, temp.BroadcastTextId);
169 temp.BroadcastTextId = 0;
170 }
171 }
172
173 if (temp.TextRange > TEXT_RANGE_WORLD)
174 {
175 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry {}, Group {}, Id {} in table `creature_text` has incorrect TextRange {}.", temp.creatureId, temp.groupId, temp.id, temp.TextRange);
177 }
178
179 // add the text into our entry's group
180 mTextMap[temp.creatureId][temp.groupId].push_back(temp);
181
182 ++textCount;
183 }
184 while (result->NextRow());
185
186 TC_LOG_INFO("server.loading", ">> Loaded {} creature texts for {} creatures in {} ms", textCount, mTextMap.size(), GetMSTimeDiffToNow(oldMSTime));
187}
188
190{
191 uint32 oldMSTime = getMSTime();
192
193 mLocaleTextMap.clear(); // for reload case
194
195 // 0 1 2 3 4
196 QueryResult result = WorldDatabase.Query("SELECT CreatureID, GroupID, ID, Locale, Text FROM creature_text_locale");
197
198 if (!result)
199 return;
200
201 do
202 {
203 Field* fields = result->Fetch();
204
205 uint32 creatureId = fields[0].GetUInt32();
206 uint32 groupId = fields[1].GetUInt8();
207 uint32 id = fields[2].GetUInt8();
208 std::string localeName = fields[3].GetString();
209
210 LocaleConstant locale = GetLocaleByName(localeName);
211 if (locale == LOCALE_enUS)
212 continue;
213
214 CreatureTextLocale& data = mLocaleTextMap[CreatureTextId(creatureId, groupId, id)];
215 ObjectMgr::AddLocaleString(fields[4].GetString(), locale, data.Text);
216 } while (result->NextRow());
217
218 TC_LOG_INFO("server.loading", ">> Loaded {} creature localized texts in {} ms", uint32(mLocaleTextMap.size()), GetMSTimeDiffToNow(oldMSTime));
219}
220
221uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject const* whisperTarget /*= nullptr*/, ChatMsg msgType /*= CHAT_MSG_ADDON*/, Language language /*= LANG_ADDON*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/, uint32 sound /*= 0*/, Team team /*= TEAM_OTHER*/, bool gmOnly /*= false*/, Player* srcPlr /*= nullptr*/)
222{
223 if (!source)
224 return 0;
225
226 CreatureTextMap::const_iterator sList = mTextMap.find(source->GetEntry());
227 if (sList == mTextMap.end())
228 {
229 TC_LOG_ERROR("sql.sql.creaturetextmgr", "CreatureTextMgr: Could not find Text for Creature {} ({}) in 'creature_text' table. Ignoring.", source->GetName(), source->GetGUID().ToString());
230 return 0;
231 }
232
233 CreatureTextHolder const& textHolder = sList->second;
234 CreatureTextHolder::const_iterator itr = textHolder.find(textGroup);
235 if (itr == textHolder.end())
236 {
237 TC_LOG_ERROR("sql.sql.creaturetextmgr", "CreatureTextMgr: Could not find TextGroup {} for Creature {} ({}) in 'creature_text' table. Ignoring.", uint32(textGroup), source->GetName(), source->GetGUID().ToString());
238 return 0;
239 }
240
241 CreatureTextGroup const& textGroupContainer = itr->second; //has all texts in the group
242 CreatureTextRepeatIds repeatGroup = source->GetTextRepeatGroup(textGroup);//has all textIDs from the group that were already said
243 CreatureTextGroup tempGroup;//will use this to talk after sorting repeatGroup
244
245 for (CreatureTextGroup::const_iterator giter = textGroupContainer.begin(); giter != textGroupContainer.end(); ++giter)
246 if (std::find(repeatGroup.begin(), repeatGroup.end(), giter->id) == repeatGroup.end())
247 tempGroup.push_back(*giter);
248
249 if (tempGroup.empty())
250 {
251 source->ClearTextRepeatGroup(textGroup);
252 tempGroup = textGroupContainer;
253 }
254
255 auto iter = Trinity::Containers::SelectRandomWeightedContainerElement(tempGroup, [](CreatureTextEntry const& t) -> double
256 {
257 return t.probability;
258 });
259
260 ChatMsg finalType = (msgType == CHAT_MSG_ADDON) ? iter->type : msgType;
261 Language finalLang = (language == LANG_ADDON) ? iter->lang : language;
262 uint32 finalSound = sound ? sound : iter->sound;
263
264 if (range == TEXT_RANGE_NORMAL)
265 range = iter->TextRange;
266
267 if (finalSound)
268 SendSound(source, finalSound, finalType, whisperTarget, range, team, gmOnly);
269
270 Unit* finalSource = source;
271 if (srcPlr)
272 finalSource = srcPlr;
273
274 if (iter->emote)
275 SendEmote(finalSource, iter->emote);
276
277 if (srcPlr)
278 {
279 PlayerTextBuilder builder(source, finalSource, finalSource->GetGender(), finalType, iter->groupId, iter->id, finalLang, whisperTarget);
280 SendChatPacket(finalSource, builder, finalType, whisperTarget, range, team, gmOnly);
281 }
282 else
283 {
284 CreatureTextBuilder builder(finalSource, finalSource->GetGender(), finalType, iter->groupId, iter->id, finalLang, whisperTarget);
285 SendChatPacket(finalSource, builder, finalType, whisperTarget, range, team, gmOnly);
286 }
287
288 source->SetTextRepeatId(textGroup, iter->id);
289 return iter->duration;
290}
291
293{
294 float dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY);
295 switch (msgType)
296 {
298 dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL);
299 break;
302 dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE);
303 break;
304 default:
305 break;
306 }
307
308 return dist;
309}
310
311void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType, WorldObject const* whisperTarget /*= nullptr*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/, Team team /*= TEAM_OTHER*/, bool gmOnly /*= false*/)
312{
313 if (!sound || !source)
314 return;
315
316 SendNonChatPacket(source, WorldPackets::Misc::PlaySound(sound).Write(), msgType, whisperTarget, range, team, gmOnly);
317}
318
319void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket const* data, ChatMsg msgType, WorldObject const* whisperTarget, CreatureTextRange range, Team team, bool gmOnly)
320{
321 switch (msgType)
322 {
324 {
325 if (!whisperTarget)
326 return;
327
328 if (Player const* whisperPlayer = whisperTarget->ToPlayer())
329 {
330 if (Group const* group = whisperPlayer->GetGroup())
331 group->BroadcastWorker([data](Player* player) { player->SendDirectMessage(data); });
332 }
333 return;
334 }
337 {
338 if (range == TEXT_RANGE_NORMAL) // ignores team and gmOnly
339 {
340 if (!whisperTarget || whisperTarget->GetTypeId() != TYPEID_PLAYER)
341 return;
342
343 whisperTarget->ToPlayer()->SendDirectMessage(data);
344 return;
345 }
346 break;
347 }
348 default:
349 break;
350 }
351
352 switch (range)
353 {
354 case TEXT_RANGE_AREA:
355 {
356 uint32 areaId = source->GetAreaId();
357 Map::PlayerList const& players = source->GetMap()->GetPlayers();
358 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
359 if (itr->GetSource()->GetAreaId() == areaId && (!team || Team(itr->GetSource()->GetTeam()) == team) && (!gmOnly || itr->GetSource()->IsGameMaster()))
360 itr->GetSource()->SendDirectMessage(data);
361 return;
362 }
363 case TEXT_RANGE_ZONE:
364 {
365 uint32 zoneId = source->GetZoneId();
366 Map::PlayerList const& players = source->GetMap()->GetPlayers();
367 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
368 if (itr->GetSource()->GetZoneId() == zoneId && (!team || Team(itr->GetSource()->GetTeam()) == team) && (!gmOnly || itr->GetSource()->IsGameMaster()))
369 itr->GetSource()->SendDirectMessage(data);
370 return;
371 }
372 case TEXT_RANGE_MAP:
373 {
374 Map::PlayerList const& players = source->GetMap()->GetPlayers();
375 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
376 if ((!team || Team(itr->GetSource()->GetTeam()) == team) && (!gmOnly || itr->GetSource()->IsGameMaster()))
377 itr->GetSource()->SendDirectMessage(data);
378 return;
379 }
380 case TEXT_RANGE_WORLD:
381 {
382 SessionMap const& smap = sWorld->GetAllSessions();
383 for (SessionMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter)
384 if (Player* player = iter->second->GetPlayer())
385 if ((!team || Team(player->GetTeam()) == team) && (!gmOnly || player->IsGameMaster()))
386 player->SendDirectMessage(data);
387 return;
388 }
390 default:
391 break;
392 }
393
394 float dist = GetRangeForChatType(msgType);
395 source->SendMessageToSetInRange(data, dist, true);
396}
397
399{
400 if (!source)
401 return;
402
403 source->HandleEmoteCommand(emote);
404}
405
406bool CreatureTextMgr::TextExist(uint32 sourceEntry, uint8 textGroup) const
407{
408 if (!sourceEntry)
409 return false;
410
411 CreatureTextMap::const_iterator sList = mTextMap.find(sourceEntry);
412 if (sList == mTextMap.end())
413 {
414 TC_LOG_DEBUG("entities.unit", "CreatureTextMgr::TextExist: Could not find Text for Creature (entry {}) in 'creature_text' table.", sourceEntry);
415 return false;
416 }
417
418 CreatureTextHolder const& textHolder = sList->second;
419 CreatureTextHolder::const_iterator itr = textHolder.find(textGroup);
420 if (itr == textHolder.end())
421 {
422 TC_LOG_DEBUG("entities.unit", "CreatureTextMgr::TextExist: Could not find TextGroup {} for Creature (entry {}).", uint32(textGroup), sourceEntry);
423 return false;
424 }
425
426 return true;
427}
428
429std::string CreatureTextMgr::GetLocalizedChatString(uint32 entry, uint8 gender, uint8 textGroup, uint32 id, LocaleConstant locale) const
430{
431 CreatureTextMap::const_iterator mapitr = mTextMap.find(entry);
432 if (mapitr == mTextMap.end())
433 return "";
434
435 CreatureTextHolder::const_iterator holderItr = mapitr->second.find(textGroup);
436 if (holderItr == mapitr->second.end())
437 return "";
438
439 CreatureTextGroup::const_iterator groupItr = holderItr->second.begin();
440 for (; groupItr != holderItr->second.end(); ++groupItr)
441 if (groupItr->id == id)
442 break;
443
444 if (groupItr == holderItr->second.end())
445 return "";
446
447 if (locale > MAX_LOCALES)
448 locale = DEFAULT_LOCALE;
449
450 std::string baseText = "";
451 BroadcastTextEntry const* bct = sObjectMgr->GetBroadcastText(groupItr->BroadcastTextId);
452
453 if (bct)
454 baseText = bct->GetText(locale, gender);
455 else
456 baseText = groupItr->text;
457
458 if (locale != DEFAULT_LOCALE && !bct)
459 {
460 LocaleCreatureTextMap::const_iterator locItr = mLocaleTextMap.find(CreatureTextId(entry, uint32(textGroup), id));
461 if (locItr != mLocaleTextMap.end())
462 ObjectMgr::GetLocaleString(locItr->second.Text, locale, baseText);
463 }
464
465 return baseText;
466}
LocaleConstant GetLocaleByName(const std::string &name)
Definition Common.cpp:33
LocaleConstant
Definition Common.h:48
@ LOCALE_enUS
Definition Common.h:49
#define DEFAULT_LOCALE
Definition Common.h:62
#define MAX_LOCALES
Definition Common.h:64
#define sCreatureTextMgr
std::vector< CreatureTextEntry > CreatureTextGroup
std::unordered_map< uint8, CreatureTextGroup > CreatureTextHolder
CreatureTextRange
@ TEXT_RANGE_ZONE
@ TEXT_RANGE_AREA
@ TEXT_RANGE_WORLD
@ TEXT_RANGE_NORMAL
@ TEXT_RANGE_MAP
std::vector< uint8 > CreatureTextRepeatIds
Definition Creature.h:67
DBCStorage< SoundEntriesEntry > sSoundEntriesStore(SoundEntriesfmt)
DBCStorage< EmotesEntry > sEmotesStore(EmotesEntryfmt)
std::shared_ptr< ResultSet > QueryResult
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition Log.h:159
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
LanguageDesc const * GetLanguageDescByID(uint32 lang)
#define sObjectMgr
Definition ObjectMgr.h:1721
Language
@ LANG_UNIVERSAL
@ LANG_ADDON
@ EMOTE_ONESHOT_NONE
ChatMsg
@ CHAT_MSG_MONSTER_WHISPER
@ CHAT_MSG_SAY
@ CHAT_MSG_RAID_BOSS_WHISPER
@ CHAT_MSG_MONSTER_PARTY
@ CHAT_MSG_RAID_BOSS_EMOTE
@ CHAT_MSG_MONSTER_EMOTE
@ MAX_CHAT_MSG_TYPE
@ CHAT_MSG_ADDON
@ CHAT_MSG_MONSTER_YELL
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
@ WORLD_SEL_CREATURE_TEXT
WorldObject const * _target
CreatureTextBuilder(WorldObject const *obj, uint8 gender, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, WorldObject const *target)
WorldObject const * _source
size_t operator()(WorldPacket *data, LocaleConstant locale) const
LocaleCreatureTextMap mLocaleTextMap
std::string GetLocalizedChatString(uint32 entry, uint8 gender, uint8 textGroup, uint32 id, LocaleConstant locale) const
static void SendChatPacket(WorldObject *source, Builder const &builder, ChatMsg msgType, WorldObject const *whisperTarget=nullptr, CreatureTextRange range=TEXT_RANGE_NORMAL, Team team=TEAM_OTHER, bool gmOnly=false)
bool TextExist(uint32 sourceEntry, uint8 textGroup) const
static float GetRangeForChatType(ChatMsg msgType)
static void SendEmote(Unit *source, Emote emote)
static CreatureTextMgr * instance()
uint32 SendChat(Creature *source, uint8 textGroup, WorldObject const *whisperTarget=nullptr, ChatMsg msgType=CHAT_MSG_ADDON, Language language=LANG_ADDON, CreatureTextRange range=TEXT_RANGE_NORMAL, uint32 sound=0, Team team=TEAM_OTHER, bool gmOnly=false, Player *srcPlr=nullptr)
CreatureTextMap mTextMap
static void SendNonChatPacket(WorldObject *source, WorldPacket const *data, ChatMsg msgType, WorldObject const *whisperTarget, CreatureTextRange range, Team team, bool gmOnly)
static void SendSound(Creature *source, uint32 sound, ChatMsg msgType, WorldObject const *whisperTarget=nullptr, CreatureTextRange range=TEXT_RANGE_NORMAL, Team team=TEAM_OTHER, bool gmOnly=false)
CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup)
void SetTextRepeatId(uint8 textGroup, uint8 id)
void ClearTextRepeatGroup(uint8 textGroup)
Class used to access individual fields of database query result.
Definition Field.h:92
uint8 GetUInt8() const
Definition Field.cpp:29
std::string GetString() const
Definition Field.cpp:125
float GetFloat() const
Definition Field.cpp:93
uint32 GetUInt32() const
Definition Field.cpp:61
Definition Group.h:165
iterator end()
iterator begin()
PlayerList const & GetPlayers() const
Definition Map.h:468
std::string ToString() const
static std::string_view GetLocaleString(std::vector< std::string > const &data, LocaleConstant locale)
Definition ObjectMgr.h:1519
static void AddLocaleString(std::string &&value, LocaleConstant localeConstant, std::vector< std::string > &data)
TypeID GetTypeId() const
Definition Object.h:93
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:183
PlayerTextBuilder(WorldObject const *obj, WorldObject const *speaker, uint8 gender, ChatMsg msgtype, uint8 textGroup, uint32 id, uint32 language, WorldObject const *target)
WorldObject const * _talker
size_t operator()(WorldPacket *data, LocaleConstant locale) const
WorldObject const * _source
WorldObject const * _target
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6163
Definition Unit.h:783
Gender GetGender() const
Definition Unit.h:912
void HandleEmoteCommand(Emote emoteId)
Definition Unit.cpp:1579
Map * GetMap() const
Definition Object.h:451
std::string const & GetName() const
Definition Object.h:384
uint32 GetAreaId() const
Definition Object.h:376
virtual void SendMessageToSetInRange(WorldPacket const *data, float dist, bool self) const
Definition Object.cpp:1790
uint32 GetZoneId() const
Definition Object.h:375
void Initialize(ChatMsg chatType, Language language, WorldObject const *sender, WorldObject const *receiver, std::string_view message, uint32 achievementId=0, std::string_view channelName="", LocaleConstant locale=DEFAULT_LOCALE, std::string_view addonPrefix="")
WorldPacket const * Write() override
WorldPacket && Move()
Definition Packet.h:53
#define sWorld
Definition World.h:901
std::unordered_map< uint32, WorldSession * > SessionMap
Definition World.h:554
@ CONFIG_LISTEN_RANGE_YELL
Definition World.h:192
@ CONFIG_LISTEN_RANGE_SAY
Definition World.h:190
@ CONFIG_LISTEN_RANGE_TEXTEMOTE
Definition World.h:191
auto SelectRandomWeightedContainerElement(C const &container, std::vector< double > weights) -> decltype(std::begin(container))
Definition Containers.h:125
std::string const & GetText(LocaleConstant locale=DEFAULT_LOCALE, uint8 gender=GENDER_MALE, bool forceGender=false) const
Definition ObjectMgr.h:490
CreatureTextRange TextRange
std::vector< std::string > Text