AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
Graveyard Class Reference

#include "GameGraveyard.h"

Public Types

typedef std::unordered_map< uint32, GraveyardStructGraveyardContainer
 

Public Member Functions

GraveyardStruct const * GetGraveyard (uint32 ID) const
 
GraveyardStruct const * GetGraveyard (const std::string &name) const
 
GraveyardStruct const * GetDefaultGraveyard (TeamId teamId)
 
GraveyardStruct const * GetClosestGraveyard (Player *player, TeamId teamId, bool nearCorpse=false)
 
GraveyardData const * FindGraveyardData (uint32 id, uint32 zone)
 
GraveyardContainer const & GetGraveyardData () const
 
bool AddGraveyardLink (uint32 id, uint32 zoneId, TeamId teamId, bool persist=true)
 
void RemoveGraveyardLink (uint32 id, uint32 zoneId, TeamId teamId, bool persist=false)
 
void LoadGraveyardZones ()
 
void LoadGraveyardFromDB ()
 

Static Public Member Functions

static Graveyardinstance ()
 

Private Attributes

GraveyardContainer _graveyardStore
 
WGGraveyardContainer GraveyardStore
 

Detailed Description

Member Typedef Documentation

◆ GraveyardContainer

Member Function Documentation

◆ AddGraveyardLink()

bool Graveyard::AddGraveyardLink ( uint32  id,
uint32  zoneId,
TeamId  teamId,
bool  persist = true 
)
286{
287 if (FindGraveyardData(id, zoneId))
288 return false;
289
290 // add link to loaded data
291 GraveyardData data;
292 data.safeLocId = id;
293 data.teamId = teamId;
294
295 GraveyardStore.insert(WGGraveyardContainer::value_type(zoneId, data));
296
297 // add link to DB
298 if (persist)
299 {
301
302 stmt->SetData(0, id);
303 stmt->SetData(1, zoneId);
304 // Xinef: DB Data compatibility...
305 stmt->SetData(2, uint16(teamId == TEAM_NEUTRAL ? 0 : (teamId == TEAM_ALLIANCE ? ALLIANCE : HORDE)));
306
307 WorldDatabase.Execute(stmt);
308 }
309
310 return true;
311}
std::uint16_t uint16
Definition: Define.h:109
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
@ WORLD_INS_GRAVEYARD_ZONE
Definition: WorldDatabase.h:39
@ ALLIANCE
Definition: SharedDefines.h:768
@ HORDE
Definition: SharedDefines.h:767
@ TEAM_NEUTRAL
Definition: SharedDefines.h:762
@ TEAM_ALLIANCE
Definition: SharedDefines.h:760
Definition: PreparedStatement.h:158
Acore::Types::is_default< T > SetData(const uint8 index, T value)
Definition: PreparedStatement.h:78
Definition: GameGraveyard.h:39
TeamId teamId
Definition: GameGraveyard.h:41
uint32 safeLocId
Definition: GameGraveyard.h:40
GraveyardData const * FindGraveyardData(uint32 id, uint32 zone)
Definition: GameGraveyard.cpp:272
WGGraveyardContainer GraveyardStore
Definition: GameGraveyard.h:72

References ALLIANCE, FindGraveyardData(), GraveyardStore, HORDE, GraveyardData::safeLocId, PreparedStatementBase::SetData(), TEAM_ALLIANCE, TEAM_NEUTRAL, GraveyardData::teamId, WORLD_INS_GRAVEYARD_ZONE, and WorldDatabase.

Referenced by LoadGraveyardZones().

◆ FindGraveyardData()

GraveyardData const * Graveyard::FindGraveyardData ( uint32  id,
uint32  zone 
)
273{
274 GraveyardMapBounds range = GraveyardStore.equal_range(zoneId);
275 for (; range.first != range.second; ++range.first)
276 {
277 GraveyardData const& data = range.first->second;
278 if (data.safeLocId == id)
279 return &data;
280 }
281
282 return nullptr;
283}
std::pair< WGGraveyardContainer::const_iterator, WGGraveyardContainer::const_iterator > GraveyardMapBounds
Definition: GameGraveyard.h:47

References GraveyardStore, and GraveyardData::safeLocId.

Referenced by AddGraveyardLink().

◆ GetClosestGraveyard()

GraveyardStruct const * Graveyard::GetClosestGraveyard ( Player player,
TeamId  teamId,
bool  nearCorpse = false 
)
98{
99 uint32 graveyardOverride = 0;
100 sScriptMgr->OnBeforeChooseGraveyard(player, teamId, nearCorpse, graveyardOverride);
101 if (graveyardOverride)
102 {
103 return sGraveyard->GetGraveyard(graveyardOverride);
104 }
105
106 WorldLocation loc = player->GetWorldLocation();
107
108 if (nearCorpse)
109 {
110 loc = player->GetCorpseLocation();
111 }
112
113 uint32 mapId = loc.GetMapId();
114 float x = loc.GetPositionX();
115 float y = loc.GetPositionY();
116 float z = loc.GetPositionZ();
117
118 uint32 zoneId = 0;
119 uint32 areaId = 0;
120 player->GetZoneAndAreaId(zoneId, areaId);
121
122 if (!zoneId && !areaId)
123 {
124 if (z > -500)
125 {
126 LOG_ERROR("sql.sql", "GetClosestGraveyard: unable to find zoneId and areaId for map {} coords ({}, {}, {})", mapId, x, y, z);
127 return GetDefaultGraveyard(teamId);
128 }
129 }
130
131 // Simulate std. algorithm:
132 // found some graveyard associated to (ghost_zone, ghost_map)
133 //
134 // if mapId == graveyard.mapId (ghost in plain zone or city or battleground) and search graveyard at same map
135 // then check faction
136 // if mapId != graveyard.mapId (ghost in instance) and search any graveyard associated
137 // then check faction
138
139 // Fetch the graveyards linked to the areaId first, presumably the closer ones.
140 GraveyardMapBounds range = GraveyardStore.equal_range(areaId);
141
142 // No graveyards linked to the area, search zone.
143 if (range.first == range.second)
144 {
145 range = GraveyardStore.equal_range(zoneId);
146 }
147 else // Found a graveyard linked to the area, check if it's a valid one.
148 {
149 GraveyardData const& graveyardLink = range.first->second;
150
151 if (!graveyardLink.IsNeutralOrFriendlyToTeam(teamId))
152 {
153 // Not a friendly or neutral graveyard, search zone.
154 range = GraveyardStore.equal_range(zoneId);
155 }
156 }
157
158 MapEntry const* map = sMapStore.LookupEntry(mapId);
159
160 // not need to check validity of map object; MapId _MUST_ be valid here
161 if (range.first == range.second && !map->IsBattlegroundOrArena())
162 {
163 LOG_ERROR("sql.sql", "Table `graveyard_zone` incomplete: Zone {} Team {} does not have a linked graveyard.", zoneId, teamId);
164 return GetDefaultGraveyard(teamId);
165 }
166
167 // at corpse map
168 bool foundNear = false;
169 float distNear = 10000;
170 GraveyardStruct const* entryNear = nullptr;
171
172 // at entrance map for corpse map
173 bool foundEntr = false;
174 float distEntr = 10000;
175 GraveyardStruct const* entryEntr = nullptr;
176
177 // some where other
178 GraveyardStruct const* entryFar = nullptr;
179
180 MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
181
182 for (; range.first != range.second; ++range.first)
183 {
184 GraveyardData const& graveyardLink = range.first->second;
185 GraveyardStruct const* entry = sGraveyard->GetGraveyard(graveyardLink.safeLocId);
186 if (!entry)
187 {
188 LOG_ERROR("sql.sql", "Table `graveyard_zone` has record for not existing `game_graveyard` table {}, skipped.", graveyardLink.safeLocId);
189 continue;
190 }
191
192 // Skip enemy faction graveyard.
193 if (!graveyardLink.IsNeutralOrFriendlyToTeam(teamId))
194 {
195 continue;
196 }
197
198 // Skip Archerus graveyards if the player isn't a Death Knight.
199 enum DeathKnightGraveyards
200 {
201 GRAVEYARD_EBON_HOLD = 1369,
202 GRAVEYARD_ARCHERUS = 1405
203 };
204
205 if (player->getClass() != CLASS_DEATH_KNIGHT && (graveyardLink.safeLocId == GRAVEYARD_EBON_HOLD || graveyardLink.safeLocId == GRAVEYARD_ARCHERUS))
206 {
207 continue;
208 }
209
210 // find now nearest graveyard at other map
211 if (mapId != entry->Map)
212 {
213 // if find graveyard at different map from where entrance placed (or no entrance data), use any first
214 if (!mapEntry
215 || mapEntry->entrance_map < 0
216 || uint32(mapEntry->entrance_map) != entry->Map
217 || (mapEntry->entrance_x == 0 && mapEntry->entrance_y == 0))
218 {
219 // not have any corrdinates for check distance anyway
220 entryFar = entry;
221 continue;
222 }
223
224 // at entrance map calculate distance (2D);
225 float dist2 = (entry->x - mapEntry->entrance_x) * (entry->x - mapEntry->entrance_x)
226 + (entry->y - mapEntry->entrance_y) * (entry->y - mapEntry->entrance_y);
227 if (foundEntr)
228 {
229 if (dist2 < distEntr)
230 {
231 distEntr = dist2;
232 entryEntr = entry;
233 }
234 }
235 else
236 {
237 foundEntr = true;
238 distEntr = dist2;
239 entryEntr = entry;
240 }
241 }
242 // find now nearest graveyard at same map
243 else
244 {
245 float dist2 = (entry->x - x) * (entry->x - x) + (entry->y - y) * (entry->y - y) + (entry->z - z) * (entry->z - z);
246 if (foundNear)
247 {
248 if (dist2 < distNear)
249 {
250 distNear = dist2;
251 entryNear = entry;
252 }
253 }
254 else
255 {
256 foundNear = true;
257 distNear = dist2;
258 entryNear = entry;
259 }
260 }
261 }
262
263 if (entryNear)
264 return entryNear;
265
266 if (entryEntr)
267 return entryEntr;
268
269 return entryFar;
270}
std::uint32_t uint32
Definition: Define.h:108
#define LOG_ERROR(filterType__,...)
Definition: Log.h:157
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
#define sGraveyard
Definition: GameGraveyard.h:75
#define sScriptMgr
Definition: ScriptMgr.h:698
@ CLASS_DEATH_KNIGHT
Definition: SharedDefines.h:146
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition: Object.cpp:3116
float GetPositionZ() const
Definition: Position.h:119
float GetPositionX() const
Definition: Position.h:117
float GetPositionY() const
Definition: Position.h:118
Definition: Position.h:251
uint32 GetMapId() const
Definition: Position.h:276
void GetWorldLocation(uint32 &mapId, float &x, float &y) const
Definition: Position.h:281
WorldLocation GetCorpseLocation() const
Definition: Player.h:2003
uint8 getClass() const
Definition: Unit.h:1438
Definition: GameGraveyard.h:28
float z
Definition: GameGraveyard.h:33
float x
Definition: GameGraveyard.h:31
float y
Definition: GameGraveyard.h:32
uint32 Map
Definition: GameGraveyard.h:30
bool IsNeutralOrFriendlyToTeam(TeamId playerTeamId) const
Definition: GameGraveyard.h:43
GraveyardStruct const * GetDefaultGraveyard(TeamId teamId)
Definition: GameGraveyard.cpp:86
Definition: DBCStructure.h:1323
float entrance_y
Definition: DBCStructure.h:1340
int32 entrance_map
Definition: DBCStructure.h:1338
bool IsBattlegroundOrArena() const
Definition: DBCStructure.h:1355
float entrance_x
Definition: DBCStructure.h:1339

References CLASS_DEATH_KNIGHT, MapEntry::entrance_map, MapEntry::entrance_x, MapEntry::entrance_y, Unit::getClass(), Player::GetCorpseLocation(), GetDefaultGraveyard(), WorldLocation::GetMapId(), Position::GetPositionX(), Position::GetPositionY(), Position::GetPositionZ(), WorldLocation::GetWorldLocation(), WorldObject::GetZoneAndAreaId(), GraveyardStore, MapEntry::IsBattlegroundOrArena(), GraveyardData::IsNeutralOrFriendlyToTeam(), LOG_ERROR, GraveyardStruct::Map, GraveyardData::safeLocId, sGraveyard, sMapStore, sScriptMgr, GraveyardStruct::x, GraveyardStruct::y, and GraveyardStruct::z.

◆ GetDefaultGraveyard()

GraveyardStruct const * Graveyard::GetDefaultGraveyard ( TeamId  teamId)
87{
88 enum DefaultGraveyard
89 {
90 HORDE_GRAVEYARD = 10, // Crossroads
91 ALLIANCE_GRAVEYARD = 4, // Westfall
92 };
93
94 return sGraveyard->GetGraveyard(teamId == TEAM_HORDE ? HORDE_GRAVEYARD : ALLIANCE_GRAVEYARD);
95}
@ TEAM_HORDE
Definition: SharedDefines.h:761

References sGraveyard, and TEAM_HORDE.

Referenced by GetClosestGraveyard().

◆ GetGraveyard() [1/2]

