TrinityCore
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 "Chat.h"
22#include "ChatTextBuilder.h"
23#include "Common.h"
24#include "Containers.h"
25#include "DatabaseEnv.h"
26#include "DB2Stores.h"
27#include "GridNotifiersImpl.h"
28#include "LanguageMgr.h"
29#include "Log.h"
30#include "MiscPackets.h"
31#include "ObjectMgr.h"
32#include "World.h"
33
36
38{
40 return &instance;
41}
42
44{
45 uint32 oldMSTime = getMSTime();
46
47 mTextMap.clear(); // for reload case
48 //all currently used temp texts are NOT reset
49
51 PreparedQueryResult result = WorldDatabase.Query(stmt);
52
53 if (!result)
54 {
55 TC_LOG_INFO("server.loading", ">> Loaded 0 ceature texts. DB table `creature_text` is empty.");
56
57 return;
58 }
59
60 uint32 textCount = 0;
61
62 do
63 {
64 Field* fields = result->Fetch();
66
67 temp.creatureId = fields[0].GetUInt32();
68 temp.groupId = fields[1].GetUInt8();
69 temp.id = fields[2].GetUInt8();
70 temp.text = fields[3].GetString();
71 temp.type = ChatMsg(fields[4].GetUInt8());
72 temp.lang = Language(fields[5].GetUInt8());
73 temp.probability = fields[6].GetFloat();
74 temp.emote = Emote(fields[7].GetUInt32());
75 temp.duration = fields[8].GetUInt32();
76 temp.sound = fields[9].GetUInt32();
77 temp.SoundPlayType = SoundKitPlayType(fields[10].GetUInt8());
78 temp.BroadcastTextId = fields[11].GetUInt32();
79 temp.TextRange = CreatureTextRange(fields[12].GetUInt8());
80
81 if (temp.sound)
82 {
83 if (!sSoundKitStore.LookupEntry(temp.sound))
84 {
85 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);
86 temp.sound = 0;
87 }
88 }
89
91 {
92 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry {}, Group {} in table `creature_text` has PlayType {} but does not exist.", temp.creatureId, temp.groupId, uint32(temp.SoundPlayType));
94 }
95
96 if (temp.lang != LANG_UNIVERSAL && !sLanguageMgr->IsLanguageExist(temp.lang))
97 {
98 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));
99 temp.lang = LANG_UNIVERSAL;
100 }
101
102 if (temp.type >= MAX_CHAT_MSG_TYPE)
103 {
104 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));
105 temp.type = CHAT_MSG_SAY;
106 }
107
108 if (temp.emote)
109 {
110 if (!sEmotesStore.LookupEntry(temp.emote))
111 {
112 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));
114 }
115 }
116
117 if (temp.BroadcastTextId)
118 {
119 if (!sBroadcastTextStore.LookupEntry(temp.BroadcastTextId))
120 {
121 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);
122 temp.BroadcastTextId = 0;
123 }
124 }
125
127 {
128 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry {}, Group {}, Id {} in table `creature_text` has incorrect TextRange {}.", temp.creatureId, temp.groupId, temp.id, temp.TextRange);
130 }
131
132 // add the text into our entry's group
133 mTextMap[temp.creatureId][temp.groupId].push_back(temp);
134
135 ++textCount;
136 }
137 while (result->NextRow());
138
139 TC_LOG_INFO("server.loading", ">> Loaded {} creature texts for {} creatures in {} ms", textCount, mTextMap.size(), GetMSTimeDiffToNow(oldMSTime));
140}
141
143{
144 uint32 oldMSTime = getMSTime();
145
146 mLocaleTextMap.clear(); // for reload case
147
148 QueryResult result = WorldDatabase.Query("SELECT CreatureId, GroupId, ID, Locale, Text FROM creature_text_locale");
149
150 if (!result)
151 return;
152
153 do
154 {
155 Field* fields = result->Fetch();
156
157 uint32 creatureId = fields[0].GetUInt32();
158 uint32 groupId = fields[1].GetUInt8();
159 uint32 id = fields[2].GetUInt8();
160 std::string_view localeName = fields[3].GetStringView();
161
162 LocaleConstant locale = GetLocaleByName(localeName);
163 if (!IsValidLocale(locale) || locale == LOCALE_enUS)
164 continue;
165
166 CreatureTextLocale& data = mLocaleTextMap[CreatureTextId(creatureId, groupId, id)];
167 ObjectMgr::AddLocaleString(fields[4].GetStringView(), locale, data.Text);
168 } while (result->NextRow());
169
170 TC_LOG_INFO("server.loading", ">> Loaded {} creature localized texts in {} ms", uint32(mLocaleTextMap.size()), GetMSTimeDiffToNow(oldMSTime));
171}
172
173uint32 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*/, SoundKitPlayType playType /*= SoundKitPlayType::Normal*/, Team team /*= TEAM_OTHER*/, bool gmOnly /*= false*/, Player* srcPlr /*= nullptr*/)
174{
175 if (!source)
176 return 0;
177
178 CreatureTextMap::const_iterator sList = mTextMap.find(source->GetEntry());
179 if (sList == mTextMap.end())
180 {
181 TC_LOG_ERROR("sql.sql.creaturetextmgr", "CreatureTextMgr: Could not find Text for Creature {} ({}) in 'creature_text' table. Ignoring.", source->GetName(), source->GetGUID().ToString());
182 return 0;
183 }
184
185 CreatureTextHolder const& textHolder = sList->second;
186 CreatureTextHolder::const_iterator itr = textHolder.find(textGroup);
187 if (itr == textHolder.end())
188 {
189 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());
190 return 0;
191 }
192
193 CreatureTextGroup const& textGroupContainer = itr->second; //has all texts in the group
194 CreatureTextRepeatIds repeatGroup = source->GetTextRepeatGroup(textGroup);//has all textIDs from the group that were already said
195 CreatureTextGroup tempGroup;//will use this to talk after sorting repeatGroup
196
197 for (CreatureTextGroup::const_iterator giter = textGroupContainer.begin(); giter != textGroupContainer.end(); ++giter)
198 if (std::find(repeatGroup.begin(), repeatGroup.end(), giter->id) == repeatGroup.end())
199 tempGroup.push_back(*giter);
200
201 if (tempGroup.empty())
202 {
203 source->ClearTextRepeatGroup(textGroup);
204 tempGroup = textGroupContainer;
205 }
206
207 auto iter = Trinity::Containers::SelectRandomWeightedContainerElement(tempGroup, [](CreatureTextEntry const& t) -> double
208 {
209 return t.probability;
210 });
211
212 ChatMsg finalType = (msgType == CHAT_MSG_ADDON) ? iter->type : msgType;
213 Language finalLang = (language == LANG_ADDON) ? iter->lang : language;
214 uint32 finalSound = iter->sound;
215 SoundKitPlayType finalPlayType = iter->SoundPlayType;
216 if (sound)
217 {
218 finalSound = sound;
219 finalPlayType = playType;
220 }
221 else if (BroadcastTextEntry const* bct = sBroadcastTextStore.LookupEntry(iter->BroadcastTextId))
222 if (uint32 broadcastTextSoundId = bct->SoundKitID[source->GetGender() == GENDER_FEMALE ? 1 : 0])
223 finalSound = broadcastTextSoundId;
224
225 if (range == TEXT_RANGE_NORMAL)
226 range = iter->TextRange;
227
228 if (finalSound)
229 SendSound(source, finalSound, finalType, whisperTarget, range, team, gmOnly, iter->BroadcastTextId, finalPlayType);
230
231 Unit* finalSource = source;
232 if (srcPlr)
233 finalSource = srcPlr;
234
235 if (iter->emote)
236 SendEmote(finalSource, iter->emote);
237
238 if (srcPlr)
239 {
240 Trinity::CreatureTextTextBuilder builder(source, finalSource, finalSource->GetGender(), finalType, iter->groupId, iter->id, finalLang, whisperTarget);
241 SendChatPacket(finalSource, builder, finalType, whisperTarget, range, team, gmOnly);
242 }
243 else
244 {
245 Trinity::CreatureTextTextBuilder builder(finalSource, finalSource, finalSource->GetGender(), finalType, iter->groupId, iter->id, finalLang, whisperTarget);
246 SendChatPacket(finalSource, builder, finalType, whisperTarget, range, team, gmOnly);
247 }
248
249 source->SetTextRepeatId(textGroup, iter->id);
250 return iter->duration;
251}
252
254{
255 float dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY);
256 switch (msgType)
257 {
259 dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL);
260 break;
263 dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE);
264 break;
265 default:
266 break;
267 }
268
269 return dist;
270}
271
272void CreatureTextMgr::SendSound(Creature* source, uint32 sound, ChatMsg msgType, WorldObject const* whisperTarget /*= nullptr*/, CreatureTextRange range /*= TEXT_RANGE_NORMAL*/,
273 Team team /*= TEAM_OTHER*/, bool gmOnly /*= false*/, uint32 keyBroadcastTextId /*= 0*/, SoundKitPlayType playType /*= SoundKitPlayType::Normal*/)
274{
275 if (!sound || !source)
276 return;
277
278 if (playType == SoundKitPlayType::ObjectSound)
279 {
281 pkt.TargetObjectGUID = whisperTarget->GetGUID();
282 pkt.SourceObjectGUID = source->GetGUID();
283 pkt.SoundKitID = sound;
284 pkt.Position = whisperTarget->GetWorldLocation();
285 pkt.BroadcastTextID = keyBroadcastTextId;
286 SendNonChatPacket(source, pkt.Write(), msgType, whisperTarget, range, team, gmOnly);
287 }
288 else if (playType == SoundKitPlayType::Normal)
289 SendNonChatPacket(source, WorldPackets::Misc::PlaySound(source->GetGUID(), sound, keyBroadcastTextId).Write(), msgType, whisperTarget, range, team, gmOnly);
290}
291
292void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket const* data, ChatMsg msgType, WorldObject const* whisperTarget, CreatureTextRange range, Team team, bool gmOnly)
293{
294 switch (msgType)
295 {
297 {
298 if (!whisperTarget)
299 return;
300
301 if (Player const* whisperPlayer = whisperTarget->ToPlayer())
302 {
303 if (Group const* group = whisperPlayer->GetGroup())
304 group->BroadcastWorker([data](Player* player) { player->SendDirectMessage(data); });
305 }
306 return;
307 }
310 {
311 if (range == TEXT_RANGE_NORMAL) // ignores team and gmOnly
312 {
313 if (!whisperTarget || whisperTarget->GetTypeId() != TYPEID_PLAYER)
314 return;
315
316 whisperTarget->ToPlayer()->SendDirectMessage(data);
317 return;
318 }
319 break;
320 }
321 default:
322 break;
323 }
324
325 switch (range)
326 {
327 case TEXT_RANGE_AREA:
328 {
329 uint32 areaId = source->GetAreaId();
330 Map::PlayerList const& players = source->GetMap()->GetPlayers();
331 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
332 if (itr->GetSource()->GetAreaId() == areaId && (!team || Team(itr->GetSource()->GetEffectiveTeam()) == team) && (!gmOnly || itr->GetSource()->IsGameMaster()))
333 itr->GetSource()->SendDirectMessage(data);
334 return;
335 }
336 case TEXT_RANGE_ZONE:
337 {
338 uint32 zoneId = source->GetZoneId();
339 Map::PlayerList const& players = source->GetMap()->GetPlayers();
340 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
341 if (itr->GetSource()->GetZoneId() == zoneId && (!team || Team(itr->GetSource()->GetEffectiveTeam()) == team) && (!gmOnly || itr->GetSource()->IsGameMaster()))
342 itr->GetSource()->SendDirectMessage(data);
343 return;
344 }
345 case TEXT_RANGE_MAP:
346 {
347 Map::PlayerList const& players = source->GetMap()->GetPlayers();
348 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
349 if ((!team || Team(itr->GetSource()->GetEffectiveTeam()) == team) && (!gmOnly || itr->GetSource()->IsGameMaster()))
350 itr->GetSource()->SendDirectMessage(data);
351 return;
352 }
353 case TEXT_RANGE_WORLD:
354 {
355 SessionMap const& smap = sWorld->GetAllSessions();
356 for (SessionMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter)
357 if (Player* player = iter->second->GetPlayer())
358 if ((!team || Team(player->GetTeam()) == team) && (!gmOnly || player->IsGameMaster()))
359 player->SendDirectMessage(data);
360 return;
361 }
363 if (!whisperTarget || !whisperTarget->IsPlayer())
364 return;
365
366 whisperTarget->ToPlayer()->SendDirectMessage(data);
367 return;
369 default:
370 break;
371 }
372
373 float dist = GetRangeForChatType(msgType);
374 source->SendMessageToSetInRange(data, dist, true);
375}
376
378{
379 if (!source)
380 return;
381
382 source->HandleEmoteCommand(emote);
383}
384
385bool CreatureTextMgr::TextExist(uint32 sourceEntry, uint8 textGroup) const
386{
387 if (!sourceEntry)
388 return false;
389
390 CreatureTextMap::const_iterator sList = mTextMap.find(sourceEntry);
391 if (sList == mTextMap.end())
392 {
393 TC_LOG_DEBUG("entities.unit", "CreatureTextMgr::TextExist: Could not find Text for Creature (entry {}) in 'creature_text' table.", sourceEntry);
394 return false;
395 }
396
397 CreatureTextHolder const& textHolder = sList->second;
398 CreatureTextHolder::const_iterator itr = textHolder.find(textGroup);
399 if (itr == textHolder.end())
400 {
401 TC_LOG_DEBUG("entities.unit", "CreatureTextMgr::TextExist: Could not find TextGroup {} for Creature (entry {}).", uint32(textGroup), sourceEntry);
402 return false;
403 }
404
405 return true;
406}
407
408std::string CreatureTextMgr::GetLocalizedChatString(uint32 entry, uint8 gender, uint8 textGroup, uint32 id, LocaleConstant locale) const
409{
410 CreatureTextMap::const_iterator mapitr = mTextMap.find(entry);
411 if (mapitr == mTextMap.end())
412 return "";
413
414 CreatureTextHolder::const_iterator holderItr = mapitr->second.find(textGroup);
415 if (holderItr == mapitr->second.end())
416 return "";
417
418 CreatureTextGroup::const_iterator groupItr = holderItr->second.begin();
419 for (; groupItr != holderItr->second.end(); ++groupItr)
420 if (groupItr->id == id)
421 break;
422
423 if (groupItr == holderItr->second.end())
424 return "";
425
426 if (locale >= TOTAL_LOCALES)
427 locale = DEFAULT_LOCALE;
428
429 std::string baseText = "";
430 BroadcastTextEntry const* bct = sBroadcastTextStore.LookupEntry(groupItr->BroadcastTextId);
431
432 if (bct)
433 baseText = DB2Manager::GetBroadcastTextValue(bct, locale, gender);
434 else
435 baseText = groupItr->text;
436
437 if (locale != DEFAULT_LOCALE && !bct)
438 {
439 LocaleCreatureTextMap::const_iterator locItr = mLocaleTextMap.find(CreatureTextId(entry, uint32(textGroup), id));
440 if (locItr != mLocaleTextMap.end())
441 ObjectMgr::GetLocaleString(locItr->second.Text, locale, baseText);
442 }
443
444 return baseText;
445}
LocaleConstant GetLocaleByName(std::string_view name)
Definition: Common.cpp:36
LocaleConstant
Definition: Common.h:48
@ TOTAL_LOCALES
Definition: Common.h:62
@ LOCALE_enUS
Definition: Common.h:49
constexpr bool IsValidLocale(LocaleConstant locale)
Definition: Common.h:95
#define DEFAULT_LOCALE
Definition: Common.h:66
std::vector< CreatureTextEntry > CreatureTextGroup
std::unordered_map< uint8, CreatureTextGroup > CreatureTextHolder
SoundKitPlayType
CreatureTextRange
@ TEXT_RANGE_ZONE
@ TEXT_RANGE_AREA
@ TEXT_RANGE_WORLD
@ TEXT_RANGE_PERSONAL
@ TEXT_RANGE_NORMAL
@ TEXT_RANGE_MAP
std::vector< uint8 > CreatureTextRepeatIds
Definition: Creature.h:66
DB2Storage< EmotesEntry > sEmotesStore("Emotes.db2", &EmotesLoadInfo::Instance)
DB2Storage< BroadcastTextEntry > sBroadcastTextStore("BroadcastText.db2", &BroadcastTextLoadInfo::Instance)
DB2Storage< SoundKitEntry > sSoundKitStore("SoundKit.db2", &SoundKitLoadInfo::Instance)
std::shared_ptr< ResultSet > QueryResult
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
#define sLanguageMgr
Definition: LanguageMgr.h:97
#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:41
Language
@ LANG_UNIVERSAL
@ LANG_ADDON
@ GENDER_FEMALE
Emote
@ EMOTE_ONESHOT_NONE
Team
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
Definition: WorldDatabase.h:34
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)
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, uint32 keyBroadcastTextId=0, SoundKitPlayType playType=SoundKitPlayType::Normal)
bool TextExist(uint32 sourceEntry, uint8 textGroup) const
static float GetRangeForChatType(ChatMsg msgType)
void LoadCreatureTextLocales()
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, SoundKitPlayType playType=SoundKitPlayType::Normal, 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)
CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup)
Definition: Creature.cpp:3578
void SetTextRepeatId(uint8 textGroup, uint8 id)
Definition: Creature.cpp:3569
void ClearTextRepeatGroup(uint8 textGroup)
Definition: Creature.cpp:3589
static char const * GetBroadcastTextValue(BroadcastTextEntry const *broadcastText, LocaleConstant locale=DEFAULT_LOCALE, uint8 gender=GENDER_MALE, bool forceGender=false)
Definition: DB2Stores.cpp:2008
Class used to access individual fields of database query result.
Definition: Field.h:90
uint8 GetUInt8() const
Definition: Field.cpp:30
std::string GetString() const
Definition: Field.cpp:118
std::string_view GetStringView() const
Definition: Field.cpp:130
float GetFloat() const
Definition: Field.cpp:94
uint32 GetUInt32() const
Definition: Field.cpp:62
Definition: Group.h:197
iterator end()
Definition: MapRefManager.h:35
iterator begin()
Definition: MapRefManager.h:34
PlayerList const & GetPlayers() const
Definition: Map.h:367
std::string ToString() const
Definition: ObjectGuid.cpp:554
static void AddLocaleString(std::string_view value, LocaleConstant localeConstant, std::vector< std::string > &data)
Definition: ObjectMgr.cpp:240
static std::string_view GetLocaleString(std::vector< std::string > const &data, LocaleConstant locale)
Definition: ObjectMgr.h:1682
bool IsPlayer() const
Definition: Object.h:212
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
Definition: Unit.h:627
Gender GetGender() const
Definition: Unit.h:755
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition: Unit.cpp:1598
constexpr WorldLocation GetWorldLocation() const
Definition: Position.h:196
Map * GetMap() const
Definition: Object.h:624
std::string const & GetName() const
Definition: Object.h:555
uint32 GetAreaId() const
Definition: Object.h:546
virtual void SendMessageToSetInRange(WorldPacket const *data, float dist, bool self) const
Definition: Object.cpp:1750
uint32 GetZoneId() const
Definition: Object.h:545
WorldPacket const * Write() override
TaggedPosition<::Position::XYZ > Position
Definition: MiscPackets.h:639
WorldPacket const * Write() override
#define sWorld
Definition: World.h:931
std::unordered_map< uint32, WorldSession * > SessionMap
Definition: World.h:559
@ CONFIG_LISTEN_RANGE_YELL
Definition: World.h:211
@ CONFIG_LISTEN_RANGE_SAY
Definition: World.h:209
@ CONFIG_LISTEN_RANGE_TEXTEMOTE
Definition: World.h:210
auto SelectRandomWeightedContainerElement(C const &container, std::span< double > const &weights) -> decltype(std::begin(container))
Definition: Containers.h:126
SoundKitPlayType SoundPlayType
CreatureTextRange TextRange
std::vector< std::string > Text