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

#include "GameGraveyard.h"

Public Types

typedef std::unordered_map< uint32, GraveyardStruct > GraveyardContainer
 

Public Member Functions

GraveyardStruct const * GetGraveyard (uint32 ID) const
 
GraveyardStruct const * GetGraveyard (std::string const &name) const
 
GraveyardStruct const * GetDefaultGraveyard (TeamId teamId)
 
GraveyardStruct const * GetClosestGraveyard (Player *player, TeamId teamId, bool nearCorpse=false)
 
GraveyardStruct const * GetClosestGraveyard (uint32 mapId, float x, float y, float z, TeamId teamId, uint32 areaId, uint32 zoneId, bool isDeathKnight)
 
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 Graveyard * instance ()
 

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 
)
293{
294 if (FindGraveyardData(id, zoneId))
295 return false;
296
297 // add link to loaded data
298 GraveyardData data;
299 data.safeLocId = id;
300 data.teamId = teamId;
301
302 GraveyardStore.insert(WGGraveyardContainer::value_type(zoneId, data));
303
304 // add link to DB
305 if (persist)
306 {
308
309 stmt->SetData(0, id);
310 stmt->SetData(1, zoneId);
311 // Xinef: DB Data compatibility...
312 stmt->SetData(2, uint16(teamId == TEAM_NEUTRAL ? 0 : (teamId == TEAM_ALLIANCE ? ALLIANCE : HORDE)));
313
314 WorldDatabase.Execute(stmt);
315 }
316
317 return true;
318}
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition DatabaseEnv.cpp:20
std::uint16_t uint16
Definition Define.h:108
@ ALLIANCE
Definition SharedDefines.h:756
@ HORDE
Definition SharedDefines.h:755
@ TEAM_NEUTRAL
Definition SharedDefines.h:750
@ TEAM_ALLIANCE
Definition SharedDefines.h:748
@ WORLD_INS_GRAVEYARD_ZONE
Definition WorldDatabase.h:40
GraveyardData const * FindGraveyardData(uint32 id, uint32 zone)
Definition GameGraveyard.cpp:279
WGGraveyardContainer GraveyardStore
Definition GameGraveyard.h:73
Acore::Types::is_default< T > SetData(const uint8 index, T value)
Definition PreparedStatement.h:77
Definition PreparedStatement.h:157
Definition GameGraveyard.h:38
TeamId teamId
Definition GameGraveyard.h:40
uint32 safeLocId
Definition GameGraveyard.h:39

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 
)
280{
281 GraveyardMapBounds range = GraveyardStore.equal_range(zoneId);
282 for (; range.first != range.second; ++range.first)
283 {
284 GraveyardData const& data = range.first->second;
285 if (data.safeLocId == id)
286 return &data;
287 }
288
289 return nullptr;
290}
std::pair< WGGraveyardContainer::const_iterator, WGGraveyardContainer::const_iterator > GraveyardMapBounds
Definition GameGraveyard.h:46

References GraveyardStore, and GraveyardData::safeLocId.

Referenced by AddGraveyardLink().

◆ GetClosestGraveyard() [1/2]