GraveyardStruct const * Graveyard::GetGraveyard ( const std::string &  name) const
420{
421 // explicit name case
422 std::wstring wname;
423 if (!Utf8toWStr(name, wname))
424 return nullptr;
425
426 // converting string that we try to find to lower case
427 wstrToLower(wname);
428
429 // Alternative first GameTele what contains wnameLow as substring in case no GameTele location found
430 const GraveyardStruct* alt = nullptr;
431 for (GraveyardContainer::const_iterator itr = _graveyardStore.begin(); itr != _graveyardStore.end(); ++itr)
432 {
433 if (itr->second.wnameLow == wname)
434 return &itr->second;
435 else if (!alt && itr->second.wnameLow.find(wname) != std::wstring::npos)
436 alt = &itr->second;
437 }
438
439 return alt;
440}
void wstrToLower(std::wstring &str)
Definition: Util.cpp:382
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:281
GraveyardContainer _graveyardStore
Definition: GameGraveyard.h:69

References _graveyardStore, Utf8toWStr(), GraveyardStruct::wnameLow, and wstrToLower().

◆ GetGraveyard() [2/2]

GraveyardStruct const * Graveyard::GetGraveyard ( uint32  ID) const
78{
79 GraveyardContainer::const_iterator itr = _graveyardStore.find(ID);
80 if (itr != _graveyardStore.end())
81 return &itr->second;
82
83 return nullptr;
84}

References _graveyardStore.

◆ GetGraveyardData()

GraveyardContainer const & Graveyard::GetGraveyardData ( ) const
inline
62{ return _graveyardStore; }

References _graveyardStore.

◆ instance()

Graveyard * Graveyard::instance ( )
static
26{
27 static Graveyard instance;
28 return &instance;
29}
Definition: GameGraveyard.h:51
static Graveyard * instance()
Definition: GameGraveyard.cpp:25

References instance().

Referenced by instance().

◆ LoadGraveyardFromDB()

void Graveyard::LoadGraveyardFromDB ( )
32{
33 uint32 oldMSTime = getMSTime();
34
35 _graveyardStore.clear();
36
37 QueryResult result = WorldDatabase.Query("SELECT ID, Map, x, y, z, Comment FROM game_graveyard");
38 if (!result)
39 {
40 LOG_WARN("server.loading", ">> Loaded 0 graveyard. Table `game_graveyard` is empty!");
41 LOG_INFO("server.loading", " ");
42 return;
43 }
44
45 int32 Count = 0;
46
47 do
48 {
49 Field* fields = result->Fetch();
50 uint32 ID = fields[0].Get<uint32>();
51
53
54 Graveyard.Map = fields[1].Get<uint32>();
55 Graveyard.x = fields[2].Get<float>();
56 Graveyard.y = fields[3].Get<float>();
57 Graveyard.z = fields[4].Get<float>();
58 Graveyard.name = fields[5].Get<std::string>();
59
60 if (!Utf8toWStr(Graveyard.name, Graveyard.wnameLow))
61 {
62 LOG_ERROR("sql.sql", "Wrong UTF8 name for id {} in `game_graveyard` table, ignoring.", ID);
63 continue;
64 }
65
66 wstrToLower(Graveyard.wnameLow);
67
69
70 ++Count;
71 } while (result->NextRow());
72
73 LOG_INFO("server.loading", ">> Loaded {} Graveyard in {} ms", Count, GetMSTimeDiffToNow(oldMSTime));
74 LOG_INFO("server.loading", " ");
75}
std::int32_t int32
Definition: Define.h:104
#define LOG_INFO(filterType__,...)
Definition: Log.h:165
#define LOG_WARN(filterType__,...)
Definition: Log.h:161
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition: Timer.h:131
uint32 getMSTime()
Definition: Timer.h:103
std::shared_ptr< ResultSet > QueryResult
Definition: DatabaseEnvFwd.h:28
size_t Count(const ContainerMapList< SPECIFIC_TYPE > &elements, SPECIFIC_TYPE *)
Definition: TypeContainerFunctions.h:162
Class used to access individual fields of database query result.
Definition: Field.h:99
std::enable_if_t< std::is_arithmetic_v< T >, T > Get() const
Definition: Field.h:113

References _graveyardStore, Field::Get(), getMSTime(), GetMSTimeDiffToNow(), LOG_ERROR, LOG_INFO, LOG_WARN, Utf8toWStr(), WorldDatabase, and wstrToLower().

◆ LoadGraveyardZones()

void Graveyard::LoadGraveyardZones ( )
363{
364 uint32 oldMSTime = getMSTime();
365
366 GraveyardStore.clear(); // need for reload case
367
368 // 0 1 2
369 QueryResult result = WorldDatabase.Query("SELECT ID, GhostZone, Faction FROM graveyard_zone");
370
371 if (!result)
372 {
373 LOG_WARN("server.loading", ">> Loaded 0 Graveyard-Zone Links. DB Table `graveyard_zone` Is Empty.");
374 LOG_INFO("server.loading", " ");
375 return;
376 }
377
378 uint32 count = 0;
379
380 do
381 {
382 ++count;
383
384 Field* fields = result->Fetch();
385
386 uint32 safeLocId = fields[0].Get<uint32>();
387 uint32 zoneId = fields[1].Get<uint32>();
388 uint32 team = fields[2].Get<uint16>();
389 TeamId teamId = team == 0 ? TEAM_NEUTRAL : (team == ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE);
390
391 GraveyardStruct const* entry = sGraveyard->GetGraveyard(safeLocId);
392 if (!entry)
393 {
394 LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for not existing `game_graveyard` table {}, skipped.", safeLocId);
395 continue;
396 }
397
398 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId);
399 if (!areaEntry)
400 {
401 LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for not existing zone id ({}), skipped.", zoneId);
402 continue;
403 }
404
405 if (team != 0 && team != HORDE && team != ALLIANCE)
406 {
407 LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for non player faction ({}), skipped.", team);
408 continue;
409 }
410
411 if (!AddGraveyardLink(safeLocId, zoneId, teamId, false))
412 LOG_ERROR("sql.sql", "Table `graveyard_zone` has a duplicate record for Graveyard (ID: {}) and Zone (ID: {}), skipped.", safeLocId, zoneId);
413 } while (result->NextRow());
414
415 LOG_INFO("server.loading", ">> Loaded {} Graveyard-Zone Links in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
416 LOG_INFO("server.loading", " ");
417}
DBCStorage< AreaTableEntry > sAreaTableStore(AreaTableEntryfmt)
TeamId
Definition: SharedDefines.h:759
bool AddGraveyardLink(uint32 id, uint32 zoneId, TeamId teamId, bool persist=true)
Definition: GameGraveyard.cpp:285
Definition: DBCStructure.h:519

References AddGraveyardLink(), ALLIANCE, Field::Get(), getMSTime(), GetMSTimeDiffToNow(), GraveyardStore, HORDE, LOG_ERROR, LOG_INFO, LOG_WARN, sAreaTableStore, sGraveyard, TEAM_ALLIANCE, TEAM_HORDE, TEAM_NEUTRAL, and WorldDatabase.

◆ RemoveGraveyardLink()

void Graveyard::RemoveGraveyardLink ( uint32  id,
uint32  zoneId,
TeamId  teamId,
bool  persist = false 
)
314{
315 GraveyardMapBoundsNonConst range = GraveyardStore.equal_range(zoneId);
316 if (range.first == range.second)
317 {
318 LOG_ERROR("sql.sql", "Table `graveyard_zone` incomplete: Zone {} Team {} does not have a linked graveyard.", zoneId, teamId);
319 return;
320 }
321
322 bool found = false;
323
324 for (; range.first != range.second; ++range.first)
325 {
326 GraveyardData& data = range.first->second;
327
328 // skip not matching safezone id
329 if (data.safeLocId != id)
330 continue;
331
332 // skip enemy faction graveyard at same map (normal area, city, or battleground)
333 // team == 0 case can be at call from .neargrave
334 if (data.teamId != TEAM_NEUTRAL && teamId != TEAM_NEUTRAL && data.teamId != teamId)
335 continue;
336
337 found = true;
338 break;
339 }
340
341 // no match, return
342 if (!found)
343 return;
344
345 // remove from links
346 GraveyardStore.erase(range.first);
347
348 // remove link from DB
349 if (persist)
350 {
352
353 stmt->SetData(0, id);
354 stmt->SetData(1, zoneId);
355 // Xinef: DB Data compatibility...
356 stmt->SetData(2, uint16(teamId == TEAM_NEUTRAL ? 0 : (teamId == TEAM_ALLIANCE ? ALLIANCE : HORDE)));
357
358 WorldDatabase.Execute(stmt);
359 }
360}
@ WORLD_DEL_GRAVEYARD_ZONE
Definition: WorldDatabase.h:40
std::pair< WGGraveyardContainer::iterator, WGGraveyardContainer::iterator > GraveyardMapBoundsNonConst
Definition: GameGraveyard.h:48

References ALLIANCE, GraveyardStore, HORDE, LOG_ERROR, GraveyardData::safeLocId, PreparedStatementBase::SetData(), TEAM_ALLIANCE, TEAM_NEUTRAL, GraveyardData::teamId, WORLD_DEL_GRAVEYARD_ZONE, and WorldDatabase.

Member Data Documentation

◆ _graveyardStore

GraveyardContainer Graveyard::_graveyardStore
private

◆ GraveyardStore