GraveyardStruct const * Graveyard::GetClosestGraveyard ( Player *  player,
TeamId  teamId,
bool  nearCorpse = false 
)
98{
99 uint32 graveyardOverride = 0;
100 sScriptMgr->OnPlayerBeforeChooseGraveyard(player, teamId, nearCorpse, graveyardOverride);
101 if (graveyardOverride)
102 {
103 return 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 return GetClosestGraveyard(mapId, x, y, z, teamId, areaId, zoneId,
124}
std::uint32_t uint32
Definition Define.h:107
#define sScriptMgr
Definition ScriptMgr.h:766
@ CLASS_DEATH_KNIGHT
Definition SharedDefines.h:131
@ CLASS_CONTEXT_GRAVEYARD
Definition UnitDefines.h:249
GraveyardStruct const * GetGraveyard(uint32 ID) const
Definition GameGraveyard.cpp:77
GraveyardStruct const * GetClosestGraveyard(Player *player, TeamId teamId, bool nearCorpse=false)
Definition GameGraveyard.cpp:97
WorldLocation GetCorpseLocation() const
Definition Player.h:2071
bool IsClass(Classes playerClass, ClassContext context=CLASS_CONTEXT_NONE) const override
Definition Player.cpp:1350
Definition Position.h:256
uint32 GetMapId() const
Definition Position.h:281
void GetWorldLocation(uint32 &mapId, float &x, float &y) const
Definition Position.h:286
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition Object.cpp:3187
float GetPositionZ() const
Definition Position.h:123
float GetPositionX() const
Definition Position.h:121
float GetPositionY() const
Definition Position.h:122

References CLASS_CONTEXT_GRAVEYARD, CLASS_DEATH_KNIGHT, GetClosestGraveyard(), Player::GetCorpseLocation(), GetGraveyard(), WorldLocation::GetMapId(), Position::GetPositionX(), Position::GetPositionY(), Position::GetPositionZ(), WorldLocation::GetWorldLocation(), WorldObject::GetZoneAndAreaId(), Player::IsClass(), and sScriptMgr.

Referenced by GetClosestGraveyard().

◆ GetClosestGraveyard() [2/2]

GraveyardStruct const * Graveyard::GetClosestGraveyard ( uint32  mapId,
float  x,
float  y,
float  z,
TeamId  teamId,
uint32  areaId,
uint32  zoneId,
bool  isDeathKnight 
)
128{
129 if (!zoneId && !areaId)
130 {
131 if (z > -500)
132 {
133 LOG_ERROR("sql.sql", "GetClosestGraveyard: unable to find zoneId and areaId for map {} coords ({}, {}, {})", mapId, x, y, z);
134 return GetDefaultGraveyard(teamId);
135 }
136 }
137
138 // Simulate std. algorithm:
139 // found some graveyard associated to (ghost_zone, ghost_map)
140 //
141 // if mapId == graveyard.mapId (ghost in plain zone or city or battleground) and search graveyard at same map
142 // then check faction
143 // if mapId != graveyard.mapId (ghost in instance) and search any graveyard associated
144 // then check faction
145
146 // Fetch the graveyards linked to the areaId first, presumably the closer ones.
147 GraveyardMapBounds range = GraveyardStore.equal_range(areaId);
148
149 // No graveyards linked to the area, search zone.
150 if (range.first == range.second)
151 {
152 range = GraveyardStore.equal_range(zoneId);
153 }
154 else // Found a graveyard linked to the area, check if it's a valid one.
155 {
156 GraveyardData const& graveyardLink = range.first->second;
157
158 if (!graveyardLink.IsNeutralOrFriendlyToTeam(teamId))
159 {
160 // Not a friendly or neutral graveyard, search zone.
161 range = GraveyardStore.equal_range(zoneId);
162 }
163 }
164
165 MapEntry const* map = sMapStore.LookupEntry(mapId);
166
167 // not need to check validity of map object; MapId _MUST_ be valid here
168 if (range.first == range.second && !map->IsBattlegroundOrArena())
169 {
170 LOG_ERROR("sql.sql", "Table `graveyard_zone` incomplete: Zone {} Team {} does not have a linked graveyard.", zoneId, teamId);
171 return GetDefaultGraveyard(teamId);
172 }
173
174 // at corpse map
175 bool foundNear = false;
176 float distNear = 10000;
177 GraveyardStruct const* entryNear = nullptr;
178
179 // at entrance map for corpse map
180 bool foundEntr = false;
181 float distEntr = 10000;
182 GraveyardStruct const* entryEntr = nullptr;
183
184 // some where other
185 GraveyardStruct const* entryFar = nullptr;
186
187 MapEntry const* mapEntry = sMapStore.LookupEntry(mapId);
188
189 for (; range.first != range.second; ++range.first)
190 {
191 GraveyardData const& graveyardLink = range.first->second;
192 GraveyardStruct const* entry = GetGraveyard(graveyardLink.safeLocId);
193 if (!entry)
194 {
195 LOG_ERROR("sql.sql", "Table `graveyard_zone` has record for not existing `game_graveyard` table {}, skipped.", graveyardLink.safeLocId);
196 continue;
197 }
198
199 // Skip enemy faction graveyard.
200 if (!graveyardLink.IsNeutralOrFriendlyToTeam(teamId))
201 {
202 continue;
203 }
204
205 // Skip Archerus graveyards if the player isn't a Death Knight.
206 enum DeathKnightGraveyards
207 {
208 GRAVEYARD_EBON_HOLD = 1369,
209 GRAVEYARD_ARCHERUS = 1405
210 };
211
212 if (!isDeathKnight && (graveyardLink.safeLocId == GRAVEYARD_EBON_HOLD || graveyardLink.safeLocId == GRAVEYARD_ARCHERUS))
213 {
214 continue;
215 }
216
217 // find now nearest graveyard at other map
218 if (mapId != entry->Map)
219 {
220 // if find graveyard at different map from where entrance placed (or no entrance data), use any first
221 if (!mapEntry
222 || mapEntry->entrance_map < 0
223 || uint32(mapEntry->entrance_map) != entry->Map
224 || (mapEntry->entrance_x == 0 && mapEntry->entrance_y == 0))
225 {
226 // not have any corrdinates for check distance anyway
227 entryFar = entry;
228 continue;
229 }
230
231 // at entrance map calculate distance (2D);
232 float dist2 = (entry->x - mapEntry->entrance_x) * (entry->x - mapEntry->entrance_x)
233 + (entry->y - mapEntry->entrance_y) * (entry->y - mapEntry->entrance_y);
234 if (foundEntr)
235 {
236 if (dist2 < distEntr)
237 {
238 distEntr = dist2;
239 entryEntr = entry;
240 }
241 }
242 else
243 {
244 foundEntr = true;
245 distEntr = dist2;
246 entryEntr = entry;
247 }
248 }
249 // find now nearest graveyard at same map
250 else
251 {
252 float dist2 = (entry->x - x) * (entry->x - x) + (entry->y - y) * (entry->y - y) + (entry->z - z) * (entry->z - z);
253 if (foundNear)
254 {
255 if (dist2 < distNear)
256 {
257 distNear = dist2;
258 entryNear = entry;
259 }
260 }
261 else
262 {
263 foundNear = true;
264 distNear = dist2;
265 entryNear = entry;
266 }
267 }
268 }
269
270 if (entryNear)
271 return entryNear;
272
273 if (entryEntr)
274 return entryEntr;
275
276 return entryFar;
277}
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
#define LOG_ERROR(filterType__,...)
Definition Log.h:145
GraveyardStruct const * GetDefaultGraveyard(TeamId teamId)
Definition GameGraveyard.cpp:86
bool IsNeutralOrFriendlyToTeam(TeamId playerTeamId) const
Definition GameGraveyard.h:42
Definition GameGraveyard.h:27
float z
Definition GameGraveyard.h:32
float x
Definition GameGraveyard.h:30
float y
Definition GameGraveyard.h:31
uint32 Map
Definition GameGraveyard.h:29
Definition DBCStructure.h:1361
float entrance_y
Definition DBCStructure.h:1378
int32 entrance_map
Definition DBCStructure.h:1376
bool IsBattlegroundOrArena() const
Definition DBCStructure.h:1393
float entrance_x
Definition DBCStructure.h:1377

References MapEntry::entrance_map, MapEntry::entrance_x, MapEntry::entrance_y, GetDefaultGraveyard(), GetGraveyard(), GraveyardStore, MapEntry::IsBattlegroundOrArena(), GraveyardData::IsNeutralOrFriendlyToTeam(), LOG_ERROR, GraveyardStruct::Map, GraveyardData::safeLocId, sMapStore, 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 GetGraveyard(teamId == TEAM_HORDE ? HORDE_GRAVEYARD : ALLIANCE_GRAVEYARD);
95}
@ TEAM_HORDE
Definition SharedDefines.h:749

References GetGraveyard(), and TEAM_HORDE.

Referenced by GetClosestGraveyard().

◆ GetGraveyard() [1/2]

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

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.

Referenced by GetClosestGraveyard(), GetClosestGraveyard(), GetDefaultGraveyard(), and LoadGraveyardZones().

◆ GetGraveyardData()

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

References _graveyardStore.

◆ instance()

Graveyard * Graveyard::instance ( )
static
26{
27 static Graveyard instance;
28 return &instance;
29}
Definition GameGraveyard.h:50
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 {
50
51 Field* fields = result->Fetch();
52
53 Graveyard.ID = fields[0].Get<uint32>();
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.", Graveyard.ID);
63 continue;
64 }
65
66 wstrToLower(Graveyard.wnameLow);
67
68 _graveyardStore[Graveyard.ID] = std::move(Graveyard);
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::shared_ptr< ResultSet > QueryResult
Definition DatabaseEnvFwd.h:27
std::int32_t int32
Definition Define.h:103
#define LOG_INFO(filterType__,...)
Definition Log.h:153
#define LOG_WARN(filterType__,...)
Definition Log.h:149
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:131
uint32 getMSTime()
Definition Timer.h:103
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
std::size_t Count(ContainerMapList< SPECIFIC_TYPE > const &elements, SPECIFIC_TYPE *)
Definition TypeContainerFunctions.h:159

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

◆ LoadGraveyardZones()

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

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

◆ RemoveGraveyardLink()

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

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


The documentation for this class was generated from the following files: