diff options
Diffstat (limited to 'src')
250 files changed, 7395 insertions, 4494 deletions
diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index 6299ae802a7..20d1193b8e2 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -160,13 +160,14 @@ int main(int argc, char** argv) // Close the Database Pool and library StopDB(); - _ioService.reset(); - TC_LOG_INFO("server.bnetserver", "Halting process..."); + + signals.clear(); + + _ioService.reset(); return 0; } - /// Initialize connection to the database bool StartDB() { diff --git a/src/server/bnetserver/Packets/BitStream.h b/src/server/bnetserver/Packets/BitStream.h index f780a4dd867..432f0243149 100644 --- a/src/server/bnetserver/Packets/BitStream.h +++ b/src/server/bnetserver/Packets/BitStream.h @@ -28,6 +28,12 @@ namespace Battlenet { + union FloatToInt + { + float AsFloat; + uint32 AsInt; + }; + class BitStreamPositionException : public std::exception { static uint32 const MessageSize = 128; @@ -102,8 +108,14 @@ namespace Battlenet float ReadFloat() { - uint32 val = Read<uint32>(32); - return *reinterpret_cast<float*>(&val); + union + { + float AsFloat; + uint32 AsInt; + } convert; + + convert.AsInt = Read<uint32>(32); + return convert.AsFloat; } std::string ReadFourCC() @@ -167,8 +179,14 @@ namespace Battlenet void WriteFloat(float value) { - uint32 intVal = *reinterpret_cast<uint32*>(&value); - Write(intVal, 32); + union + { + float AsFloat; + uint32 AsInt; + } convert; + + convert.AsFloat = value; + Write(convert.AsInt, 32); } void WriteFourCC(std::string const& fcc) diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp index 9345f1b659c..89818873335 100644 --- a/src/server/bnetserver/Server/Session.cpp +++ b/src/server/bnetserver/Server/Session.cpp @@ -92,9 +92,10 @@ Battlenet::Session::Session(tcp::socket&& socket) : Socket(std::move(socket)), _ Battlenet::Session::~Session() { - delete _accountInfo; if (_authed) sSessionMgr.RemoveSession(this); + + delete _accountInfo; } void Battlenet::Session::_SetVSFields(std::string const& pstr) diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index bb752fd9b49..25a9a86bc1b 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -24,6 +24,9 @@ namespace MMAP { + static char const* const MAP_FILE_NAME_FORMAT = "%smmaps/%04i.mmap"; + static char const* const TILE_FILE_NAME_FORMAT = "%smmaps/%04i%02i%02i.mmtile"; + // ######################## MMapManager ######################## MMapManager::~MMapManager() { @@ -41,15 +44,11 @@ namespace MMAP return true; // load and init dtNavMesh - read parameters from file - uint32 pathLen = uint32(sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap") + 1); - char *fileName = new char[pathLen]; - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId); - - FILE* file = fopen(fileName, "rb"); + std::string fileName = Trinity::StringFormat(MAP_FILE_NAME_FORMAT, sWorld->GetDataPath().c_str(), mapId); + FILE* file = fopen(fileName.c_str(), "rb"); if (!file) { - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName); - delete [] fileName; + TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName.c_str()); return false; } @@ -58,8 +57,7 @@ namespace MMAP fclose(file); if (count != 1) { - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName); - delete [] fileName; + TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName.c_str()); return false; } @@ -68,14 +66,11 @@ namespace MMAP if (dtStatusFailed(mesh->init(¶ms))) { dtFreeNavMesh(mesh); - TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); - delete [] fileName; + TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %04u from file %s", mapId, fileName.c_str()); return false; } - delete [] fileName; - - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId); + TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %04i.mmap", mapId); // store inside our map list MMapData* mmap_data = new MMapData(mesh, mapId); @@ -104,33 +99,27 @@ namespace MMAP if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end()) return false; - // load this tile :: mmaps/MMMXXYY.mmtile - uint32 pathLen = uint32(sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1); - char *fileName = new char[pathLen]; - - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); - - FILE* file = fopen(fileName, "rb"); + // load this tile :: mmaps/MMMMXXYY.mmtile + std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, sWorld->GetDataPath().c_str(), mapId, x, y); + FILE* file = fopen(fileName.c_str(), "rb"); if (!file) { - TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName); - delete [] fileName; + TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName.c_str()); return false; } - delete [] fileName; // read header MmapTileHeader fileHeader; if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC) { - TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap %04u%02i%02i.mmtile", mapId, x, y); fclose(file); return false; } if (fileHeader.mmapVersion != MMAP_VERSION) { - TC_LOG_ERROR("maps", "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", + TC_LOG_ERROR("maps", "MMAP:loadMap: %04u%02i%02i.mmtile was built with generator v%i, expected v%i", mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); fclose(file); return false; @@ -142,7 +131,7 @@ namespace MMAP size_t result = fread(data, fileHeader.size, 1, file); if (!result) { - TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap %04u%02i%02i.mmtile", mapId, x, y); fclose(file); return false; } @@ -157,14 +146,14 @@ namespace MMAP { mmap->loadedTileRefs.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef)); ++loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y); + TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %04i[%02i, %02i] into %04i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y); LoadPhaseTiles(mapId, x, y); return true; } - TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y); + TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %04u%02i%02i.mmtile into navmesh", mapId, x, y); dtFree(data); return false; } @@ -172,34 +161,28 @@ namespace MMAP PhasedTile* MMapManager::LoadTile(uint32 mapId, int32 x, int32 y) { // load this tile :: mmaps/MMMXXYY.mmtile - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1; - char *fileName = new char[pathLen]; - - snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); - - FILE* file = fopen(fileName, "rb"); + std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, sWorld->GetDataPath().c_str(), mapId, x, y); + FILE* file = fopen(fileName.c_str(), "rb"); if (!file) { // Not all tiles have phased versions, don't flood this msg //TC_LOG_DEBUG("phase", "MMAP:LoadTile: Could not open mmtile file '%s'", fileName); - delete[] fileName; return NULL; } - delete[] fileName; PhasedTile* pTile = new PhasedTile(); // read header if (fread(&pTile->fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || pTile->fileHeader.mmapMagic != MMAP_MAGIC) { - TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header in mmap %04u%02i%02i.mmtile", mapId, x, y); fclose(file); return NULL; } if (pTile->fileHeader.mmapVersion != MMAP_VERSION) { - TC_LOG_ERROR("phase", "MMAP:LoadTile: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", + TC_LOG_ERROR("phase", "MMAP:LoadTile: %04u%02i%02i.mmtile was built with generator v%i, expected v%i", mapId, x, y, pTile->fileHeader.mmapVersion, MMAP_VERSION); fclose(file); return NULL; @@ -211,7 +194,7 @@ namespace MMAP size_t result = fread(pTile->data, pTile->fileHeader.size, 1, file); if (!result) { - TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header or data in mmap %04u%02i%02i.mmtile", mapId, x, y); fclose(file); return NULL; } @@ -237,7 +220,7 @@ namespace MMAP // only a few tiles have terrain swaps, do not write error for them if (data) { - TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loaded phased %03u%02i%02i.mmtile for root phase map %u", map->ID, x, y, mapId); + TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loaded phased %04u%02i%02i.mmtile for root phase map %u", map->ID, x, y, mapId); _phaseTiles[map->ID][packedGridPos] = data; } } @@ -256,7 +239,7 @@ namespace MMAP if (_phaseTiles[mapId][packedGridPos]) { - TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloaded phased %03u%02i%02i.mmtile for root phase map %u", mapId, x, y, rootMapId); + TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloaded phased %04u%02i%02i.mmtile for root phase map %u", mapId, x, y, rootMapId); delete _phaseTiles[mapId][packedGridPos]->data; delete _phaseTiles[mapId][packedGridPos]; _phaseTiles[mapId].erase(packedGridPos); @@ -269,7 +252,7 @@ namespace MMAP if (loadedMMaps.find(mapId) == loadedMMaps.end()) { // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %04u%02i%02i.mmtile", mapId, x, y); return false; } @@ -280,7 +263,7 @@ namespace MMAP if (mmap->loadedTileRefs.find(packedGridPos) == mmap->loadedTileRefs.end()) { // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %04u%02i%02i.mmtile", mapId, x, y); return false; } @@ -292,14 +275,14 @@ namespace MMAP // this is technically a memory leak // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used // we cannot recover from this error - assert out - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); + TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %04u%02i%02i.mmtile from navmesh", mapId, x, y); ASSERT(false); } else { mmap->loadedTileRefs.erase(packedGridPos); --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %04i", mapId, x, y, mapId); UnloadPhaseTile(mapId, x, y); return true; @@ -313,7 +296,7 @@ namespace MMAP if (loadedMMaps.find(mapId) == loadedMMaps.end()) { // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId); + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %04u", mapId); return false; } @@ -324,18 +307,18 @@ namespace MMAP uint32 x = (i->first >> 16); uint32 y = (i->first & 0x0000FFFF); if (dtStatusFailed(mmap->navMesh->removeTile(i->second, NULL, NULL))) - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); + TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %04u%02i%02i.mmtile from navmesh", mapId, x, y); else { UnloadPhaseTile(mapId, x, y); --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %04i[%02i, %02i] from %04i", mapId, x, y, mapId); } } delete mmap; loadedMMaps.erase(mapId); - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %03i.mmap", mapId); + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %04i.mmap", mapId); return true; } @@ -346,14 +329,14 @@ namespace MMAP if (loadedMMaps.find(mapId) == loadedMMaps.end()) { // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId); + TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %04u", mapId); return false; } MMapData* mmap = loadedMMaps[mapId]; if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) { - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId); + TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %04u instanceId %u", mapId, instanceId); return false; } @@ -361,7 +344,7 @@ namespace MMAP dtFreeNavMeshQuery(query); mmap->navMeshQueries.erase(instanceId); - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); + TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %04u instanceId %u", mapId, instanceId); return true; } @@ -388,11 +371,11 @@ namespace MMAP if (dtStatusFailed(query->init(mmap->GetNavMesh(swaps), 1024))) { dtFreeNavMeshQuery(query); - TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %04u instanceId %u", mapId, instanceId); return NULL; } - TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %04u instanceId %u", mapId, instanceId); mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query)); } @@ -426,25 +409,25 @@ namespace MMAP if (loadedPhasedTiles[swap].find(packedXY) == loadedPhasedTiles[swap].end()) { - TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: mmtile %03u[%02i, %02i] unload skipped, due to not loaded", swap, x, y); + TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: mmtile %04u[%02i, %02i] unload skipped, due to not loaded", swap, x, y); return; } dtMeshHeader* header = (dtMeshHeader*)ptile->data; // remove old tile if (dtStatusFailed(navMesh->removeTile(loadedTileRefs[packedXY], NULL, NULL))) - TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not unload phased %03u%02i%02i.mmtile from navmesh", swap, x, y); + TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not unload phased %04u%02i%02i.mmtile from navmesh", swap, x, y); else { - TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Unloaded phased %03u%02i%02i.mmtile from navmesh", swap, x, y); + TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Unloaded phased %04u%02i%02i.mmtile from navmesh", swap, x, y); // restore base tile if (dtStatusSucceed(navMesh->addTile(_baseTiles[packedXY]->data, _baseTiles[packedXY]->dataSize, 0, 0, &loadedTileRefs[packedXY]))) { - TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Loaded base mmtile %03u[%02i, %02i] into %03i[%02i, %02i]", _mapId, x, y, _mapId, header->x, header->y); + TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Loaded base mmtile %04u[%02i, %02i] into %04i[%02i, %02i]", _mapId, x, y, _mapId, header->x, header->y); } else - TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not load base %03u%02i%02i.mmtile to navmesh", _mapId, x, y); + TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not load base %04u%02i%02i.mmtile to navmesh", _mapId, x, y); } loadedPhasedTiles[swap].erase(packedXY); @@ -464,12 +447,12 @@ namespace MMAP if (loadedTileRefs.find(packedXY) == loadedTileRefs.end()) { - TC_LOG_DEBUG("phase", "MMapData::AddSwap: phased mmtile %03u[%02i, %02i] load skipped, due to not loaded base tile on map %u", swap, x, y, _mapId); + TC_LOG_DEBUG("phase", "MMapData::AddSwap: phased mmtile %04u[%02i, %02i] load skipped, due to not loaded base tile on map %u", swap, x, y, _mapId); return; } if (loadedPhasedTiles[swap].find(packedXY) != loadedPhasedTiles[swap].end()) { - TC_LOG_DEBUG("phase", "MMapData::AddSwap: WARNING! phased mmtile %03u[%02i, %02i] load skipped, due to already loaded on map %u", swap, x, y, _mapId); + TC_LOG_DEBUG("phase", "MMapData::AddSwap: WARNING! phased mmtile %04u[%02i, %02i] load skipped, due to already loaded on map %u", swap, x, y, _mapId); return; } @@ -480,25 +463,22 @@ namespace MMAP if (!oldTile) { - TC_LOG_DEBUG("phase", "MMapData::AddSwap: phased mmtile %03u[%02i, %02i] load skipped, due to not loaded base tile ref on map %u", swap, x, y, _mapId); + TC_LOG_DEBUG("phase", "MMapData::AddSwap: phased mmtile %04u[%02i, %02i] load skipped, due to not loaded base tile ref on map %u", swap, x, y, _mapId); return; } - uint32 old_x = oldTile->header->x; - uint32 old_y = oldTile->header->y; - // header xy is based on the swap map's tile set, wich doesn't have all the same tiles as root map, so copy the xy from the orignal header - memcpy(ptile->data + 8, (char*)&old_x, 4); - memcpy(ptile->data + 12, (char*)&old_y, 4); + header->x = oldTile->header->x; + header->y = oldTile->header->y; // the removed tile's data PhasedTile* pt = new PhasedTile(); // remove old tile if (dtStatusFailed(navMesh->removeTile(loadedTileRefs[packedXY], &pt->data, &pt->dataSize))) - TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not unload %03u%02i%02i.mmtile from navmesh", _mapId, x, y); + TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not unload %04u%02i%02i.mmtile from navmesh", _mapId, x, y); else { - TC_LOG_DEBUG("phase", "MMapData::AddSwap: Unloaded %03u%02i%02i.mmtile from navmesh", _mapId, x, y); + TC_LOG_DEBUG("phase", "MMapData::AddSwap: Unloaded %04u%02i%02i.mmtile from navmesh", _mapId, x, y); // store the removed data first time, this is the origonal, non-phased tile if (_baseTiles.find(packedXY) == _baseTiles.end()) @@ -510,43 +490,38 @@ namespace MMAP // add new swapped tile if (dtStatusSucceed(navMesh->addTile(ptile->data, ptile->fileHeader.size, 0, 0, &loadedTileRefs[packedXY]))) { - TC_LOG_DEBUG("phase", "MMapData::AddSwap: Loaded phased mmtile %03u[%02i, %02i] into %03i[%02i, %02i]", swap, x, y, _mapId, header->x, header->y); + TC_LOG_DEBUG("phase", "MMapData::AddSwap: Loaded phased mmtile %04u[%02i, %02i] into %04i[%02i, %02i]", swap, x, y, _mapId, header->x, header->y); } else - TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not load %03u%02i%02i.mmtile to navmesh", swap, x, y); + TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not load %04u%02i%02i.mmtile to navmesh", swap, x, y); } } dtNavMesh* MMapData::GetNavMesh(TerrainSet swaps) { - for (uint32 swap : _activeSwaps) + std::set<uint32> activeSwaps = _activeSwaps; // _activeSwaps is modified inside RemoveSwap + for (uint32 swap : activeSwaps) { - if (swaps.find(swap) == swaps.end()) // swap not active + if (!swaps.count(swap)) // swap not active { PhaseTileContainer ptc = MMAP::MMapFactory::createOrGetMMapManager()->GetPhaseTileContainer(swap); for (PhaseTileContainer::const_iterator itr = ptc.begin(); itr != ptc.end(); ++itr) - { RemoveSwap(itr->second, swap, itr->first); // remove swap - } } } - if (!swaps.empty()) + // for each of the calling unit's terrain swaps + for (uint32 swap : swaps) { - // for each of the calling unit's terrain swaps - for (uint32 swap : swaps) + if (!_activeSwaps.count(swap)) // swap not active { // for each of the terrain swap's xy tiles PhaseTileContainer ptc = MMAP::MMapFactory::createOrGetMMapManager()->GetPhaseTileContainer(swap); for (PhaseTileContainer::const_iterator itr = ptc.begin(); itr != ptc.end(); ++itr) - { - if (_activeSwaps.find(swap) == _activeSwaps.end()) // swap not active - { - AddSwap(itr->second, swap, itr->first); // add swap - } - } + AddSwap(itr->second, swap, itr->first); // add swap } } + return navMesh; } } diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index f9fcff96ad2..0c3ff1a9bfa 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -66,7 +66,7 @@ namespace VMAP std::string VMapManager2::getMapFileName(unsigned int mapId) { std::stringstream fname; - fname.width(3); + fname.width(4); fname << std::setfill('0') << mapId << std::string(MAP_FILENAME_EXTENSION2); return fname.str(); diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index b493ec18f5f..862f3e1cefe 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -90,7 +90,7 @@ namespace VMAP { std::stringstream tilefilename; tilefilename.fill('0'); - tilefilename << std::setw(3) << mapID << '_'; + tilefilename << std::setw(4) << mapID << '_'; //tilefilename << std::setw(2) << tileX << '_' << std::setw(2) << tileY << ".vmtile"; tilefilename << std::setw(2) << tileY << '_' << std::setw(2) << tileX << ".vmtile"; return tilefilename.str(); diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp index 172c556b9a7..86391d5488a 100644 --- a/src/server/collision/Maps/TileAssembler.cpp +++ b/src/server/collision/Maps/TileAssembler.cpp @@ -116,7 +116,7 @@ namespace VMAP // write map tree file std::stringstream mapfilename; - mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree"; + mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(4) << map_iter->first << ".vmtree"; FILE* mapfile = fopen(mapfilename.str().c_str(), "wb"); if (!mapfile) { @@ -157,7 +157,7 @@ namespace VMAP uint32 nSpawns = tileEntries.count(tile->first); std::stringstream tilefilename; tilefilename.fill('0'); - tilefilename << iDestDir << '/' << std::setw(3) << map_iter->first << '_'; + tilefilename << iDestDir << '/' << std::setw(4) << map_iter->first << '_'; uint32 x, y; StaticMapTree::unpackTileID(tile->first, x, y); tilefilename << std::setw(2) << x << '_' << std::setw(2) << y << ".vmtile"; diff --git a/src/server/collision/VMapDefinitions.h b/src/server/collision/VMapDefinitions.h index 8d18372d2b1..7234256f069 100644 --- a/src/server/collision/VMapDefinitions.h +++ b/src/server/collision/VMapDefinitions.h @@ -25,8 +25,8 @@ namespace VMAP { - const char VMAP_MAGIC[] = "VMAP_4.2"; - const char RAW_VMAP_MAGIC[] = "VMAP042"; // used in extracted vmap files with raw data + const char VMAP_MAGIC[] = "VMAP_4.3"; + const char RAW_VMAP_MAGIC[] = "VMAP043"; // used in extracted vmap files with raw data const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; // defined in TileAssembler.cpp currently... diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp index ac61d455b4c..8a37186d0af 100644 --- a/src/server/game/AI/CreatureAISelector.cpp +++ b/src/server/game/AI/CreatureAISelector.cpp @@ -53,7 +53,7 @@ namespace FactorySelector ai_factory = ai_registry.GetRegistryItem("VehicleAI"); else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER) ai_factory = ai_registry.GetRegistryItem("PetAI"); - else if (creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) + else if (creature->HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) ai_factory = ai_registry.GetRegistryItem("NullCreatureAI"); else if (creature->IsGuard()) ai_factory = ai_registry.GetRegistryItem("GuardAI"); @@ -95,7 +95,7 @@ namespace FactorySelector // select NullCreatureAI if not another cases ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key(); - TC_LOG_DEBUG("scripts", "Creature %s (%s DB GUID: " UI64FMTD ") is using AI type: %s.", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), creature->GetDBTableGUIDLow(), ainame.c_str()); + TC_LOG_DEBUG("scripts", "Creature %s (%s DB GUID: " UI64FMTD ") is using AI type: %s.", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), creature->GetSpawnId(), ainame.c_str()); return (ai_factory == NULL ? new NullCreatureAI(creature) : ai_factory->Create(creature)); } diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index bc26fc42df8..66164730219 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -478,7 +478,7 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false } //disable npcflags - me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + me->SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)) { HasImmuneToNPCFlags = true; diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index 720847b2f20..ab91b0b5b27 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -313,7 +313,7 @@ void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, const Qu TC_LOG_DEBUG("scripts", "FollowerAI start with WAYPOINT_MOTION_TYPE, set to MoveIdle."); } - me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + me->SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); AddFollowState(STATE_FOLLOW_INPROGRESS); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index d59f0130c9c..f50bf1fe0e1 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -1355,7 +1355,31 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_SET_COUNTER: { - StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset); + if (ObjectList* targets = GetTargets(e, unit)) + { + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + { + if (IsCreature(*itr)) + { + if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI())) + ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset); + else + TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartAI, skipping"); + } + else if (IsGameObject(*itr)) + { + if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI())) + ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset); + else + TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartGameObjectAI, skipping"); + } + } + + delete targets; + } + else + StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset); + break; } case SMART_ACTION_WP_START: @@ -1681,7 +1705,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) if (IsCreature(*itr)) - (*itr)->ToUnit()->SetUInt32Value(UNIT_NPC_FLAGS, e.action.unitFlag.flag); + (*itr)->ToUnit()->SetUInt64Value(UNIT_NPC_FLAGS, e.action.unitFlag.flag); delete targets; break; @@ -1694,7 +1718,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) if (IsCreature(*itr)) - (*itr)->ToUnit()->SetFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag); + (*itr)->ToUnit()->SetFlag64(UNIT_NPC_FLAGS, e.action.unitFlag.flag); delete targets; break; @@ -1707,7 +1731,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) if (IsCreature(*itr)) - (*itr)->ToUnit()->RemoveFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag); + (*itr)->ToUnit()->RemoveFlag64(UNIT_NPC_FLAGS, e.action.unitFlag.flag); delete targets; break; @@ -3470,14 +3494,14 @@ void SmartScript::GetScript() SmartAIEventList e; if (me) { - e = sSmartScriptMgr->GetScript(-((int32)me->GetDBTableGUIDLow()), mScriptType); + e = sSmartScriptMgr->GetScript(-((int32)me->GetSpawnId()), mScriptType); if (e.empty()) e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType); FillScript(e, me, NULL); } else if (go) { - e = sSmartScriptMgr->GetScript(-((int32)go->GetDBTableGUIDLow()), mScriptType); + e = sSmartScriptMgr->GetScript(-((int32)go->GetSpawnId()), mScriptType); if (e.empty()) e = sSmartScriptMgr->GetScript((int32)go->GetEntry(), mScriptType); FillScript(e, go, NULL); @@ -3667,5 +3691,12 @@ void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry) Unit* SmartScript::GetLastInvoker() { - return ObjectAccessor::FindUnit(mLastInvoker); + WorldObject* lookupRoot = me; + if (!lookupRoot) + lookupRoot = go; + + if (lookupRoot) + return ObjectAccessor::GetUnit(*lookupRoot, mLastInvoker); + + return ObjectAccessor::FindPlayer(mLastInvoker); } diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index f13bcf3050b..0233d1aa7d0 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -118,7 +118,7 @@ class SmartScript smart = false; if (!smart) - TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: " UI64FMTD " Entry: %u) is not using SmartAI, action called by Creature (GUID: " UI64FMTD " Entry: %u) skipped to prevent crash.", uint64(c ? c->GetDBTableGUIDLow() : UI64LIT(0)), c ? c->GetEntry() : 0, uint64(me ? me->GetDBTableGUIDLow() : UI64LIT(0)), me ? me->GetEntry() : 0); + TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: " UI64FMTD " Entry: %u) is not using SmartAI, action called by Creature (GUID: " UI64FMTD " Entry: %u) skipped to prevent crash.", uint64(c ? c->GetSpawnId() : UI64LIT(0)), c ? c->GetEntry() : 0, uint64(me ? me->GetSpawnId() : UI64LIT(0)), me ? me->GetEntry() : 0); return smart; } @@ -132,7 +132,7 @@ class SmartScript if (!go || go->GetAIName() != "SmartGameObjectAI") smart = false; if (!smart) - TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: " UI64FMTD " Entry: %u) is not using SmartGameObjectAI, action called by GameObject (GUID: " UI64FMTD " Entry: %u) skipped to prevent crash.", uint64(g ? g->GetDBTableGUIDLow() : UI64LIT(0)), g ? g->GetEntry() : 0, uint64(go ? go->GetDBTableGUIDLow() : UI64LIT(0)), go ? go->GetEntry() : 0); + TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: " UI64FMTD " Entry: %u) is not using SmartGameObjectAI, action called by GameObject (GUID: " UI64FMTD " Entry: %u) skipped to prevent crash.", uint64(g ? g->GetSpawnId() : UI64LIT(0)), g ? g->GetEntry() : 0, uint64(go ? go->GetSpawnId() : UI64LIT(0)), go ? go->GetEntry() : 0); return smart; } @@ -211,20 +211,27 @@ class SmartScript void OnReset(); void ResetBaseObject() { - if (!meOrigGUID.IsEmpty()) + WorldObject* lookupRoot = me; + if (!lookupRoot) + lookupRoot = go; + + if (lookupRoot) { - if (Creature* m = HashMapHolder<Creature>::Find(meOrigGUID)) + if (!meOrigGUID.IsEmpty()) { - me = m; - go = NULL; + if (Creature* m = ObjectAccessor::GetCreature(*lookupRoot, meOrigGUID)) + { + me = m; + go = NULL; + } } - } - if (!goOrigGUID.IsEmpty()) - { - if (GameObject* o = HashMapHolder<GameObject>::Find(goOrigGUID)) + if (!goOrigGUID.IsEmpty()) { - me = NULL; - go = o; + if (GameObject* o = ObjectAccessor::GetGameObject(*lookupRoot, goOrigGUID)) + { + me = NULL; + go = o; + } } } goOrigGUID.Clear(); diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index e913880ac77..40ab7ebc52e 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -59,9 +59,9 @@ enum RBACPermissions // 7 - reuse // 8 - reuse // 9 - reuse - // 10 - reuse + RBAC_PERM_USE_CHARACTER_TEMPLATES = 10, RBAC_PERM_LOG_GM_TRADE = 11, - // 12 - reuse + // 12 - reuse RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13, RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK = 14, RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK = 15, @@ -566,7 +566,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_RELOAD_LOCALES_CRETURE_TEXT = 659, RBAC_PERM_COMMAND_RELOAD_LOCALES_GAMEOBJECT = 660, RBAC_PERM_COMMAND_RELOAD_LOCALES_GOSSIP_MENU_OPTION = 661, - // UNUSED + RBAC_PERM_COMMAND_RELOAD_CHARACTER_TEMPLATE = 662, RBAC_PERM_COMMAND_RELOAD_LOCALES_ITEM_SET_NAME = 663, RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING = 664, RBAC_PERM_COMMAND_RELOAD_LOCALES_PAGE_TEXT = 665, @@ -738,6 +738,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_TICKET_RESET_BUG = 831, RBAC_PERM_COMMAND_TICKET_RESET_COMPLAINT = 832, RBAC_PERM_COMMAND_TICKET_RESET_SUGGESTION = 833, + RBAC_PERM_COMMAND_GO_QUEST = 834, // custom permissions 1000+ RBAC_PERM_MAX diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp index 2b34d308763..76b2d849a73 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp @@ -320,7 +320,7 @@ bool AuctionBotSeller::Initialize() continue; } - if (prototype->GetFlags() & ITEM_FLAG_UNLOCKED) + if (prototype->GetFlags() & ITEM_FIELD_FLAG_UNLOCKED) { // skip any not locked lootable items (mostly quest specific or reward cases) if (!prototype->GetLockID()) diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index dc1b666a921..fbd49acaf0b 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -793,7 +793,7 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl } Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), map, PHASEMASK_NORMAL, entry, x, y, z, o)) + if (!creature->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, PHASEMASK_NORMAL, entry, x, y, z, o)) { TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Can't create creature entry: %u", entry); delete creature; @@ -829,7 +829,7 @@ GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z // Create gameobject GameObject* go = new GameObject; - if (!go->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), entry, map, PHASEMASK_NORMAL, x, y, z, o, 0, 0, 0, 0, 100, GO_STATE_READY)) + if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, x, y, z, o, 0, 0, 0, 0, 100, GO_STATE_READY)) { TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Cannot create gameobject template %u! Battlefield not created!", entry); delete go; diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 72ab49f34d4..c6c46c48f50 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -1313,7 +1313,7 @@ bool Battleground::HasFreeSlots() const void Battleground::BuildPvPLogDataPacket(WorldPackets::Battleground::PVPLogData& pvpLogData) { if (GetStatus() == STATUS_WAIT_LEAVE) - pvpLogData.Winner.Set(GetWinner()); + pvpLogData.Winner = GetWinner(); pvpLogData.Players.reserve(GetPlayerScoresSize()); for (auto const& score : PlayerScores) @@ -1325,19 +1325,17 @@ void Battleground::BuildPvPLogDataPacket(WorldPackets::Battleground::PVPLogData& playerData.Faction = score.second->TeamId; if (score.second->HonorableKills || score.second->Deaths || score.second->BonusHonor) { - WorldPackets::Battleground::PVPLogData::HonorData& honorData = playerData.Honor.Value; - honorData.HonorKills = score.second->HonorableKills; - honorData.Deaths = score.second->Deaths; - honorData.ContributionPoints = score.second->BonusHonor; - - playerData.Honor.HasValue = true; + playerData.Honor = boost::in_place(); + playerData.Honor->HonorKills = score.second->HonorableKills; + playerData.Honor->Deaths = score.second->Deaths; + playerData.Honor->ContributionPoints = score.second->BonusHonor; } playerData.DamageDone = score.second->DamageDone; playerData.HealingDone = score.second->HealingDone; score.second->BuildObjectivesBlock(playerData.Stats); - if (Player* player = ObjectAccessor::GetObjectInMap(playerData.PlayerGUID, GetBgMap(), (Player*)nullptr)) + if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), playerData.PlayerGUID)) { playerData.IsInWorld = true; playerData.PrimaryTalentTree = player->GetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID); @@ -1356,15 +1354,14 @@ void Battleground::BuildPvPLogDataPacket(WorldPackets::Battleground::PVPLogData& if (isRated()) { - WorldPackets::Battleground::PVPLogData::RatingData& ratingData = pvpLogData.Ratings.Value; + pvpLogData.Ratings = boost::in_place(); + for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i) { - ratingData.Postmatch[i] = _arenaTeamScores[i].NewRating; - ratingData.Prematch[i] = _arenaTeamScores[i].OldRating; - ratingData.PrematchMMR[i] = _arenaTeamScores[i].MatchmakerRating; + pvpLogData.Ratings->Postmatch[i] = _arenaTeamScores[i].NewRating; + pvpLogData.Ratings->Prematch[i] = _arenaTeamScores[i].OldRating; + pvpLogData.Ratings->PrematchMMR[i] = _arenaTeamScores[i].MatchmakerRating; } - - pvpLogData.Ratings.HasValue = true; } pvpLogData.PlayerCount[0] = int8(GetPlayersCountByTeam(HORDE)); @@ -1448,7 +1445,7 @@ bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created // So we must create it specific for this instance GameObject* go = new GameObject; - if (!go->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), entry, GetBgMap(), + if (!go->Create(GetBgMap()->GenerateLowGuid<HighGuid::GameObject>(), entry, GetBgMap(), PHASEMASK_NORMAL, x, y, z, o, rotation0, rotation1, rotation2, rotation3, 100, goState)) { TC_LOG_ERROR("bg.battleground", "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!", @@ -1592,7 +1589,7 @@ Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y, Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), map, PHASEMASK_NORMAL, entry, x, y, z, o)) + if (!creature->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, PHASEMASK_NORMAL, entry, x, y, z, o)) { TC_LOG_ERROR("bg.battleground", "Battleground::AddCreature: cannot create creature (entry: %u) for BG (map: %u, instance id: %u)!", entry, m_MapId, m_InstanceID); diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 1bb636078e2..a227dc1a07b 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -471,8 +471,8 @@ void BattlegroundMgr::LoadBattlegroundTemplates() _battlegroundMapTemplates.clear(); _battlegroundTemplates.clear(); - // 0 1 2 3 4 5 6 7 8 9 10 11 - QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template"); + // 0 1 2 3 4 5 6 7 8 9 + QueryResult result = WorldDatabase.Query("SELECT ID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, HordeStartLoc, StartMaxDist, Weight, ScriptName FROM battleground_template"); if (!result) { TC_LOG_ERROR("server.loading", ">> Loaded 0 battlegrounds. DB table `battleground_template` is empty."); @@ -504,22 +504,22 @@ void BattlegroundMgr::LoadBattlegroundTemplates() bgTemplate.MaxPlayersPerTeam = fields[2].GetUInt16(); bgTemplate.MinLevel = fields[3].GetUInt8(); bgTemplate.MaxLevel = fields[4].GetUInt8(); - float dist = fields[9].GetFloat(); + float dist = fields[7].GetFloat(); bgTemplate.MaxStartDistSq = dist * dist; - bgTemplate.Weight = fields[10].GetUInt8(); - bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[11].GetCString()); + bgTemplate.Weight = fields[8].GetUInt8(); + bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[9].GetCString()); bgTemplate.BattlemasterEntry = bl; if (bgTemplate.MaxPlayersPerTeam == 0 || bgTemplate.MinPlayersPerTeam > bgTemplate.MaxPlayersPerTeam) { - TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has bad values for MinPlayersPerTeam (%u) and MaxPlayersPerTeam(%u)", + TC_LOG_ERROR("sql.sql", "Table `battleground_template` for ID %u has bad values for MinPlayersPerTeam (%u) and MaxPlayersPerTeam(%u)", bgTemplate.Id, bgTemplate.MinPlayersPerTeam, bgTemplate.MaxPlayersPerTeam); continue; } if (bgTemplate.MinLevel == 0 || bgTemplate.MaxLevel == 0 || bgTemplate.MinLevel > bgTemplate.MaxLevel) { - TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has bad values for MinLevel (%u) and MaxLevel (%u)", + TC_LOG_ERROR("sql.sql", "Table `battleground_template` for ID %u has bad values for MinLevel (%u) and MaxLevel (%u)", bgTemplate.Id, bgTemplate.MinLevel, bgTemplate.MaxLevel); continue; } @@ -529,22 +529,22 @@ void BattlegroundMgr::LoadBattlegroundTemplates() uint32 startId = fields[5].GetUInt32(); if (WorldSafeLocsEntry const* start = sWorldSafeLocsStore.LookupEntry(startId)) { - bgTemplate.StartLocation[TEAM_ALLIANCE].Relocate(start->Loc.X, start->Loc.Y, start->Loc.Z, fields[6].GetFloat()); + bgTemplate.StartLocation[TEAM_ALLIANCE].Relocate(start->Loc.X, start->Loc.Y, start->Loc.Z, (start->Facing * M_PI) / 180); } else { - TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has non-existed WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.", bgTemplate.Id, startId); + TC_LOG_ERROR("sql.sql", "Table `battleground_template` for ID %u a non-existant WorldSafeLoc (ID: %u) in field `AllianceStartLoc`. BG not created.", bgTemplate.Id, startId); continue; } - startId = fields[7].GetUInt32(); + startId = fields[6].GetUInt32(); if (WorldSafeLocsEntry const* start = sWorldSafeLocsStore.LookupEntry(startId)) { - bgTemplate.StartLocation[TEAM_HORDE].Relocate(start->Loc.X, start->Loc.Y, start->Loc.Z, fields[8].GetFloat()); + bgTemplate.StartLocation[TEAM_HORDE].Relocate(start->Loc.X, start->Loc.Y, start->Loc.Z, (start->Facing * M_PI) / 180); } else { - TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has non-existed WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.", bgTemplate.Id, startId); + TC_LOG_ERROR("sql.sql", "Table `battleground_template` for ID %u has a non-existant WorldSafeLoc (ID: %u) in field `HordeStartLoc`. BG not created.", bgTemplate.Id, startId); continue; } } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index 8ea632a1dba..8376c3e4584 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -304,7 +304,7 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type) if (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3) || (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3))) { - CreatureData &data = sObjectMgr->NewOrExistCreatureData(creature->GetDBTableGUIDLow()); + CreatureData &data = sObjectMgr->NewOrExistCreatureData(creature->GetSpawnId()); data.spawndist = 5; } //else spawndist will be 15, so creatures move maximum=10 diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index e9e4bbb2a9c..4a96c6a99c0 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -119,7 +119,7 @@ void BattlegroundEY::PostUpdateImpl(uint32 diff) void BattlegroundEY::GetPlayerPositionData(std::vector<WorldPackets::Battleground::BattlegroundPlayerPosition>* positions) const { - if (Player* player = ObjectAccessor::GetObjectInMap(m_FlagKeeper, GetBgMap(), (Player*)nullptr)) + if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), m_FlagKeeper)) { WorldPackets::Battleground::BattlegroundPlayerPosition position; position.Guid = player->GetGUID(); @@ -176,7 +176,7 @@ void BattlegroundEY::CheckSomeoneJoinedPoint() GameObject* obj = NULL; for (uint8 i = 0; i < EY_POINTS_MAX; ++i) { - obj = HashMapHolder<GameObject>::Find(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]); + obj = GetBgMap()->GetGameObject(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]); if (obj) { uint8 j = 0; @@ -216,7 +216,7 @@ void BattlegroundEY::CheckSomeoneLeftPoint() GameObject* obj = NULL; for (uint8 i = 0; i < EY_POINTS_MAX; ++i) { - obj = HashMapHolder<GameObject>::Find(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]); + obj = GetBgMap()->GetGameObject(BgObjects[BG_EY_OBJECT_TOWER_CAP_FEL_REAVER + i]); if (obj) { uint8 j = 0; @@ -603,7 +603,7 @@ void BattlegroundEY::RespawnFlagAfterDrop() { RespawnFlag(true); - GameObject* obj = HashMapHolder<GameObject>::Find(GetDroppedFlagGUID()); + GameObject* obj = GetBgMap()->GetGameObject(GetDroppedFlagGUID()); if (obj) obj->Delete(); else diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 040905a32d4..2c11bd149fd 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -195,7 +195,7 @@ void BattlegroundWS::PostUpdateImpl(uint32 diff) void BattlegroundWS::GetPlayerPositionData(std::vector<WorldPackets::Battleground::BattlegroundPlayerPosition>* positions) const { - if (Player* player = ObjectAccessor::GetObjectInMap(m_FlagKeepers[TEAM_ALLIANCE], GetBgMap(), (Player*)nullptr)) + if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), m_FlagKeepers[TEAM_ALLIANCE])) { WorldPackets::Battleground::BattlegroundPlayerPosition position; position.Guid = player->GetGUID(); @@ -206,7 +206,7 @@ void BattlegroundWS::GetPlayerPositionData(std::vector<WorldPackets::Battlegroun positions->push_back(position); } - if (Player* player = ObjectAccessor::GetObjectInMap(m_FlagKeepers[TEAM_HORDE], GetBgMap(), (Player*)nullptr)) + if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), m_FlagKeepers[TEAM_HORDE])) { WorldPackets::Battleground::BattlegroundPlayerPosition position; position.Guid = player->GetGUID(); diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index caa75c24121..9c3646c39ca 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -24,6 +24,7 @@ file(GLOB_RECURSE sources_DataStores DataStores/*.cpp DataStores/*.h) file(GLOB_RECURSE sources_DungeonFinding DungeonFinding/*.cpp DungeonFinding/*.h) file(GLOB_RECURSE sources_Entities Entities/*.cpp Entities/*.h) file(GLOB_RECURSE sources_Events Events/*.cpp Events/*.h) +file(GLOB_RECURSE sources_Garrison Garrison/*.cpp Garrison/*.h) file(GLOB_RECURSE sources_Globals Globals/*.cpp Globals/*.h) file(GLOB_RECURSE sources_Grids Grids/*.cpp Grids/*.h) file(GLOB_RECURSE sources_Groups Groups/*.cpp Groups/*.h) @@ -75,6 +76,7 @@ set(game_STAT_SRCS ${sources_DungeonFinding} ${sources_Entities} ${sources_Events} + ${sources_Garrison} ${sources_Globals} ${sources_Grids} ${sources_Groups} @@ -172,6 +174,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Vehicle ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Transport ${CMAKE_CURRENT_SOURCE_DIR}/Events + ${CMAKE_CURRENT_SOURCE_DIR}/Garrison ${CMAKE_CURRENT_SOURCE_DIR}/Globals ${CMAKE_CURRENT_SOURCE_DIR}/Grids/Cells ${CMAKE_CURRENT_SOURCE_DIR}/Grids/Notifiers @@ -217,8 +220,8 @@ include_directories( GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_library(game STATIC - ${game_STAT_SRCS} ${game_STAT_PCH_SRC} + ${game_STAT_SRCS} ) add_dependencies(game revision.h) diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 837ff0be60f..c7952d7758c 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -321,9 +321,9 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st std::string zoneName = "Unknown"; if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId)) { - areaName = area->ZoneName; + areaName = area->AreaName_lang; if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID)) - zoneName = zone->ZoneName; + zoneName = zone->AreaName_lang; } sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (%s) (Account: %u) X: %f Y: %f Z: %f Map: %u (%s) Area: %u (%s) Zone: %s Selected: %s (%s)]", diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 5fc7240cb9c..babbbbce153 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -301,10 +301,10 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) switch (object->GetTypeId()) { case TYPEID_UNIT: - condMeets &= object->ToCreature()->GetDBTableGUIDLow() == ConditionValue3; + condMeets &= object->ToCreature()->GetSpawnId() == ConditionValue3; break; case TYPEID_GAMEOBJECT: - condMeets &= object->ToGameObject()->GetDBTableGUIDLow() == ConditionValue3; + condMeets &= object->ToGameObject()->GetSpawnId() == ConditionValue3; break; default: break; diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index bb8f581c1c8..35978810001 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -28,6 +28,14 @@ DB2Storage<AreaGroupMemberEntry> sAreaGroupMemberStore("AreaGroupMemb DB2Storage<BroadcastTextEntry> sBroadcastTextStore("BroadcastText.db2", BroadcastTextFormat, HOTFIX_SEL_BROADCAST_TEXT); DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore("CurrencyTypes.db2", CurrencyTypesFormat, HOTFIX_SEL_CURRENCY_TYPES); DB2Storage<CurvePointEntry> sCurvePointStore("CurvePoint.db2", CurvePointFormat, HOTFIX_SEL_CURVE_POINT); +DB2Storage<GameObjectsEntry> sGameObjectsStore("GameObjects.db2", GameObjectsFormat, HOTFIX_SEL_GAMEOBJECTS); +DB2Storage<GarrBuildingEntry> sGarrBuildingStore("GarrBuilding.db2", GarrBuildingFormat, HOTFIX_SEL_GARR_BUILDING); +DB2Storage<GarrBuildingPlotInstEntry> sGarrBuildingPlotInstStore("GarrBuildingPlotInst.db2", GarrBuildingPlotInstFormat, HOTFIX_SEL_GARR_BUILDING_PLOT_INST); +DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore("GarrPlotBuilding.db2", GarrPlotBuildingFormat, HOTFIX_SEL_GARR_PLOT_BUILDING); +DB2Storage<GarrPlotEntry> sGarrPlotStore("GarrPlot.db2", GarrPlotFormat, HOTFIX_SEL_GARR_PLOT); +DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore("GarrPlotInstance.db2", GarrPlotInstanceFormat, HOTFIX_SEL_GARR_PLOT_INSTANCE); +DB2Storage<GarrSiteLevelEntry> sGarrSiteLevelStore("GarrSiteLevel.db2", GarrSiteLevelFormat, HOTFIX_SEL_GARR_SITE_LEVEL); +DB2Storage<GarrSiteLevelPlotInstEntry> sGarrSiteLevelPlotInstStore("GarrSiteLevelPlotInst.db2", GarrSiteLevelPlotInstFormat, HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST); DB2Storage<HolidaysEntry> sHolidaysStore("Holidays.db2", HolidaysEntryFormat, HOTFIX_SEL_HOLIDAYS); DB2Storage<ItemAppearanceEntry> sItemAppearanceStore("ItemAppearance.db2", ItemAppearanceFormat, HOTFIX_SEL_ITEM_APPEARANCE); DB2Storage<ItemBonusEntry> sItemBonusStore("ItemBonus.db2", ItemBonusFormat, HOTFIX_SEL_ITEM_BONUS); @@ -50,8 +58,8 @@ DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore("Spel DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore("SpellClassOptions.db2", SpellClassOptionsFormat, HOTFIX_SEL_SPELL_CLASS_OPTIONS); DB2Storage<SpellLearnSpellEntry> sSpellLearnSpellStore("SpellLearnSpell.db2", SpellLearnSpellFormat, HOTFIX_SEL_SPELL_LEARN_SPELL); DB2Storage<SpellMiscEntry> sSpellMiscStore("SpellMisc.db2", SpellMiscFormat, HOTFIX_SEL_SPELL_MISC); -DB2Storage<SpellPowerEntry> sSpellPowerStore("SpellPower.db2", SpellPowerFormat, HOTFIX_SEL_SPELL_POWER); DB2Storage<SpellPowerDifficultyEntry> sSpellPowerDifficultyStore("SpellPowerDifficulty.db2", SpellPowerDifficultyFormat, HOTFIX_SEL_SPELL_POWER_DIFFICULTY); +DB2Storage<SpellPowerEntry> sSpellPowerStore("SpellPower.db2", SpellPowerFormat, HOTFIX_SEL_SPELL_POWER); DB2Storage<SpellReagentsEntry> sSpellReagentsStore("SpellReagents.db2", SpellReagentsFormat, HOTFIX_SEL_SPELL_REAGENTS); DB2Storage<SpellRuneCostEntry> sSpellRuneCostStore("SpellRuneCost.db2", SpellRuneCostFormat, HOTFIX_SEL_SPELL_RUNE_COST); DB2Storage<SpellTotemsEntry> sSpellTotemsStore("SpellTotems.db2", SpellTotemsFormat, HOTFIX_SEL_SPELL_TOTEMS); @@ -125,41 +133,53 @@ void DB2Manager::LoadStores(std::string const& dataPath) DB2StoreProblemList bad_db2_files; uint32 availableDb2Locales = 0xFF; - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sAreaGroupStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sAreaGroupMemberStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sBroadcastTextStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sCurrencyTypesStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sCurvePointStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sHolidaysStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemAppearanceStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemBonusStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemBonusTreeNodeStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemCurrencyCostStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemEffectStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemExtendedCostStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemModifiedAppearanceStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemSparseStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemXBonusTreeStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sKeyChainStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sMountStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sOverrideSpellDataStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sPhaseXPhaseGroupStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sQuestPackageItemStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSoundEntriesStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellAuraRestrictionsStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellCastingRequirementsStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellClassOptionsStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellLearnSpellStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellMiscStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellPowerStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellPowerDifficultyStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellReagentsStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellRuneCostStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellTotemsStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiNodesStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiPathNodeStore, db2Path); - LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiPathStore, db2Path); +#define LOAD_DB2(store) LoadDB2(availableDb2Locales, bad_db2_files, _stores, &store, db2Path) + + LOAD_DB2(sAreaGroupMemberStore); + LOAD_DB2(sAreaGroupStore); + LOAD_DB2(sBroadcastTextStore); + LOAD_DB2(sCurrencyTypesStore); + LOAD_DB2(sCurvePointStore); + LOAD_DB2(sGameObjectsStore); + LOAD_DB2(sGarrBuildingPlotInstStore); + LOAD_DB2(sGarrBuildingStore); + LOAD_DB2(sGarrPlotBuildingStore); + LOAD_DB2(sGarrPlotInstanceStore); + LOAD_DB2(sGarrPlotStore); + LOAD_DB2(sGarrSiteLevelPlotInstStore); + LOAD_DB2(sGarrSiteLevelStore); + LOAD_DB2(sHolidaysStore); + LOAD_DB2(sItemAppearanceStore); + LOAD_DB2(sItemBonusStore); + LOAD_DB2(sItemBonusTreeNodeStore); + LOAD_DB2(sItemCurrencyCostStore); + LOAD_DB2(sItemEffectStore); + LOAD_DB2(sItemExtendedCostStore); + LOAD_DB2(sItemModifiedAppearanceStore); + LOAD_DB2(sItemSparseStore); + LOAD_DB2(sItemStore); + LOAD_DB2(sItemXBonusTreeStore); + LOAD_DB2(sKeyChainStore); + LOAD_DB2(sMountStore); + LOAD_DB2(sOverrideSpellDataStore); + LOAD_DB2(sPhaseXPhaseGroupStore); + LOAD_DB2(sQuestPackageItemStore); + LOAD_DB2(sSoundEntriesStore); + LOAD_DB2(sSpellAuraRestrictionsStore); + LOAD_DB2(sSpellCastingRequirementsStore); + LOAD_DB2(sSpellClassOptionsStore); + LOAD_DB2(sSpellLearnSpellStore); + LOAD_DB2(sSpellMiscStore); + LOAD_DB2(sSpellPowerDifficultyStore); + LOAD_DB2(sSpellPowerStore); + LOAD_DB2(sSpellReagentsStore); + LOAD_DB2(sSpellRuneCostStore); + LOAD_DB2(sSpellTotemsStore); + LOAD_DB2(sTaxiNodesStore); + LOAD_DB2(sTaxiPathNodeStore); + LOAD_DB2(sTaxiPathStore); + +#undef LOAD_DB2 for (AreaGroupMemberEntry const* areaGroupMember : sAreaGroupMemberStore) _areaGroupMembers[areaGroupMember->AreaGroupID].push_back(areaGroupMember->AreaID); diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 1095127e882..720cd01531c 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -23,8 +23,16 @@ #include "SharedDefines.h" extern DB2Storage<BroadcastTextEntry> sBroadcastTextStore; -extern DB2Storage<HolidaysEntry> sHolidaysStore; extern DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore; +extern DB2Storage<GameObjectsEntry> sGameObjectsStore; +extern DB2Storage<GarrBuildingEntry> sGarrBuildingStore; +extern DB2Storage<GarrBuildingPlotInstEntry> sGarrBuildingPlotInstStore; +extern DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore; +extern DB2Storage<GarrPlotEntry> sGarrPlotStore; +extern DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore; +extern DB2Storage<GarrSiteLevelEntry> sGarrSiteLevelStore; +extern DB2Storage<GarrSiteLevelPlotInstEntry> sGarrSiteLevelPlotInstStore; +extern DB2Storage<HolidaysEntry> sHolidaysStore; extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore; extern DB2Storage<ItemEffectEntry> sItemEffectStore; extern DB2Storage<ItemEntry> sItemStore; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 912ae5d60d5..cad9ca32e69 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -81,6 +81,112 @@ struct CurvePointEntry float Y; // 4 }; +struct GameObjectsEntry +{ + uint32 ID; // 0 + uint32 MapID; // 1 + uint32 DisplayID; // 2 + DBCPosition3D Position; // 3-5 + float RotationX; // 6 + float RotationY; // 7 + float RotationZ; // 8 + float RotationW; // 9 + float Size; // 10 + uint32 PhaseUseFlags; // 11 + uint32 PhaseID; // 12 + uint32 PhaseGroupID; // 13 + uint32 Type; // 14 + uint32 Data[8]; // 15-22 + LocalizedString* Name; // 23 +}; + +struct GarrBuildingEntry +{ + uint32 ID; // 0 + uint32 HordeGameObjectID; // 1 + uint32 AllianceGameObjectID; // 2 + uint32 Unknown; // 3 + uint32 Type; // 4 + uint32 Level; // 5 + LocalizedString* NameAlliance; // 6 + LocalizedString* NameHorde; // 7 + LocalizedString* Description; // 8 + LocalizedString* Tooltip; // 9 + uint32 BuildDuration; // 10 + uint32 CostCurrencyID; // 11 + int32 CostCurrencyAmount; // 12 + uint32 HordeTexPrefixKitID; // 13 + uint32 AllianceTexPrefixKitID; // 14 + uint32 IconFileDataID; // 15 + uint32 BonusAmount; // 16 + uint32 Flags; // 17 + uint32 AllianceActivationScenePackageID; // 18 + uint32 HordeActivationScenePackageID; // 19 + uint32 MaxShipments; // 20 + uint32 FollowerRequiredGarrAbilityID; // 21 + uint32 FollowerGarrAbilityEffectID; // 22 + int32 CostMoney; // 23 +}; + +struct GarrBuildingPlotInstEntry +{ + uint32 ID; // 0 + uint32 GarrBuildingID; // 1 + uint32 UiTextureAtlasMemberID; // 2 + uint32 GarrSiteLevelPlotInstID; // 3 + DBCPosition2D LandmarkOffset; // 4-5 +}; + +struct GarrPlotEntry +{ + uint32 ID; // 0 + uint32 GarrPlotUICategoryID; // 1 + uint32 PlotType; // 2 + uint32 Flags; // 3 + LocalizedString* Name; // 4 + uint32 MinCount; // 5 + uint32 MaxCount; // 6 + uint32 AllianceConstructionGameObjectID; // 7 + uint32 HordeConstructionGameObjectID; // 8 +}; + +struct GarrPlotBuildingEntry +{ + uint32 ID; // 0 + uint32 GarrPlotID; // 1 + uint32 GarrBuildingID; // 2 +}; + +struct GarrPlotInstanceEntry +{ + uint32 ID; // 0 + uint32 GarrPlotID; // 1 + LocalizedString* Name; // 2 +}; + +struct GarrSiteLevelEntry +{ + uint32 ID; // 0 + uint32 Level; // 1 + uint32 MapID; // 2 + uint32 SiteID; // 3 + uint32 UITextureKitID; // 4 + DBCPosition2D TownHall; // 5-6 + uint32 MovieID; // 7 + uint32 Level2; // 8 + uint32 UpgradeResourceCost; // 9 + uint32 UpgradeMoneyCost; // 10 +}; + +struct GarrSiteLevelPlotInstEntry +{ + uint32 ID; // 0 + uint32 GarrSiteLevelID; // 1 + uint32 GarrPlotInstanceID; // 2 + DBCPosition2D Landmark; // 3-4 + uint32 Unknown; // 5 +}; + struct HolidaysEntry { uint32 ID; // 0 diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h index f59c7b56f56..19622dcc3d2 100644 --- a/src/server/game/DataStores/DB2fmt.h +++ b/src/server/game/DataStores/DB2fmt.h @@ -23,6 +23,14 @@ char const AreaGroupMemberFormat[] = "nii"; char const BroadcastTextFormat[] = "nissiiiiiiiii"; char const CurrencyTypesFormat[] = "nisssiiiiiis"; char const CurvePointFormat[] = "niiff"; +char const GameObjectsFormat[] = "niiffffffffiiiiiiiiiiiis"; +char const GarrBuildingFormat[] = "niiiiissssiiiiiiiiiiiiii"; +char const GarrPlotFormat[] = "niiisiiii"; +char const GarrPlotBuildingFormat[] = "nii"; +char const GarrBuildingPlotInstFormat[] = "niiiff"; +char const GarrPlotInstanceFormat[] = "nis"; +char const GarrSiteLevelFormat[] = "niiiiffiiii"; +char const GarrSiteLevelPlotInstFormat[] = "niiffi"; char const HolidaysEntryFormat[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisiii"; char const ItemFormat[] = "niiiiiiii"; char const ItemAppearanceFormat[] = "nii"; diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index cc310fbdeb5..fc05f0fdc6a 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -21,6 +21,8 @@ #include "Define.h" +#pragma pack(push, 1) + struct DBCPosition2D { float X; @@ -34,6 +36,8 @@ struct DBCPosition3D float Z; }; +#pragma pack(pop) + enum LevelLimit { // Client expected level limitation, like as used in DBC item max levels for "until max player level" @@ -427,6 +431,7 @@ enum MapFlags MAP_FLAG_CAN_TOGGLE_DIFFICULTY = 0x0100, MAP_FLAG_FLEX_LOCKING = 0x8000, // All difficulties share completed encounters lock, not bound to a single instance id // heroic difficulty flag overrides it and uses instance id bind + MAP_FLAG_GARRISON = 0x4000000 }; enum AbilytyLearnType diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index fd6047a8adf..2893ea3df83 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -29,13 +29,7 @@ #include <vector> // Structures using to access raw DBC data and required packing to portability - -// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif struct AchievementEntry { @@ -78,10 +72,10 @@ struct AreaTableEntry //uint32 SoundProviderPrefUnderwater; // 7, //uint32 AmbienceID; // 8, //uint32 ZoneMusic; // 9, - char* ZoneName; // 10 + //char* ZoneName; // 10 - Internal name //uint32 IntroSound; // 11 uint32 ExplorationLevel; // 12 - //char* AreaName_lang // 13 + char* AreaName_lang; // 13 - In-game name uint32 FactionGroupMask; // 14 uint32 LiquidTypeID[4]; // 15-18 //float AmbientMultiplier; // 19 @@ -159,7 +153,7 @@ struct BarberShopStyleEntry uint32 Type; // 1 value 0 -> hair, value 2 -> facialhair //char* DisplayName_lang; // 2 //char* Description_lang // 3 - //float CostModifier; // 4 + float CostModifier; // 4 uint32 Race; // 5 uint32 Sex; // 6 uint32 Data; // 7 (real ID to hair/facial hair) @@ -1241,13 +1235,13 @@ struct MapEntry uint32 RaidOffset; // 17 uint32 MaxPlayers; // 18 int32 ParentMapID; // 19 related to phasing - //uint32 CosmeticParentMapID // 20 + int32 CosmeticParentMapID; // 20 //uint32 TimeOffset // 21 // Helpers uint32 Expansion() const { return ExpansionID; } - bool IsDungeon() const { return InstanceType == MAP_INSTANCE || InstanceType == MAP_RAID; } + bool IsDungeon() const { return (InstanceType == MAP_INSTANCE || InstanceType == MAP_RAID) && !IsGarrison(); } bool IsNonRaidDungeon() const { return InstanceType == MAP_INSTANCE; } bool Instanceable() const { return InstanceType == MAP_INSTANCE || InstanceType == MAP_RAID || InstanceType == MAP_BATTLEGROUND || InstanceType == MAP_ARENA; } bool IsRaid() const { return InstanceType == MAP_RAID; } @@ -1272,6 +1266,7 @@ struct MapEntry } bool IsDynamicDifficultyMap() const { return (Flags & MAP_FLAG_CAN_TOGGLE_DIFFICULTY) != 0; } + bool IsGarrison() const { return (Flags & MAP_FLAG_GARRISON) != 0; } }; struct MapDifficultyEntry @@ -2058,12 +2053,7 @@ struct WorldStateUI }; */ -// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif struct VectorArray { diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 271aca1c43f..e3b474bc27b 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -25,13 +25,13 @@ char const Achievementfmt[] = "niixsxiixixxiii"; const std::string CustomAchievementfmt = "pppaaaapapaapp"; const std::string CustomAchievementIndex = "ID"; -char const AreaTableEntryfmt[] = "iiiniixxxxsxixiiiiixxxxxxxxxx"; +char const AreaTableEntryfmt[] = "iiiniixxxxxxisiiiiixxxxxxxxxx"; char const AreaTriggerEntryfmt[] = "nifffxxxfffffxxxx"; char const ArmorLocationfmt[] = "nfffff"; char const AuctionHouseEntryfmt[] = "niiix"; char const BankBagSlotPricesEntryfmt[] = "ni"; char const BannedAddOnsfmt[] = "nxxxxxxxxxx"; -char const BarberShopStyleEntryfmt[] = "nixxxiii"; +char const BarberShopStyleEntryfmt[] = "nixxfiii"; char const BattlemasterListEntryfmt[] = "niiiiiiiiiiiiiiiiixsiiiixxxxxxx"; char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiiii"; char const CharSectionsEntryfmt[] = "diiixxxiii"; @@ -113,7 +113,7 @@ char const LiquidTypefmt[] = "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx char const LockEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; char const PhaseEntryfmt[] = "ni"; char const MailTemplateEntryfmt[] = "nxs"; -char const MapEntryfmt[] = "nxiixxsixxixiffxiiiixx"; +char const MapEntryfmt[] = "nxiixxsixxixiffxiiiiix"; char const MapDifficultyEntryfmt[] = "diisiiii"; char const MinorTalentEntryfmt[] = "niii"; char const MovieEntryfmt[] = "nxxxx"; diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp index 8850392a13e..b1ce1f0cdbb 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp @@ -15,10 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ObjectAccessor.h" #include "Unit.h" #include "SpellInfo.h" #include "Log.h" +#include "UpdateData.h" #include "AreaTrigger.h" AreaTrigger::AreaTrigger() : WorldObject(false), _duration(0) @@ -41,7 +41,7 @@ void AreaTrigger::AddToWorld() ///- Register the AreaTrigger for guid lookup and for caster if (!IsInWorld()) { - sObjectAccessor->AddObject(this); + GetMap()->GetObjectsStore().Insert<AreaTrigger>(GetGUID(), this); WorldObject::AddToWorld(); } } @@ -52,7 +52,7 @@ void AreaTrigger::RemoveFromWorld() if (IsInWorld()) { WorldObject::RemoveFromWorld(); - sObjectAccessor->RemoveObject(this); + GetMap()->GetObjectsStore().Remove<AreaTrigger>(GetGUID()); } } diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 6be200b8887..4294eb57dbd 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -48,7 +48,7 @@ void Corpse::AddToWorld() { ///- Register the corpse for guid lookup if (!IsInWorld()) - sObjectAccessor->AddObject(this); + GetMap()->GetObjectsStore().Insert<Corpse>(GetGUID(), this); Object::AddToWorld(); } @@ -57,7 +57,7 @@ void Corpse::RemoveFromWorld() { ///- Remove the corpse from the accessor if (IsInWorld()) - sObjectAccessor->RemoveObject(this); + GetMap()->GetObjectsStore().Remove<Corpse>(GetGUID()); Object::RemoveFromWorld(); } @@ -89,7 +89,7 @@ bool Corpse::Create(ObjectGuid::LowType guidlow, Player* owner) Object::_Create(ObjectGuid::Create<HighGuid::Corpse>(GetMapId(), 0, guidlow)); SetPhaseMask(owner->GetPhaseMask(), false); - SetObjectScale(1); + SetObjectScale(1.0f); SetGuidValue(CORPSE_FIELD_OWNER, owner->GetGUID()); _gridCoord = Trinity::ComputeGridCoord(GetPositionX(), GetPositionY()); @@ -107,7 +107,6 @@ void Corpse::SaveToDB() uint16 index = 0; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CORPSE); - stmt->setUInt64(index++, GetGUID().GetCounter()); // corpseGuid stmt->setUInt64(index++, GetOwnerGUID().GetCounter()); // guid stmt->setFloat (index++, GetPositionX()); // posX stmt->setFloat (index++, GetPositionY()); // posY @@ -129,11 +128,8 @@ void Corpse::SaveToDB() { index = 0; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CORPSE_PHASES); - stmt->setUInt32(index++, GetGUID().GetCounter()); // Guid (corpse's) - stmt->setUInt32(index++, phaseId); // PhaseId stmt->setUInt32(index++, GetOwnerGUID().GetCounter()); // OwnerGuid - stmt->setUInt32(index++, uint32(m_time)); // Time - stmt->setUInt8(index++, GetType()); // CorpseType + stmt->setUInt32(index++, phaseId); // PhaseId trans->Append(stmt); } @@ -156,36 +152,19 @@ void Corpse::DeleteBonesFromWorld() void Corpse::DeleteFromDB(SQLTransaction& trans) { - PreparedStatement* stmt = NULL; - if (GetType() == CORPSE_BONES) - { - // Only specific bones - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE); - stmt->setUInt32(0, GetGUID().GetCounter()); - trans->Append(stmt); - - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE_PHASES); - stmt->setUInt32(0, GetGUID().GetCounter()); - trans->Append(stmt); - } - else - { - // all corpses (not bones) - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_CORPSES); - stmt->setUInt32(0, GetOwnerGUID().GetCounter()); - trans->Append(stmt); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE); + stmt->setUInt64(0, GetOwnerGUID().GetCounter()); + trans->Append(stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_CORPSES_PHASES); - stmt->setUInt32(0, GetOwnerGUID().GetCounter()); - trans->Append(stmt); - } + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE_PHASES); + stmt->setUInt64(0, GetOwnerGUID().GetCounter()); + trans->Append(stmt); } bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, corpseGuid, guid FROM corpse WHERE corpseType <> 0 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse float posX = fields[0].GetFloat(); float posY = fields[1].GetFloat(); @@ -195,13 +174,14 @@ bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) Object::_Create(ObjectGuid::Create<HighGuid::Corpse>(mapId, 0, guid)); + SetObjectScale(1.0f); SetUInt32Value(CORPSE_FIELD_DISPLAY_ID, fields[5].GetUInt32()); _LoadIntoDataField(fields[6].GetCString(), CORPSE_FIELD_ITEM, EQUIPMENT_SLOT_END); SetUInt32Value(CORPSE_FIELD_BYTES_1, fields[7].GetUInt32()); SetUInt32Value(CORPSE_FIELD_BYTES_2, fields[8].GetUInt32()); SetUInt32Value(CORPSE_FIELD_FLAGS, fields[9].GetUInt8()); SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, fields[10].GetUInt8()); - SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Create<HighGuid::Player>(fields[15].GetUInt64())); + SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Create<HighGuid::Player>(fields[14].GetUInt64())); m_time = time_t(fields[11].GetUInt32()); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 61be7790ba1..70a2ab2307a 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -147,7 +147,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_groupLootTimer(0), m_PlayerDamageReq(0), _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE), -m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), +m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(NULL), m_creatureData(NULL), m_waypointID(0), m_path_id(0), m_formation(NULL) { @@ -185,7 +185,11 @@ void Creature::AddToWorld() { if (GetZoneScript()) GetZoneScript()->OnCreatureCreate(this); - sObjectAccessor->AddObject(this); + + GetMap()->GetObjectsStore().Insert<Creature>(GetGUID(), this); + if (m_spawnId) + GetMap()->GetCreatureBySpawnIdStore().insert(std::make_pair(m_spawnId, this)); + Unit::AddToWorld(); SearchFormation(); AIM_Initialize(); @@ -200,10 +204,15 @@ void Creature::RemoveFromWorld() { if (GetZoneScript()) GetZoneScript()->OnCreatureRemove(this); + if (m_formation) sFormationMgr->RemoveCreatureFromGroup(m_formation, this); + Unit::RemoveFromWorld(); - sObjectAccessor->RemoveObject(this); + + if (m_spawnId) + Trinity::Containers::MultimapErasePair(GetMap()->GetCreatureBySpawnIdStore(), m_spawnId, this); + GetMap()->GetObjectsStore().Remove<Creature>(GetGUID()); } } @@ -222,7 +231,7 @@ void Creature::SearchFormation() if (IsSummon()) return; - ObjectGuid::LowType lowguid = GetDBTableGUIDLow(); + ObjectGuid::LowType lowguid = GetSpawnId(); if (!lowguid) return; @@ -373,13 +382,14 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/) setFaction(cInfo->faction); - uint32 npcflag, unit_flags, dynamicflags; + uint32 unit_flags, dynamicflags; + uint64 npcflag; ObjectMgr::ChooseCreatureFlags(cInfo, npcflag, unit_flags, dynamicflags, data); if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT) - SetUInt32Value(UNIT_NPC_FLAGS, npcflag | sGameEventMgr->GetNPCFlag(this)); + SetUInt64Value(UNIT_NPC_FLAGS, npcflag | sGameEventMgr->GetNPCFlag(this)); else - SetUInt32Value(UNIT_NPC_FLAGS, npcflag); + SetUInt64Value(UNIT_NPC_FLAGS, npcflag); SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags); SetUInt32Value(UNIT_FIELD_FLAGS_2, cInfo->unit_flags2); @@ -474,7 +484,7 @@ void Creature::Update(uint32 diff) if (!allowed) // Will be rechecked on next Update call break; - ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::Creature>(GetMapId(), GetEntry(), m_DBTableGuid); + ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::Creature>(GetMapId(), GetEntry(), m_spawnId); time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid); if (!linkedRespawntime) // Can respawn Respawn(); @@ -936,7 +946,7 @@ void Creature::SaveToDB() { // this should only be used when the creature has already been loaded // preferably after adding to map, because mapid may not be valid otherwise - CreatureData const* data = sObjectMgr->GetCreatureData(m_DBTableGuid); + CreatureData const* data = sObjectMgr->GetCreatureData(m_spawnId); if (!data) { TC_LOG_ERROR("entities.unit", "Creature::SaveToDB failed, cannot get creature data!"); @@ -950,13 +960,13 @@ void Creature::SaveToDB() void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) { // update in loaded data - if (!m_DBTableGuid) - m_DBTableGuid = GetGUID().GetCounter(); + if (!m_spawnId) + m_spawnId = sObjectMgr->GenerateCreatureSpawnId(); - CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_DBTableGuid); + CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_spawnId); uint32 displayId = GetNativeDisplayId(); - uint32 npcflag = GetUInt32Value(UNIT_NPC_FLAGS); + uint64 npcflag = GetUInt64Value(UNIT_NPC_FLAGS); uint32 unit_flags = GetUInt32Value(UNIT_FIELD_FLAGS); uint32 dynamicflags = GetUInt32Value(OBJECT_DYNAMIC_FLAGS); @@ -1020,13 +1030,13 @@ void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) SQLTransaction trans = WorldDatabase.BeginTransaction(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); - stmt->setUInt64(0, m_DBTableGuid); + stmt->setUInt64(0, m_spawnId); trans->Append(stmt); uint8 index = 0; stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE); - stmt->setUInt64(index++, m_DBTableGuid); + stmt->setUInt64(index++, m_spawnId); stmt->setUInt32(index++, GetEntry()); stmt->setUInt16(index++, uint16(mapid)); stmt->setUInt32(index++, spawnMask); @@ -1044,7 +1054,7 @@ void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) stmt->setUInt32(index++, GetHealth()); stmt->setUInt32(index++, GetPower(POWER_MANA)); stmt->setUInt8(index++, uint8(GetDefaultMovementType())); - stmt->setUInt32(index++, npcflag); + stmt->setUInt64(index++, npcflag); stmt->setUInt32(index++, unit_flags); stmt->setUInt32(index++, dynamicflags); trans->Append(stmt); @@ -1225,26 +1235,17 @@ bool Creature::CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, Creatu return true; } -bool Creature::LoadCreatureFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap) +bool Creature::LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap) { - CreatureData const* data = sObjectMgr->GetCreatureData(guid); - + CreatureData const* data = sObjectMgr->GetCreatureData(spawnId); if (!data) { - TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") not found in table `creature`, can't load. ", guid); + TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") not found in table `creature`, can't load. ", spawnId); return false; } - m_DBTableGuid = guid; - if (map->GetInstanceId() == 0) - { - if (map->GetCreature(ObjectGuid::Create<HighGuid::Creature>(data->mapid, data->id, guid))) - return false; - } - else - guid = sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(); - - if (!Create(guid, map, data->phaseMask, data->id, data->posX, data->posY, data->posZ, data->orientation, data)) + m_spawnId = spawnId; + if (!Create(map->GenerateLowGuid<HighGuid::Creature>(), map, data->phaseMask, data->id, data->posX, data->posY, data->posZ, data->orientation, data)) return false; //We should set first home position, because then AI calls home movement @@ -1255,7 +1256,7 @@ bool Creature::LoadCreatureFromDB(ObjectGuid::LowType guid, Map* map, bool addTo m_respawnDelay = data->spawntimesecs; m_deathState = ALIVE; - m_respawnTime = GetMap()->GetCreatureRespawnTime(m_DBTableGuid); + m_respawnTime = GetMap()->GetCreatureRespawnTime(m_spawnId); if (m_respawnTime) // respawn on Update { m_deathState = DEAD; @@ -1293,7 +1294,7 @@ bool Creature::LoadCreatureFromDB(ObjectGuid::LowType guid, Map* map, bool addTo m_creatureData = data; - loot.SetGUID(ObjectGuid::Create<HighGuid::LootObject>(data->mapid, data->id, sObjectMgr->GetGenerator<HighGuid::LootObject>()->Generate())); + loot.SetGUID(ObjectGuid::Create<HighGuid::LootObject>(data->mapid, data->id, GetMap()->GenerateLowGuid<HighGuid::LootObject>())); if (addToMap && !GetMap()->AddToMap(this)) return false; @@ -1352,31 +1353,31 @@ bool Creature::hasInvolvedQuest(uint32 quest_id) const void Creature::DeleteFromDB() { - if (!m_DBTableGuid) + if (!m_spawnId) { TC_LOG_ERROR("entities.unit", "Trying to delete not saved %s!", GetGUID().ToString().c_str()); return; } - GetMap()->RemoveCreatureRespawnTime(m_DBTableGuid); - sObjectMgr->DeleteCreatureData(m_DBTableGuid); + GetMap()->RemoveCreatureRespawnTime(m_spawnId); + sObjectMgr->DeleteCreatureData(m_spawnId); SQLTransaction trans = WorldDatabase.BeginTransaction(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); - stmt->setUInt64(0, m_DBTableGuid); + stmt->setUInt64(0, m_spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON); - stmt->setUInt64(0, m_DBTableGuid); + stmt->setUInt64(0, m_spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_CREATURE); - stmt->setUInt64(0, m_DBTableGuid); + stmt->setUInt64(0, m_spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP); - stmt->setUInt64(0, m_DBTableGuid); + stmt->setUInt64(0, m_spawnId); trans->Append(stmt); WorldDatabase.CommitTransaction(trans); @@ -1511,7 +1512,9 @@ void Creature::setDeathState(DeathState s) SaveRespawnTime(); SetTarget(ObjectGuid::Empty); // remove target selection in any cases (can be set at aura remove in Unit::setDeathState) - SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + + SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0); // if creature is mounted on a virtual mount, remove it at death setActive(false); @@ -1541,7 +1544,7 @@ void Creature::setDeathState(DeathState s) UpdateMovementFlags(); CreatureTemplate const* cinfo = GetCreatureTemplate(); - SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag); + SetUInt64Value(UNIT_NPC_FLAGS, cinfo->npcflag); ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~UNIT_STATE_IGNORE_PATHFINDING)); SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); LoadCreaturesAddon(true); @@ -1566,8 +1569,8 @@ void Creature::Respawn(bool force) if (getDeathState() == DEAD) { - if (m_DBTableGuid) - GetMap()->RemoveCreatureRespawnTime(m_DBTableGuid); + if (m_spawnId) + GetMap()->RemoveCreatureRespawnTime(m_spawnId); TC_LOG_DEBUG("entities.unit", "Respawning creature %s (%s)", GetName().c_str(), GetGUID().ToString().c_str()); @@ -1600,9 +1603,9 @@ void Creature::Respawn(bool force) TriggerJustRespawned = true;//delay event to next tick so all creatures are created on the map before processing } - uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr->IsPartOfAPool<Creature>(GetDBTableGUIDLow()) : 0; + uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<Creature>(GetSpawnId()) : 0; if (poolid) - sPoolMgr->UpdatePool<Creature>(poolid, GetDBTableGUIDLow()); + sPoolMgr->UpdatePool<Creature>(poolid, GetSpawnId()); //Re-initialize reactstate that could be altered by movementgenerators InitializeReactState(); @@ -2016,10 +2019,10 @@ bool Creature::_IsTargetAcceptable(const Unit* target) const void Creature::SaveRespawnTime() { - if (IsSummon() || !m_DBTableGuid || (m_creatureData && !m_creatureData->dbData)) + if (IsSummon() || !m_spawnId || (m_creatureData && !m_creatureData->dbData)) return; - GetMap()->SaveCreatureRespawnTime(m_DBTableGuid, m_respawnTime); + GetMap()->SaveCreatureRespawnTime(m_spawnId, m_respawnTime); } // this should not be called by petAI or @@ -2051,9 +2054,9 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const CreatureAddon const* Creature::GetCreatureAddon() const { - if (m_DBTableGuid) + if (m_spawnId) { - if (CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(m_DBTableGuid)) + if (CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(m_spawnId)) return addon; } @@ -2130,7 +2133,7 @@ bool Creature::LoadCreaturesAddon(bool reload) if (HasAura(*itr)) { if (!reload) - TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD " Entry: %u) has duplicate aura (spell %u) in `auras` field.", GetDBTableGUIDLow(), GetEntry(), *itr); + TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD " Entry: %u) has duplicate aura (spell %u) in `auras` field.", GetSpawnId(), GetEntry(), *itr); continue; } @@ -2210,9 +2213,9 @@ time_t Creature::GetRespawnTimeEx() const void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, float* dist) const { - if (m_DBTableGuid) + if (m_spawnId) { - if (CreatureData const* data = sObjectMgr->GetCreatureData(GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(GetSpawnId())) { x = data->posX; y = data->posY; diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index f9496a05cf4..0e985ff3648 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -93,7 +93,7 @@ struct CreatureTemplate int32 expansion; uint32 expansionUnknown; // either 0 or 3, sent to the client / wdb uint32 faction; - uint32 npcflag; + uint64 npcflag; float speed_walk; float speed_run; float scale; @@ -209,12 +209,7 @@ typedef std::unordered_map<uint32, CreatureQuestItemList> CreatureQuestItemMap; // Benchmarked: Faster than std::map (insert/find) typedef std::unordered_map<uint32, CreatureTemplate> CreatureTemplateContainer; -// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif // Defines base stats for creatures (used to calculate HP/mana/armor/attackpower/rangedattackpower/all damage). struct CreatureBaseStats @@ -309,7 +304,7 @@ struct CreatureData uint32 curmana; uint8 movementType; uint32 spawnMask; - uint32 npcflag; + uint64 npcflag; uint32 unit_flags; // enum UnitFlags mask values uint32 dynamicflags; uint32 phaseid; @@ -349,12 +344,7 @@ enum ChatType CHAT_TYPE_END = 255 }; -// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif // `creature_addon` table struct CreatureAddon @@ -383,7 +373,7 @@ struct VendorItem uint8 Type; //helpers - bool IsGoldRequired(ItemTemplate const* pProto) const { return pProto->GetFlags2() & ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD || !ExtendedCost; } + bool IsGoldRequired(ItemTemplate const* pProto) const { return pProto->GetFlags2() & ITEM_FLAG2_EXT_COST_REQUIRES_GOLD || !ExtendedCost; } }; typedef std::vector<VendorItem*> VendorItemList; @@ -487,7 +477,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject void SelectLevel(); void LoadEquipment(int8 id = 1, bool force = false); - ObjectGuid::LowType GetDBTableGUIDLow() const { return m_DBTableGuid; } + ObjectGuid::LowType GetSpawnId() const { return m_spawnId; } void Update(uint32 time) override; // overwrited Unit::Update void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr, float* dist =nullptr) const; @@ -571,8 +561,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject void setDeathState(DeathState s) override; // override virtual Unit::setDeathState - bool LoadFromDB(ObjectGuid::LowType guid, Map* map) { return LoadCreatureFromDB(guid, map, false); } - bool LoadCreatureFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap = true); + bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map) { return LoadCreatureFromDB(spawnId, map, false); } + bool LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap = true); void SaveToDB(); // overriden in Pet virtual void SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask); @@ -730,7 +720,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject void RegenerateHealth(); void Regenerate(Powers power); MovementGeneratorType m_defaultMovementType; - ObjectGuid::LowType m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid + ObjectGuid::LowType m_spawnId; ///< For new or temporary creatures is 0 for saved it is lowguid uint8 m_equipmentId; int8 m_originalEquipmentId; // can be -1 diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index 086b307c1c2..00e11ca9ef7 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -56,7 +56,7 @@ void FormationMgr::AddCreatureToGroup(ObjectGuid::LowType leaderGuid, Creature* void FormationMgr::RemoveCreatureFromGroup(CreatureGroup* group, Creature* member) { - TC_LOG_DEBUG("entities.unit", "Deleting member pointer to GUID: " UI64FMTD " from group " UI64FMTD, group->GetId(), member->GetDBTableGUIDLow()); + TC_LOG_DEBUG("entities.unit", "Deleting member pointer to GUID: " UI64FMTD " from group " UI64FMTD, group->GetId(), member->GetSpawnId()); group->RemoveMember(member); if (group->isEmpty()) @@ -145,13 +145,13 @@ void CreatureGroup::AddMember(Creature* member) TC_LOG_DEBUG("entities.unit", "CreatureGroup::AddMember: Adding %s.", member->GetGUID().ToString().c_str()); //Check if it is a leader - if (member->GetDBTableGUIDLow() == m_groupID) + if (member->GetSpawnId() == m_groupID) { TC_LOG_DEBUG("entities.unit", "%s is formation leader. Adding group.", member->GetGUID().ToString().c_str()); m_leader = member; } - m_members[member] = sFormationMgr->CreatureGroupMap.find(member->GetDBTableGUIDLow())->second; + m_members[member] = sFormationMgr->CreatureGroupMap.find(member->GetSpawnId())->second; member->SetFormation(this); } @@ -166,7 +166,7 @@ void CreatureGroup::RemoveMember(Creature* member) void CreatureGroup::MemberAttackStart(Creature* member, Unit* target) { - uint8 groupAI = sFormationMgr->CreatureGroupMap[member->GetDBTableGUIDLow()]->groupAI; + uint8 groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()]->groupAI; if (!groupAI) return; diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp index 6792044cb34..5f2bd4915de 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -54,7 +54,7 @@ void DynamicObject::AddToWorld() ///- Register the dynamicObject for guid lookup and for caster if (!IsInWorld()) { - sObjectAccessor->AddObject(this); + GetMap()->GetObjectsStore().Insert<DynamicObject>(GetGUID(), this); WorldObject::AddToWorld(); BindToCaster(); } @@ -77,7 +77,7 @@ void DynamicObject::RemoveFromWorld() UnbindFromCaster(); WorldObject::RemoveFromWorld(); - sObjectAccessor->RemoveObject(this); + GetMap()->GetObjectsStore().Remove<DynamicObject>(GetGUID()); } } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 5466a848701..852269855df 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -57,7 +57,7 @@ GameObject::GameObject() : WorldObject(false), MapObject(), m_goInfo = NULL; m_goData = NULL; - m_DBTableGuid = UI64LIT(0); + m_spawnId = UI64LIT(0); m_rotation = 0; m_groupLootTimer = 0; @@ -131,7 +131,9 @@ void GameObject::AddToWorld() if (m_zoneScript) m_zoneScript->OnGameObjectCreate(this); - sObjectAccessor->AddObject(this); + GetMap()->GetObjectsStore().Insert<GameObject>(GetGUID(), this); + if (m_spawnId) + GetMap()->GetGameObjectBySpawnIdStore().insert(std::make_pair(m_spawnId, this)); // The state can be changed after GameObject::Create but before GameObject::AddToWorld bool toggledState = GetGoType() == GAMEOBJECT_TYPE_CHEST ? getLootState() == GO_READY : (GetGoState() == GO_STATE_READY || IsTransport()); @@ -160,8 +162,12 @@ void GameObject::RemoveFromWorld() if (m_model) if (GetMap()->ContainsGameObjectModel(*m_model)) GetMap()->RemoveGameObjectModel(*m_model); + WorldObject::RemoveFromWorld(); - sObjectAccessor->RemoveObject(this); + + if (m_spawnId) + Trinity::Containers::MultimapErasePair(GetMap()->GetGameObjectBySpawnIdStore(), m_spawnId, this); + GetMap()->GetObjectsStore().Remove<GameObject>(GetGUID()); } } @@ -193,6 +199,12 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u return false; } + if (goinfo->type == GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT) + { + TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created: gameobject type GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT cannot be manually created.", guidlow, name_id); + return false; + } + if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT) m_updateFlag |= UPDATEFLAG_TRANSPORT; @@ -427,7 +439,7 @@ void GameObject::Update(uint32 diff) time_t now = time(NULL); if (m_respawnTime <= now) // timer expired { - ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::GameObject>(GetMapId(), GetEntry(), m_DBTableGuid); + ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::GameObject>(GetMapId(), GetEntry(), m_spawnId); time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid); if (linkedRespawntime) // Can't respawn, the master is dead { @@ -483,9 +495,9 @@ void GameObject::Update(uint32 diff) } // Respawn timer - uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr->IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0; + uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0; if (poolid) - sPoolMgr->UpdatePool<GameObject>(poolid, GetDBTableGUIDLow()); + sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId()); else GetMap()->AddToMap(this); } @@ -724,9 +736,9 @@ void GameObject::Delete() SetGoState(GO_STATE_READY); SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); - uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr->IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0; + uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0; if (poolid) - sPoolMgr->UpdatePool<GameObject>(poolid, GetDBTableGUIDLow()); + sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId()); else AddObjectToRemoveList(); } @@ -775,7 +787,7 @@ void GameObject::SaveToDB() { // this should only be used when the gameobject has already been loaded // preferably after adding to map, because mapid may not be valid otherwise - GameObjectData const* data = sObjectMgr->GetGOData(m_DBTableGuid); + GameObjectData const* data = sObjectMgr->GetGOData(m_spawnId); if (!data) { TC_LOG_ERROR("misc", "GameObject::SaveToDB failed, cannot get gameobject data!"); @@ -792,11 +804,11 @@ void GameObject::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) if (!goI) return; - if (!m_DBTableGuid) - m_DBTableGuid = GetGUID().GetCounter(); + if (!m_spawnId) + m_spawnId = sObjectMgr->GenerateGameObjectSpawnId(); // update in loaded data (changing data only in this place) - GameObjectData& data = sObjectMgr->NewGOData(m_DBTableGuid); + GameObjectData& data = sObjectMgr->NewGOData(m_spawnId); // data->guid = guid must not be updated at save data.id = GetEntry(); @@ -822,11 +834,11 @@ void GameObject::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) uint8 index = 0; PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT); - stmt->setUInt64(0, m_DBTableGuid); + stmt->setUInt64(0, m_spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_GAMEOBJECT); - stmt->setUInt64(index++, m_DBTableGuid); + stmt->setUInt64(index++, m_spawnId); stmt->setUInt32(index++, GetEntry()); stmt->setUInt16(index++, uint16(mapid)); stmt->setUInt8(index++, spawnMask); @@ -846,13 +858,12 @@ void GameObject::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) WorldDatabase.CommitTransaction(trans); } -bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap) +bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap) { - GameObjectData const* data = sObjectMgr->GetGOData(guid); - + GameObjectData const* data = sObjectMgr->GetGOData(spawnId); if (!data) { - TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD ") not found in table `gameobject`, can't load. ", guid); + TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD ") not found in table `gameobject`, can't load. ", spawnId); return false; } @@ -873,11 +884,8 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool a GOState go_state = data->go_state; uint32 artKit = data->artKit; - m_DBTableGuid = guid; - if (map->GetInstanceId() != 0) - guid = sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(); - - if (!Create(guid, entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, artKit)) + m_spawnId = spawnId; + if (!Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, artKit)) return false; if (data->phaseid) @@ -903,13 +911,13 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool a else { m_respawnDelayTime = data->spawntimesecs; - m_respawnTime = GetMap()->GetGORespawnTime(m_DBTableGuid); + m_respawnTime = GetMap()->GetGORespawnTime(m_spawnId); // ready to respawn if (m_respawnTime && m_respawnTime <= time(NULL)) { m_respawnTime = 0; - GetMap()->RemoveGORespawnTime(m_DBTableGuid); + GetMap()->RemoveGORespawnTime(m_spawnId); } } } @@ -930,18 +938,18 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool a void GameObject::DeleteFromDB() { - GetMap()->RemoveGORespawnTime(m_DBTableGuid); - sObjectMgr->DeleteGOData(m_DBTableGuid); + GetMap()->RemoveGORespawnTime(m_spawnId); + sObjectMgr->DeleteGOData(m_spawnId); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT); - stmt->setUInt64(0, m_DBTableGuid); + stmt->setUInt64(0, m_spawnId); WorldDatabase.Execute(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_EVENT_GAMEOBJECT); - stmt->setUInt64(0, m_DBTableGuid); + stmt->setUInt64(0, m_spawnId); WorldDatabase.Execute(stmt); } @@ -1009,7 +1017,7 @@ Unit* GameObject::GetOwner() const void GameObject::SaveRespawnTime() { if (m_goData && m_goData->dbData && m_respawnTime > time(NULL) && m_spawnedByDefault) - GetMap()->SaveGORespawnTime(m_DBTableGuid, m_respawnTime); + GetMap()->SaveGORespawnTime(m_spawnId, m_respawnTime); } bool GameObject::IsNeverVisible() const @@ -1066,7 +1074,7 @@ void GameObject::Respawn() if (m_spawnedByDefault && m_respawnTime > 0) { m_respawnTime = time(NULL); - GetMap()->RemoveGORespawnTime(m_DBTableGuid); + GetMap()->RemoveGORespawnTime(m_spawnId); } } @@ -1191,7 +1199,7 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = f void GameObject::SetGoArtKit(uint8 kit) { SetByteValue(GAMEOBJECT_BYTES_1, 2, kit); - GameObjectData* data = const_cast<GameObjectData*>(sObjectMgr->GetGOData(m_DBTableGuid)); + GameObjectData* data = const_cast<GameObjectData*>(sObjectMgr->GetGOData(m_spawnId)); if (data) data->artKit = kit; } @@ -1384,7 +1392,7 @@ void GameObject::Use(Unit* user) if (info->goober.eventID) { - TC_LOG_DEBUG("maps.script", "Goober ScriptStart id %u for GO entry %u (GUID " UI64FMTD ").", info->goober.eventID, GetEntry(), GetDBTableGUIDLow()); + TC_LOG_DEBUG("maps.script", "Goober ScriptStart id %u for GO entry %u (GUID " UI64FMTD ").", info->goober.eventID, GetEntry(), GetSpawnId()); GetMap()->ScriptsStart(sEventScripts, info->goober.eventID, player, this); EventInform(info->goober.eventID, user); } @@ -2140,8 +2148,7 @@ uint32 GameObject::GetTransportPeriod() const if (m_goValue.Transport.AnimationInfo) return m_goValue.Transport.AnimationInfo->TotalTime; - // return something that will nicely divide for GAMEOBJECT_DYNAMIC value calculation - return m_goValue.Transport.PathProgress; + return 0; } void GameObject::SetTransportState(GOState state, uint32 stopFrame /*= 0*/) @@ -2310,15 +2317,13 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t dynFlags |= GO_DYNFLAG_LO_SPARKLE; break; case GAMEOBJECT_TYPE_TRANSPORT: - { - float timer = float(m_goValue.Transport.PathProgress % GetTransportPeriod()); - pathProgress = int16(timer / float(GetTransportPeriod()) * 65535.0f); - break; - } case GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT: { - float timer = float(m_goValue.Transport.PathProgress % GetUInt32Value(GAMEOBJECT_LEVEL)); - pathProgress = int16(timer / float(GetUInt32Value(GAMEOBJECT_LEVEL)) * 65535.0f); + if (uint32 transportPeriod = GetTransportPeriod()) + { + float timer = float(m_goValue.Transport.PathProgress % transportPeriod); + pathProgress = int16(timer / float(transportPeriod) * 65535.0f); + } break; } default: @@ -2370,9 +2375,9 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /* = NULL*/) const { - if (m_DBTableGuid) + if (m_spawnId) { - if (GameObjectData const* data = sObjectMgr->GetGOData(GetDBTableGUIDLow())) + if (GameObjectData const* data = sObjectMgr->GetGOData(GetSpawnId())) { x = data->posX; y = data->posY; diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 50bd1ebd9f5..ee429c95475 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -887,7 +887,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map bool IsDynTransport() const; bool IsDestructibleBuilding() const; - ObjectGuid::LowType GetDBTableGUIDLow() const { return m_DBTableGuid; } + ObjectGuid::LowType GetSpawnId() const { return m_spawnId; } void UpdateRotationFields(float rotation2 = 0.0f, float rotation3 = 0.0f); @@ -896,8 +896,8 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map void SaveToDB(); void SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask); - bool LoadFromDB(ObjectGuid::LowType guid, Map* map) { return LoadGameObjectFromDB(guid, map, false); } - bool LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap = true); + bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map) { return LoadGameObjectFromDB(spawnId, map, false); } + bool LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap = true); void DeleteFromDB(); void SetOwnerGUID(ObjectGuid owner) @@ -953,7 +953,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); } void SetGoState(GOState state); - uint32 GetTransportPeriod() const; + virtual uint32 GetTransportPeriod() const; void SetTransportState(GOState state, uint32 stopFrame = 0); uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); } void SetGoArtKit(uint8 artkit); @@ -1090,7 +1090,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map typedef std::map<uint32, ObjectGuid> ChairSlotAndUser; ChairSlotAndUser ChairListSlots; - ObjectGuid::LowType m_DBTableGuid; ///< For new or temporary gameobjects is 0 for saved it is lowguid + ObjectGuid::LowType m_spawnId; ///< For new or temporary gameobjects is 0 for saved it is lowguid GameObjectTemplate const* m_goInfo; GameObjectData const* m_goData; GameObjectValue m_goValue; diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 5534b6e08e3..7250c0cff23 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -51,7 +51,7 @@ void AddItemsSetItem(Player* player, Item* item) for (size_t x = 0; x < player->ItemSetEff.size(); ++x) { - if (player->ItemSetEff[x] && player->ItemSetEff[x]->setid == setid) + if (player->ItemSetEff[x] && player->ItemSetEff[x]->ItemSetID == setid) { eff = player->ItemSetEff[x]; break; @@ -61,7 +61,8 @@ void AddItemsSetItem(Player* player, Item* item) if (!eff) { eff = new ItemSetEffect(); - eff->setid = setid; + eff->ItemSetID = setid; + eff->EquippedItemCount = 0; size_t x = 0; for (; x < player->ItemSetEff.size(); ++x) @@ -69,51 +70,39 @@ void AddItemsSetItem(Player* player, Item* item) break; if (x < player->ItemSetEff.size()) - player->ItemSetEff[x]=eff; + player->ItemSetEff[x] = eff; else player->ItemSetEff.push_back(eff); } - ++eff->item_count; + ++eff->EquippedItemCount; ItemSetSpells& spells = sItemSetSpellsStore[setid]; - for (uint32 x = 0; x < spells.size(); ++x) + for (ItemSetSpellEntry const* itemSetSpell : spells) { //not enough for spell - if (spells[x]->Threshold > eff->item_count) + if (itemSetSpell->Threshold > eff->EquippedItemCount) continue; - uint32 z = 0; - for (; z < MAX_ITEM_SET_SPELLS; ++z) - if (eff->spells[z] && eff->spells[z]->Id == spells[x]->SpellID) - break; - - if (z < MAX_ITEM_SET_SPELLS) + if (eff->SetBonuses.count(itemSetSpell)) continue; - //new spell - for (uint32 y = 0; y < MAX_ITEM_SET_SPELLS; ++y) + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemSetSpell->SpellID); + if (!spellInfo) { - if (!eff->spells[y]) // free slot - { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spells[x]->SpellID); - if (!spellInfo) - { - TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id %u in items set %u effects", spells[x]->SpellID, setid); - break; - } - - // spell cast only if fit form requirement, in other case will cast at form change - player->ApplyEquipSpell(spellInfo, NULL, true); - eff->spells[y] = spellInfo; - break; - } + TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id %u in items set %u effects", itemSetSpell->SpellID, setid); + continue; } + + eff->SetBonuses.insert(itemSetSpell); + // spell cast only if fit form requirement, in other case will cast at form change + if (!itemSetSpell->ChrSpecID || itemSetSpell->ChrSpecID == player->GetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID)) + player->ApplyEquipSpell(spellInfo, NULL, true); } } -void RemoveItemsSetItem(Player*player, ItemTemplate const* proto) +void RemoveItemsSetItem(Player* player, ItemTemplate const* proto) { uint32 setid = proto->GetItemSet(); @@ -129,7 +118,7 @@ void RemoveItemsSetItem(Player*player, ItemTemplate const* proto) size_t setindex = 0; for (; setindex < player->ItemSetEff.size(); setindex++) { - if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->setid == setid) + if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->ItemSetID == setid) { eff = player->ItemSetEff[setindex]; break; @@ -140,29 +129,23 @@ void RemoveItemsSetItem(Player*player, ItemTemplate const* proto) if (!eff) return; - --eff->item_count; + --eff->EquippedItemCount; - ItemSetSpells& spells = sItemSetSpellsStore[setid]; - - for (uint32 x = 0; x < spells.size(); x++) + ItemSetSpells const& spells = sItemSetSpellsStore[setid]; + for (ItemSetSpellEntry const* itemSetSpell : spells) { // enough for spell - if (spells[x]->Threshold <= eff->item_count) + if (itemSetSpell->Threshold <= eff->EquippedItemCount) continue; - for (uint32 z = 0; z < MAX_ITEM_SET_SPELLS; z++) - { - if (eff->spells[z] && eff->spells[z]->Id == spells[x]->SpellID) - { - // spell can be not active if not fit form requirement - player->ApplyEquipSpell(eff->spells[z], NULL, false); - eff->spells[z]=NULL; - break; - } - } + if (!eff->SetBonuses.count(itemSetSpell)) + continue; + + player->ApplyEquipSpell(sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID), nullptr, false); + eff->SetBonuses.erase(itemSetSpell); } - if (!eff->item_count) //all items of a set were removed + if (!eff->EquippedItemCount) //all items of a set were removed { ASSERT(eff == player->ItemSetEff[setindex]); delete eff; @@ -378,7 +361,7 @@ void Item::SaveToDB(SQLTransaction& trans) trans->Append(stmt); - if ((uState == ITEM_CHANGED) && HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) + if ((uState == ITEM_CHANGED) && HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GIFT_OWNER); stmt->setUInt64(0, GetOwnerGUID().GetCounter()); @@ -393,7 +376,7 @@ void Item::SaveToDB(SQLTransaction& trans) stmt->setUInt64(0, GetGUID().GetCounter()); trans->Append(stmt); - if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) + if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT); stmt->setUInt64(0, GetGUID().GetCounter()); @@ -468,7 +451,7 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie // Remove bind flag for items vs NO_BIND set if (IsSoulBound() && proto->GetBonding() == NO_BIND) { - ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND, false); + ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND, false); need_save = true; } @@ -777,7 +760,7 @@ bool Item::CanBeTraded(bool mail, bool trade) const if (m_lootGenerated) return false; - if ((!mail || !IsBoundAccountWide()) && (IsSoulBound() && (!HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE) || !trade))) + if ((!mail || !IsBoundAccountWide()) && (IsSoulBound() && (!HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE) || !trade))) return false; if (IsBag() && (Player::IsBagPos(GetPos()) || !((Bag const*)this)->IsEmpty())) @@ -1067,7 +1050,7 @@ Item* Item::CreateItem(uint32 itemEntry, uint32 count, Player const* player) ASSERT(count != 0, "proto->Stackable == 0 but checked at loading already"); Item* item = NewItemOrBag(proto); - if (item->Create(sObjectMgr->GetGenerator<HighGuid::Item>()->Generate(), itemEntry, player)) + if (item->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), itemEntry, player)) { item->SetCount(count); return item; @@ -1088,7 +1071,7 @@ Item* Item::CloneItem(uint32 count, Player const* player) const newItem->SetGuidValue(ITEM_FIELD_CREATOR, GetGuidValue(ITEM_FIELD_CREATOR)); newItem->SetGuidValue(ITEM_FIELD_GIFTCREATOR, GetGuidValue(ITEM_FIELD_GIFTCREATOR)); - newItem->SetUInt32Value(ITEM_FIELD_FLAGS, GetUInt32Value(ITEM_FIELD_FLAGS) & ~(ITEM_FLAG_REFUNDABLE | ITEM_FLAG_BOP_TRADEABLE)); + newItem->SetUInt32Value(ITEM_FIELD_FLAGS, GetUInt32Value(ITEM_FIELD_FLAGS) & ~(ITEM_FIELD_FLAG_REFUNDABLE | ITEM_FIELD_FLAG_BOP_TRADEABLE)); newItem->SetUInt32Value(ITEM_FIELD_DURATION, GetUInt32Value(ITEM_FIELD_DURATION)); // player CAN be NULL in which case we must not update random properties because that accesses player's item update queue if (player) @@ -1106,7 +1089,7 @@ bool Item::IsBindedNotWith(Player const* player) const if (GetOwnerGUID() == player->GetGUID()) return false; - if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE)) + if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE)) if (allowedGUIDs.find(player->GetGUID()) != allowedGUIDs.end()) return false; @@ -1142,7 +1125,7 @@ void Item::BuildDynamicValuesUpdate(uint8 updateType, ByteBuffer* data, Player* std::vector<uint32> const& values = _dynamicValues[index]; if (_fieldNotifyFlags & flags[index] || ((updateType == UPDATETYPE_VALUES ? _dynamicChangesMask.GetBit(index) : !values.empty()) && (flags[index] & visibleFlag)) || - (index == ITEM_DYNAMIC_FIELD_MODIFIERS && _changesMask.GetBit(ITEM_FIELD_MODIFIERS_MASK))) + (index == ITEM_DYNAMIC_FIELD_MODIFIERS && (updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(ITEM_FIELD_MODIFIERS_MASK) : GetUInt32Value(ITEM_FIELD_MODIFIERS_MASK) != 0))) { updateMask.SetBit(index); @@ -1185,6 +1168,18 @@ void Item::BuildDynamicValuesUpdate(uint8 updateType, ByteBuffer* data, Player* data->append(fieldBuffer); } +void Item::AddToObjectUpdate() +{ + if (Player* owner = GetOwner()) + owner->GetMap()->AddUpdateObject(this); +} + +void Item::RemoveFromObjectUpdate() +{ + if (Player* owner = GetOwner()) + owner->GetMap()->RemoveUpdateObject(this); +} + void Item::SaveRefundDataToDB() { SQLTransaction trans = CharacterDatabase.BeginTransaction(); @@ -1216,10 +1211,10 @@ void Item::DeleteRefundDataFromDB(SQLTransaction* trans) void Item::SetNotRefundable(Player* owner, bool changestate /*=true*/, SQLTransaction* trans /*=NULL*/) { - if (!HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) + if (!HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE)) return; - RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE); + RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE); // Following is not applicable in the trading procedure if (changestate) SetState(ITEM_CHANGED, owner); @@ -1274,13 +1269,13 @@ bool Item::IsRefundExpired() void Item::SetSoulboundTradeable(GuidSet const& allowedLooters) { - SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE); + SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE); allowedGUIDs = allowedLooters; } void Item::ClearSoulboundTradeable(Player* currentOwner) { - RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE); + RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE); if (allowedGUIDs.empty()) return; @@ -1320,7 +1315,7 @@ bool Item::CanBeTransmogrified() const if (proto->GetClass() == ITEM_CLASS_WEAPON && proto->GetSubClass() == ITEM_SUBCLASS_WEAPON_FISHING_POLE) return false; - if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG) + if (proto->GetFlags2() & ITEM_FLAG2_CANNOT_BE_TRANSMOG) return false; if (!HasStats()) @@ -1336,7 +1331,7 @@ bool Item::CanTransmogrify() const if (!proto) return false; - if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG) + if (proto->GetFlags2() & ITEM_FLAG2_CANNOT_TRANSMOG) return false; if (proto->GetQuality() == ITEM_QUALITY_LEGENDARY) @@ -1349,7 +1344,7 @@ bool Item::CanTransmogrify() const if (proto->GetClass() == ITEM_CLASS_WEAPON && proto->GetSubClass() == ITEM_SUBCLASS_WEAPON_FISHING_POLE) return false; - if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_CAN_TRANSMOG) + if (proto->GetFlags2() & ITEM_FLAG2_CAN_TRANSMOG) return true; if (!HasStats()) @@ -1410,7 +1405,7 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice) { normalSellPrice = true; - if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE) + if (proto->GetFlags2() & ITEM_FLAG2_HAS_NORMAL_PRICE) { return proto->GetBuyPrice(); } @@ -1529,7 +1524,7 @@ uint32 Item::GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice /*= { uint32 cost = 0; - if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE) + if (proto->GetFlags2() & ITEM_FLAG2_HAS_NORMAL_PRICE) cost = proto->GetSellPrice(); else { @@ -1735,28 +1730,28 @@ void Item::ItemContainerDeleteLootMoneyAndLootItemsFromDB() ItemContainerDeleteLootItemsFromDB(); } -uint32 Item::GetItemLevel() const +uint32 Item::GetItemLevel(Player const* owner) const { ItemTemplate const* stats = GetTemplate(); if (!stats) return MIN_ITEM_LEVEL; uint32 itemLevel = stats->GetBaseItemLevel(); - if (Player const* owner = GetOwner()) - if (ScalingStatDistributionEntry const* ssd = sScalingStatDistributionStore.LookupEntry(stats->GetScalingStatDistribution())) - if (uint32 heirloomIlvl = sDB2Manager.GetHeirloomItemLevel(ssd->ItemLevelCurveID, owner->getLevel())) - itemLevel = heirloomIlvl; + if (ScalingStatDistributionEntry const* ssd = sScalingStatDistributionStore.LookupEntry(stats->GetScalingStatDistribution())) + if (uint32 heirloomIlvl = sDB2Manager.GetHeirloomItemLevel(ssd->ItemLevelCurveID, owner->getLevel())) + itemLevel = heirloomIlvl; return std::min(std::max(itemLevel + _bonusData.ItemLevel, uint32(MIN_ITEM_LEVEL)), uint32(MAX_ITEM_LEVEL)); } -int32 Item::GetItemStatValue(uint32 index) const +int32 Item::GetItemStatValue(uint32 index, Player const* owner) const { ASSERT(index < MAX_ITEM_PROTO_STATS); - if (uint32 randomPropPoints = GetRandomPropertyPoints(GetItemLevel(), GetQuality(), GetTemplate()->GetInventoryType(), GetTemplate()->GetSubClass())) + uint32 itemLevel = GetItemLevel(owner); + if (uint32 randomPropPoints = GetRandomPropertyPoints(itemLevel, GetQuality(), GetTemplate()->GetInventoryType(), GetTemplate()->GetSubClass())) { float statValue = float(_bonusData.ItemStatAllocation[index] * randomPropPoints) * 0.0001f; - if (GtItemSocketCostPerLevelEntry const* gtCost = sGtItemSocketCostPerLevelStore.EvaluateTable(GetItemLevel() - 1, 0)) + if (GtItemSocketCostPerLevelEntry const* gtCost = sGtItemSocketCostPerLevelStore.EvaluateTable(itemLevel - 1, 0)) statValue -= float(int32(_bonusData.ItemStatSocketCostMultiplier[index] * gtCost->ratio)); return int32(std::floor(statValue + 0.5f)); @@ -1837,11 +1832,14 @@ void BonusData::AddBonus(uint32 type, int32 const (&values)[2]) { uint32 statIndex = 0; for (statIndex = 0; statIndex < MAX_ITEM_PROTO_STATS; ++statIndex) - if (ItemStatType[statIndex] == values[0]) + if (ItemStatType[statIndex] == values[0] || ItemStatType[statIndex] == -1) break; if (statIndex < MAX_ITEM_PROTO_STATS) + { + ItemStatType[statIndex] = values[0]; ItemStatAllocation[statIndex] += values[1]; + } break; } case ITEM_BONUS_QUALITY: diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 810bbdac704..7d03a0a68eb 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -31,9 +31,9 @@ class Unit; struct ItemSetEffect { - uint32 setid; - uint32 item_count; - SpellInfo const* spells[8]; + uint32 ItemSetID; + uint32 EquippedItemCount; + std::unordered_set<ItemSetSpellEntry const*> SetBonuses; }; enum InventoryResult @@ -261,10 +261,10 @@ class Item : public Object void SetOwnerGUID(ObjectGuid guid) { SetGuidValue(ITEM_FIELD_OWNER, guid); } Player* GetOwner()const; - void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND, val); } - bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND); } - bool IsBoundAccountWide() const { return (GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT) != 0; } - bool IsBattlenetAccountBound() const { return (GetTemplate()->GetFlags2() & ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND) != 0; } + void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND, val); } + bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND); } + bool IsBoundAccountWide() const { return (GetTemplate()->GetFlags() & ITEM_FLAG_BIND_TO_ACCOUNT) != 0; } + bool IsBattlenetAccountBound() const { return (GetTemplate()->GetFlags2() & ITEM_FLAG2_BNET_ACCOUNT_BOUND) != 0; } bool IsBindedNotWith(Player const* player) const; bool IsBoundByEnchant() const; virtual void SaveToDB(SQLTransaction& trans); @@ -291,7 +291,7 @@ class Item : public Object Bag* ToBag() { if (IsBag()) return reinterpret_cast<Bag*>(this); else return NULL; } const Bag* ToBag() const { if (IsBag()) return reinterpret_cast<const Bag*>(this); else return NULL; } - bool IsLocked() const { return !HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED); } + bool IsLocked() const { return !HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_UNLOCKED); } bool IsBag() const { return GetTemplate()->GetInventoryType() == INVTYPE_BAG; } bool IsCurrencyToken() const { return GetTemplate()->IsCurrencyToken(); } bool IsNotEmptyBag() const; @@ -375,14 +375,14 @@ class Item : public Object bool IsConjuredConsumable() const { return GetTemplate()->IsConjuredConsumable(); } bool IsRangedWeapon() const { return GetTemplate()->IsRangedWeapon(); } uint32 GetQuality() const { return _bonusData.Quality; } - uint32 GetItemLevel() const; + uint32 GetItemLevel(Player const* owner) const; int32 GetRequiredLevel() const { return _bonusData.RequiredLevel; } int32 GetItemStatType(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return _bonusData.ItemStatType[index]; } - int32 GetItemStatValue(uint32 index) const; + int32 GetItemStatValue(uint32 index, Player const* owner) const; SocketColor GetSocketColor(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_SOCKETS); return SocketColor(_bonusData.SocketColor[index]); } uint32 GetAppearanceModId() const { return _bonusData.AppearanceModID; } - uint32 GetArmor() const { return GetTemplate()->GetArmor(GetItemLevel()); } - void GetDamage(float& minDamage, float& maxDamage) const { GetTemplate()->GetDamage(GetItemLevel(), minDamage, maxDamage); } + uint32 GetArmor(Player const* owner) const { return GetTemplate()->GetArmor(GetItemLevel(owner)); } + void GetDamage(Player const* owner, float& minDamage, float& maxDamage) const { GetTemplate()->GetDamage(GetItemLevel(owner), minDamage, maxDamage); } uint32 GetDisplayId() const; // Item Refund system @@ -406,6 +406,8 @@ class Item : public Object void BuildUpdate(UpdateDataMapType&) override; void BuildDynamicValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const override; + void AddToObjectUpdate() override; + void RemoveFromObjectUpdate() override; uint32 GetScriptId() const { return GetTemplate()->ScriptId; } diff --git a/src/server/game/Entities/Item/ItemTemplate.cpp b/src/server/game/Entities/Item/ItemTemplate.cpp index a21a4f1aa3f..f9e2e2d4236 100644 --- a/src/server/game/Entities/Item/ItemTemplate.cpp +++ b/src/server/game/Entities/Item/ItemTemplate.cpp @@ -37,7 +37,7 @@ char const* ItemTemplate::GetDefaultLocaleName() const uint32 ItemTemplate::GetArmor(uint32 itemLevel) const { - uint32 quality = GetQuality() != ITEM_QUALITY_HEIRLOOM ? GetQuality() : ITEM_QUALITY_RARE; + uint32 quality = ItemQualities(GetQuality()) != ITEM_QUALITY_HEIRLOOM ? ItemQualities(GetQuality()) : ITEM_QUALITY_RARE; if (quality > ITEM_QUALITY_ARTIFACT) return 0; @@ -74,7 +74,7 @@ uint32 ItemTemplate::GetArmor(uint32 itemLevel) const void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamage) const { minDamage = maxDamage = 0.0f; - uint32 quality = GetQuality() != ITEM_QUALITY_HEIRLOOM ? GetQuality() : ITEM_QUALITY_RARE; + uint32 quality = ItemQualities(GetQuality()) != ITEM_QUALITY_HEIRLOOM ? ItemQualities(GetQuality()) : ITEM_QUALITY_RARE; if (GetClass() != ITEM_CLASS_WEAPON || quality > ITEM_QUALITY_ARTIFACT) return; @@ -89,7 +89,7 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag store = &sItemDamageAmmoStore; break; case INVTYPE_2HWEAPON: - if (GetFlags2() & ITEM_FLAGS_EXTRA_CASTER_WEAPON) + if (GetFlags2() & ITEM_FLAG2_CASTER_WEAPON) store = &sItemDamageTwoHandCasterStore; else store = &sItemDamageTwoHandStore; @@ -117,7 +117,7 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag case INVTYPE_WEAPON: case INVTYPE_WEAPONMAINHAND: case INVTYPE_WEAPONOFFHAND: - if (GetFlags2() & ITEM_FLAGS_EXTRA_CASTER_WEAPON) + if (GetFlags2() & ITEM_FLAG2_CASTER_WEAPON) store = &sItemDamageOneHandCasterStore; else store = &sItemDamageOneHandStore; diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index 47523872151..c578b641ad2 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -127,101 +127,140 @@ enum ItemBondingType #define MAX_BIND_TYPE 6 /* /// @todo: Requiring actual cases in which using (an) item isn't allowed while shapeshifted. Else, this flag would need an implementation. - ITEM_PROTO_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms */ - -enum ItemProtoFlags -{ - ITEM_PROTO_FLAG_UNK1 = 0x00000001, // ? - ITEM_PROTO_FLAG_CONJURED = 0x00000002, // Conjured item - ITEM_PROTO_FLAG_OPENABLE = 0x00000004, // Item can be right clicked to open for loot - ITEM_PROTO_FLAG_HEROIC = 0x00000008, // Makes green "Heroic" text appear on item - ITEM_PROTO_FLAG_DEPRECATED = 0x00000010, // Cannot equip or use - ITEM_PROTO_FLAG_INDESTRUCTIBLE = 0x00000020, // Item can not be destroyed, except by using spell (item can be reagent for spell) - ITEM_PROTO_FLAG_UNK2 = 0x00000040, // ? - ITEM_PROTO_FLAG_NO_EQUIP_COOLDOWN = 0x00000080, // No default 30 seconds cooldown when equipped - ITEM_PROTO_FLAG_UNK3 = 0x00000100, // ? - ITEM_PROTO_FLAG_WRAPPER = 0x00000200, // Item can wrap other items - ITEM_PROTO_FLAG_UNK4 = 0x00000400, // ? - ITEM_PROTO_FLAG_PARTY_LOOT = 0x00000800, // Looting this item does not remove it from available loot - ITEM_PROTO_FLAG_REFUNDABLE = 0x00001000, // Item can be returned to vendor for its original cost (extended cost) - ITEM_PROTO_FLAG_CHARTER = 0x00002000, // Item is guild or arena charter - ITEM_PROTO_FLAG_UNK5 = 0x00004000, // Only readable items have this (but not all) - ITEM_PROTO_FLAG_UNK6 = 0x00008000, // ? - ITEM_PROTO_FLAG_UNK7 = 0x00010000, // ? - ITEM_PROTO_FLAG_UNK8 = 0x00020000, // ? - ITEM_PROTO_FLAG_PROSPECTABLE = 0x00040000, // Item can be prospected - ITEM_PROTO_FLAG_UNIQUE_EQUIPPED = 0x00080000, // You can only equip one of these - ITEM_PROTO_FLAG_UNK9 = 0x00100000, // ? - ITEM_PROTO_FLAG_USEABLE_IN_ARENA = 0x00200000, // Item can be used during arena match - ITEM_PROTO_FLAG_THROWABLE = 0x00400000, // Some Thrown weapons have it (and only Thrown) but not all - ITEM_PROTO_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms - ITEM_PROTO_FLAG_UNK10 = 0x01000000, // ? - ITEM_PROTO_FLAG_SMART_LOOT = 0x02000000, // Profession recipes: can only be looted if you meet requirements and don't already know it - ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA = 0x04000000, // Item cannot be used in arena - ITEM_PROTO_FLAG_BIND_TO_ACCOUNT = 0x08000000, // Item binds to account and can be sent only to your own characters - ITEM_PROTO_FLAG_TRIGGERED_CAST = 0x10000000, // Spell is cast with triggered flag - ITEM_PROTO_FLAG_MILLABLE = 0x20000000, // Item can be milled - ITEM_PROTO_FLAG_UNK11 = 0x40000000, // ? - ITEM_PROTO_FLAG_BOP_TRADEABLE = 0x80000000 // bound item that can be traded -}; - -enum ItemFieldFlags -{ - ITEM_FLAG_SOULBOUND = 0x00000001, // Item is soulbound and cannot be traded <<-- - ITEM_FLAG_UNK1 = 0x00000002, // ? - ITEM_FLAG_UNLOCKED = 0x00000004, // Item had lock but can be opened now - ITEM_FLAG_WRAPPED = 0x00000008, // Item is wrapped and contains another item - ITEM_FLAG_UNK2 = 0x00000010, // ? - ITEM_FLAG_UNK3 = 0x00000020, // ? - ITEM_FLAG_UNK4 = 0x00000040, // ? - ITEM_FLAG_UNK5 = 0x00000080, // ? - ITEM_FLAG_BOP_TRADEABLE = 0x00000100, // Allows trading soulbound items - ITEM_FLAG_READABLE = 0x00000200, // Opens text page when right clicked - ITEM_FLAG_UNK6 = 0x00000400, // ? - ITEM_FLAG_UNK7 = 0x00000800, // ? - ITEM_FLAG_REFUNDABLE = 0x00001000, // Item can be returned to vendor for its original cost (extended cost) - ITEM_FLAG_UNK8 = 0x00002000, // ? - ITEM_FLAG_UNK9 = 0x00004000, // ? - ITEM_FLAG_UNK10 = 0x00008000, // ? - ITEM_FLAG_UNK11 = 0x00010000, // ? - ITEM_FLAG_UNK12 = 0x00020000, // ? - ITEM_FLAG_UNK13 = 0x00040000, // ? - ITEM_FLAG_UNK14 = 0x00080000, // ? - ITEM_FLAG_UNK15 = 0x00100000, // ? - ITEM_FLAG_UNK16 = 0x00200000, // ? - ITEM_FLAG_UNK17 = 0x00400000, // ? - ITEM_FLAG_UNK18 = 0x00800000, // ? - ITEM_FLAG_UNK19 = 0x01000000, // ? - ITEM_FLAG_UNK20 = 0x02000000, // ? - ITEM_FLAG_UNK21 = 0x04000000, // ? - ITEM_FLAG_UNK22 = 0x08000000, // ? - ITEM_FLAG_UNK23 = 0x10000000, // ? - ITEM_FLAG_UNK24 = 0x20000000, // ? - ITEM_FLAG_UNK25 = 0x40000000, // ? - ITEM_FLAG_UNK26 = 0x80000000, // ? - - ITEM_FLAG_MAIL_TEXT_MASK = ITEM_FLAG_READABLE | ITEM_FLAG_UNK13 | ITEM_FLAG_UNK14 -}; - -enum ItemFlagsExtra -{ - ITEM_FLAGS_EXTRA_HORDE_ONLY = 0x00000001, - ITEM_FLAGS_EXTRA_ALLIANCE_ONLY = 0x00000002, - ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD = 0x00000004, // when item uses extended cost, gold is also required - ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100, - ITEM_FLAGS_EXTRA_CASTER_WEAPON = 0x00000200, - ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE = 0x00004000, - ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND = 0x00020000, - ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG = 0x00200000, - ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG = 0x00400000, - ITEM_FLAGS_EXTRA_CAN_TRANSMOG = 0x00800000, + ITEM_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms */ + +// ITEM_FIELD_FLAGS +enum ItemFieldFlags : uint32 +{ + ITEM_FIELD_FLAG_SOULBOUND = 0x00000001, // Item is soulbound and cannot be traded <<-- + ITEM_FIELD_FLAG_TRANSLATED = 0x00000002, // Item text will not read as garbage when player does not know the language + ITEM_FIELD_FLAG_UNLOCKED = 0x00000004, // Item had lock but can be opened now + ITEM_FIELD_FLAG_WRAPPED = 0x00000008, // Item is wrapped and contains another item + ITEM_FIELD_FLAG_UNK2 = 0x00000010, + ITEM_FIELD_FLAG_UNK3 = 0x00000020, + ITEM_FIELD_FLAG_UNK4 = 0x00000040, + ITEM_FIELD_FLAG_UNK5 = 0x00000080, + ITEM_FIELD_FLAG_BOP_TRADEABLE = 0x00000100, // Allows trading soulbound items + ITEM_FIELD_FLAG_READABLE = 0x00000200, // Opens text page when right clicked + ITEM_FIELD_FLAG_UNK6 = 0x00000400, + ITEM_FIELD_FLAG_UNK7 = 0x00000800, + ITEM_FIELD_FLAG_REFUNDABLE = 0x00001000, // Item can be returned to vendor for its original cost (extended cost) + ITEM_FIELD_FLAG_UNK8 = 0x00002000, + ITEM_FIELD_FLAG_UNK9 = 0x00004000, + ITEM_FIELD_FLAG_UNK10 = 0x00008000, + ITEM_FIELD_FLAG_UNK11 = 0x00010000, + ITEM_FIELD_FLAG_UNK12 = 0x00020000, + ITEM_FIELD_FLAG_UNK13 = 0x00040000, + ITEM_FIELD_FLAG_UNK14 = 0x00080000, + ITEM_FIELD_FLAG_UNK15 = 0x00100000, + ITEM_FIELD_FLAG_UNK16 = 0x00200000, + ITEM_FIELD_FLAG_UNK17 = 0x00400000, + ITEM_FIELD_FLAG_UNK18 = 0x00800000, + ITEM_FIELD_FLAG_UNK19 = 0x01000000, + ITEM_FIELD_FLAG_UNK20 = 0x02000000, + ITEM_FIELD_FLAG_UNK21 = 0x04000000, + ITEM_FIELD_FLAG_UNK22 = 0x08000000, + ITEM_FIELD_FLAG_UNK23 = 0x10000000, + ITEM_FIELD_FLAG_UNK24 = 0x20000000, + ITEM_FIELD_FLAG_UNK25 = 0x40000000, + ITEM_FIELD_FLAG_UNK26 = 0x80000000, + + ITEM_FIELD_FLAG_MAIL_TEXT_MASK = ITEM_FIELD_FLAG_READABLE | ITEM_FIELD_FLAG_UNK13 | ITEM_FIELD_FLAG_UNK14 +}; + +enum ItemFlags : uint32 +{ + ITEM_FLAG_UNK1 = 0x00000001, + ITEM_FLAG_CONJURED = 0x00000002, // Conjured item + ITEM_FLAG_OPENABLE = 0x00000004, // Item can be right clicked to open for loot + ITEM_FLAG_HEROIC = 0x00000008, // Makes green "Heroic" text appear on item + ITEM_FLAG_DEPRECATED = 0x00000010, // Cannot equip or use + ITEM_FLAG_INDESTRUCTIBLE = 0x00000020, // Item can not be destroyed, except by using spell (item can be reagent for spell) + ITEM_FLAG_UNK2 = 0x00000040, + ITEM_FLAG_NO_EQUIP_COOLDOWN = 0x00000080, // No default 30 seconds cooldown when equipped + ITEM_FLAG_UNK3 = 0x00000100, + ITEM_FLAG_WRAPPER = 0x00000200, // Item can wrap other items + ITEM_FLAG_UNK4 = 0x00000400, + ITEM_FLAG_PARTY_LOOT = 0x00000800, // Looting this item does not remove it from available loot + ITEM_FLAG_REFUNDABLE = 0x00001000, // Item can be returned to vendor for its original cost (extended cost) + ITEM_FLAG_CHARTER = 0x00002000, // Item is guild or arena charter + ITEM_FLAG_UNK5 = 0x00004000, // Only readable items have this (but not all) + ITEM_FLAG_UNK6 = 0x00008000, + ITEM_FLAG_UNK7 = 0x00010000, + ITEM_FLAG_UNK8 = 0x00020000, + ITEM_FLAG_PROSPECTABLE = 0x00040000, // Item can be prospected + ITEM_FLAG_UNIQUE_EQUIPPED = 0x00080000, // You can only equip one of these + ITEM_FLAG_UNK9 = 0x00100000, + ITEM_FLAG_USEABLE_IN_ARENA = 0x00200000, // Item can be used during arena match + ITEM_FLAG_THROWABLE = 0x00400000, // Some Thrown weapons have it (and only Thrown) but not all + ITEM_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms + ITEM_FLAG_UNK10 = 0x01000000, + ITEM_FLAG_SMART_LOOT = 0x02000000, // Profession recipes: can only be looted if you meet requirements and don't already know it + ITEM_FLAG_NOT_USEABLE_IN_ARENA = 0x04000000, // Item cannot be used in arena + ITEM_FLAG_BIND_TO_ACCOUNT = 0x08000000, // Item binds to account and can be sent only to your own characters + ITEM_FLAG_TRIGGERED_CAST = 0x10000000, // Spell is cast with triggered flag + ITEM_FLAG_MILLABLE = 0x20000000, // Item can be milled + ITEM_FLAG_UNK11 = 0x40000000, + ITEM_FLAG_BOP_TRADEABLE = 0x80000000 // bound item that can be traded +}; + +enum ItemFlags2 : uint32 +{ + ITEM_FLAG2_HORDE_ONLY = 0x00000001, + ITEM_FLAG2_ALLIANCE_ONLY = 0x00000002, + ITEM_FLAG2_EXT_COST_REQUIRES_GOLD = 0x00000004, // when item uses extended cost, gold is also required + ITEM_FLAG2_UNK1 = 0x00000008, + ITEM_FLAG2_UNK2 = 0x00000010, + ITEM_FLAG2_UNK3 = 0x00000020, + ITEM_FLAG2_UNK4 = 0x00000040, + ITEM_FLAG2_UNK5 = 0x00000080, + ITEM_FLAG2_NEED_ROLL_DISABLED = 0x00000100, + ITEM_FLAG2_CASTER_WEAPON = 0x00000200, + ITEM_FLAG2_UNK6 = 0x00000400, + ITEM_FLAG2_UNK7 = 0x00000800, + ITEM_FLAG2_UNK8 = 0x00001000, + ITEM_FLAG2_UNK9 = 0x00002000, + ITEM_FLAG2_HAS_NORMAL_PRICE = 0x00004000, + ITEM_FLAG2_UNK10 = 0x00008000, + ITEM_FLAG2_UNK11 = 0x00010000, + ITEM_FLAG2_BNET_ACCOUNT_BOUND = 0x00020000, + ITEM_FLAG2_UNK12 = 0x00040000, + ITEM_FLAG2_UNK13 = 0x00080000, + ITEM_FLAG2_UNK14 = 0x00100000, + ITEM_FLAG2_CANNOT_BE_TRANSMOG = 0x00200000, + ITEM_FLAG2_CANNOT_TRANSMOG = 0x00400000, + ITEM_FLAG2_CAN_TRANSMOG = 0x00800000, + ITEM_FLAG2_UNK15 = 0x01000000, + ITEM_FLAG2_UNK16 = 0x02000000, + ITEM_FLAG2_UNK17 = 0x04000000, + ITEM_FLAG2_UNK18 = 0x08000000, + ITEM_FLAG2_UNK19 = 0x10000000, + ITEM_FLAG2_UNK20 = 0x20000000, + ITEM_FLAG2_UNK21 = 0x40000000, + ITEM_FLAG2_CRAFTING_MATERIAL = 0x80000000 }; enum ItemFlags3 { - ITEM_FLAG3_IGNORE_ITEM_LEVEL_DELTAS = 0x080, // Ignore item level adjustments from PLAYER_FIELD_ITEM_LEVEL_DELTA - ITEM_FLAG3_IGNORE_PVP_ITEM_LEVEL_CAP = 0x100, - ITEM_FLAG3_HEIRLOOM_QUALITY = 0x200, // Item appears as having heirloom quality ingame regardless of its real quality (does not affect stat calculation) + ITEM_FLAG3_UNK1 = 0x00000001, + ITEM_FLAG3_UNK2 = 0x00000002, + ITEM_FLAG3_UNK3 = 0x00000004, + ITEM_FLAG3_UNK4 = 0x00000008, + ITEM_FLAG3_UNK5 = 0x00000010, + ITEM_FLAG3_UNK6 = 0x00000020, + ITEM_FLAG3_UNK7 = 0x00000040, + ITEM_FLAG3_IGNORE_ITEM_LEVEL_DELTAS = 0x00000080, // Ignore item level adjustments from PLAYER_FIELD_ITEM_LEVEL_DELTA + ITEM_FLAG3_IGNORE_PVP_ITEM_LEVEL_CAP = 0x00000100, + ITEM_FLAG3_HEIRLOOM_QUALITY = 0x00000200, // Item appears as having heirloom quality ingame regardless of its real quality (does not affect stat calculation) + ITEM_FLAG3_UNK8 = 0x00000400, + ITEM_FLAG3_UNK9 = 0x00000800, + ITEM_FLAG3_DOESNT_APPEAR_IN_GUILD_NEWS = 0x00001000, // Item is not included in the guild news panel + ITEM_FLAG3_UNK10 = 0x00002000, + ITEM_FLAG3_UNK11 = 0x00004000, + ITEM_FLAG3_UNK12 = 0x00008000, + ITEM_FLAG3_UNK13 = 0x00010000, + ITEM_FLAG3_UNK14 = 0x00020000, + ITEM_FLAG3_UNK15 = 0x00040000 }; enum ItemFlagsCustom @@ -710,7 +749,7 @@ struct ItemTemplate bool IsPotion() const { return GetClass() == ITEM_CLASS_CONSUMABLE && GetSubClass() == ITEM_SUBCLASS_POTION; } bool IsVellum() const { return GetClass() == ITEM_CLASS_TRADE_GOODS && GetSubClass() == ITEM_SUBCLASS_ENCHANTMENT; } - bool IsConjuredConsumable() const { return GetClass() == ITEM_CLASS_CONSUMABLE && (GetFlags() & ITEM_PROTO_FLAG_CONJURED); } + bool IsConjuredConsumable() const { return GetClass() == ITEM_CLASS_CONSUMABLE && (GetFlags() & ITEM_FLAG_CONJURED); } bool IsRangedWeapon() const { diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index a4a2b965f3e..c2f7718438e 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -95,14 +95,12 @@ Object::~Object() if (isType(TYPEMASK_ITEM)) TC_LOG_FATAL("misc", "Item slot %u", ((Item*)this)->GetSlot()); ASSERT(false); - RemoveFromWorld(); } if (m_objectUpdated) { TC_LOG_FATAL("misc", "Object::~Object %s deleted but still in update list!!", GetGUID().ToString().c_str()); ASSERT(false); - sObjectAccessor->RemoveUpdateObject(this); } delete[] m_uint32Values; @@ -159,7 +157,8 @@ void Object::AddToWorld() m_inWorld = true; // synchronize values mirror with values array (changes will send in updatecreate opcode any way - ClearUpdateMask(true); + ASSERT(!m_objectUpdated); + ClearUpdateMask(false); } void Object::RemoveFromWorld() @@ -822,6 +821,15 @@ void Object::BuildDynamicValuesUpdate(uint8 updateType, ByteBuffer* data, Player data->append(fieldBuffer); } +void Object::AddToObjectUpdateIfNeeded() +{ + if (m_inWorld && !m_objectUpdated) + { + AddToObjectUpdate(); + m_objectUpdated = true; + } +} + void Object::ClearUpdateMask(bool remove) { _changesMask.Clear(); @@ -832,7 +840,7 @@ void Object::ClearUpdateMask(bool remove) if (m_objectUpdated) { if (remove) - sObjectAccessor->RemoveUpdateObject(this); + RemoveFromObjectUpdate(); m_objectUpdated = false; } } @@ -982,11 +990,7 @@ void Object::SetInt32Value(uint16 index, int32 value) m_int32Values[index] = value; _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -999,11 +1003,7 @@ void Object::SetUInt32Value(uint16 index, uint32 value) m_uint32Values[index] = value; _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1025,11 +1025,7 @@ void Object::SetUInt64Value(uint16 index, uint64 value) _changesMask.SetBit(index); _changesMask.SetBit(index + 1); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1044,12 +1040,7 @@ bool Object::AddGuidValue(uint16 index, ObjectGuid const& value) _changesMask.SetBit(index + 2); _changesMask.SetBit(index + 3); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } - + AddToObjectUpdateIfNeeded(); return true; } @@ -1067,12 +1058,7 @@ bool Object::RemoveGuidValue(uint16 index, ObjectGuid const& value) _changesMask.SetBit(index + 2); _changesMask.SetBit(index + 3); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } - + AddToObjectUpdateIfNeeded(); return true; } @@ -1088,11 +1074,7 @@ void Object::SetFloatValue(uint16 index, float value) m_floatValues[index] = value; _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1112,11 +1094,7 @@ void Object::SetByteValue(uint16 index, uint8 offset, uint8 value) m_uint32Values[index] |= uint32(uint32(value) << (offset * 8)); _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1136,11 +1114,7 @@ void Object::SetUInt16Value(uint16 index, uint8 offset, uint16 value) m_uint32Values[index] |= uint32(uint32(value) << (offset * 16)); _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1155,11 +1129,7 @@ void Object::SetGuidValue(uint16 index, ObjectGuid const& value) _changesMask.SetBit(index + 2); _changesMask.SetBit(index + 3); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1238,11 +1208,7 @@ void Object::SetFlag(uint16 index, uint32 newFlag) m_uint32Values[index] = newval; _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1259,11 +1225,7 @@ void Object::RemoveFlag(uint16 index, uint32 oldFlag) m_uint32Values[index] = newval; _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1303,11 +1265,7 @@ void Object::SetByteFlag(uint16 index, uint8 offset, uint8 newFlag) m_uint32Values[index] |= uint32(uint32(newFlag) << (offset * 8)); _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1326,11 +1284,7 @@ void Object::RemoveByteFlag(uint16 index, uint8 offset, uint8 oldFlag) m_uint32Values[index] &= ~uint32(uint32(oldFlag) << (offset * 8)); _changesMask.SetBit(index); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1405,11 +1359,7 @@ void Object::AddDynamicValue(uint16 index, uint32 value) mask.SetBit(values.size() - 1); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } void Object::RemoveDynamicValue(uint16 index, uint32 /*value*/) @@ -1428,11 +1378,7 @@ void Object::ClearDynamicValue(uint16 index) _dynamicChangesMask.SetBit(index); _dynamicChangesArrayMask[index].SetCount(0); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1450,11 +1396,7 @@ void Object::SetDynamicValue(uint16 index, uint8 offset, uint32 value) _dynamicChangesMask.SetBit(index); _dynamicChangesArrayMask[index].SetBit(offset); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } } @@ -1466,62 +1408,6 @@ bool Object::PrintIndexError(uint32 index, bool set) const return false; } -bool Position::operator==(Position const &a) -{ - return (G3D::fuzzyEq(a.m_positionX, m_positionX) && - G3D::fuzzyEq(a.m_positionY, m_positionY) && - G3D::fuzzyEq(a.m_positionZ, m_positionZ) && - G3D::fuzzyEq(a._orientation, _orientation)); -} - -bool Position::HasInLine(WorldObject const* target, float width) const -{ - if (!HasInArc(float(M_PI), target)) - return false; - width += target->GetObjectSize(); - float angle = GetRelativeAngle(target); - return std::fabs(std::sin(angle)) * GetExactDist2d(target->GetPositionX(), target->GetPositionY()) < width; -} - -std::string Position::ToString() const -{ - std::stringstream sstr; - sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << _orientation; - return sstr.str(); -} - -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer) -{ - float x, y, z, o; - buf >> x >> y >> z >> o; - streamer.Pos->Relocate(x, y, z, o); - return buf; -} -ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer) -{ - buf << streamer.Pos->GetPositionX(); - buf << streamer.Pos->GetPositionY(); - buf << streamer.Pos->GetPositionZ(); - return buf; -} - -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer) -{ - float x, y, z; - buf >> x >> y >> z; - streamer.Pos->Relocate(x, y, z); - return buf; -} - -ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer) -{ - buf << streamer.Pos->GetPositionX(); - buf << streamer.Pos->GetPositionY(); - buf << streamer.Pos->GetPositionZ(); - buf << streamer.Pos->GetOrientation(); - return buf; -} - void MovementInfo::OutDebug() { TC_LOG_DEBUG("misc", "MOVEMENT INFO"); @@ -1881,92 +1767,6 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m return distsq < maxdist * maxdist; } -void Position::RelocateOffset(const Position & offset) -{ - m_positionX = GetPositionX() + (offset.GetPositionX() * std::cos(GetOrientation()) + offset.GetPositionY() * std::sin(GetOrientation() + float(M_PI))); - m_positionY = GetPositionY() + (offset.GetPositionY() * std::cos(GetOrientation()) + offset.GetPositionX() * std::sin(GetOrientation())); - m_positionZ = GetPositionZ() + offset.GetPositionZ(); - SetOrientation(GetOrientation() + offset.GetOrientation()); -} - -void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const -{ - float dx = endPos.GetPositionX() - GetPositionX(); - float dy = endPos.GetPositionY() - GetPositionY(); - - retOffset.m_positionX = dx * std::cos(GetOrientation()) + dy * std::sin(GetOrientation()); - retOffset.m_positionY = dy * std::cos(GetOrientation()) - dx * std::sin(GetOrientation()); - retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ(); - retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation()); -} - -Position Position::GetPositionWithOffset(Position const& offset) const -{ - Position ret(*this); - ret.RelocateOffset(offset); - return ret; -} - -float Position::GetAngle(const Position* obj) const -{ - if (!obj) - return 0; - - return GetAngle(obj->GetPositionX(), obj->GetPositionY()); -} - -// Return angle in range 0..2*pi -float Position::GetAngle(const float x, const float y) const -{ - float dx = x - GetPositionX(); - float dy = y - GetPositionY(); - - float ang = std::atan2(dy, dx); - ang = (ang >= 0) ? ang : 2 * float(M_PI) + ang; - return ang; -} - -void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) const -{ - float dx = GetPositionX() - x; - float dy = GetPositionY() - y; - - if (std::fabs(dx) < 0.001f && std::fabs(dy) < 0.001f) - { - float angle = (float)rand_norm()*static_cast<float>(2*M_PI); - vcos = std::cos(angle); - vsin = std::sin(angle); - } - else - { - float dist = std::sqrt((dx*dx) + (dy*dy)); - vcos = dx / dist; - vsin = dy / dist; - } -} - -bool Position::HasInArc(float arc, const Position* obj, float border) const -{ - // always have self in arc - if (obj == this) - return true; - - // move arc to range 0.. 2*pi - arc = NormalizeOrientation(arc); - - float angle = GetAngle(obj); - angle -= _orientation; - - // move angle to range -pi ... +pi - angle = NormalizeOrientation(angle); - if (angle > float(M_PI)) - angle -= 2.0f * float(M_PI); - - float lborder = -1 * (arc/border); // in range -pi..0 - float rborder = (arc/border); // in range 0..pi - return ((angle >= lborder) && (angle <= rborder)); -} - bool WorldObject::IsInBetween(const WorldObject* obj1, const WorldObject* obj2, float size) const { if (!obj1 || !obj2) @@ -2100,11 +1900,6 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const } } -bool Position::IsPositionValid() const -{ - return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, _orientation); -} - float WorldObject::GetGridActivationRange() const { if (ToPlayer()) @@ -2334,11 +2129,7 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const void Object::ForceValuesUpdateAtIndex(uint32 i) { _changesMask.SetBit(i); - if (m_inWorld && !m_objectUpdated) - { - sObjectAccessor->AddUpdateObject(this); - m_objectUpdated = true; - } + AddToObjectUpdateIfNeeded(); } void WorldObject::SendMessageToSet(WorldPacket const* data, bool self) @@ -2486,7 +2277,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert break; } - if (!summon->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), this, 0, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), nullptr, vehId)) + if (!summon->Create(GenerateLowGuid<HighGuid::Creature>(), this, 0, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), nullptr, vehId)) { delete summon; return NULL; @@ -2583,7 +2374,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float Map* map = GetMap(); GameObject* go = new GameObject(); - if (!go->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), entry, map, GetPhaseMask(), x, y, z, ang, rotation0, rotation1, rotation2, rotation3, 100, GO_STATE_READY)) + if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, GetPhaseMask(), x, y, z, ang, rotation0, rotation1, rotation2, rotation3, 100, GO_STATE_READY)) { delete go; return NULL; @@ -3292,6 +3083,16 @@ void WorldObject::BuildUpdate(UpdateDataMapType& data_map) ClearUpdateMask(false); } +void WorldObject::AddToObjectUpdate() +{ + GetMap()->AddUpdateObject(this); +} + +void WorldObject::RemoveFromObjectUpdate() +{ + GetMap()->RemoveUpdateObject(this); +} + ObjectGuid WorldObject::GetTransGUID() const { if (GetTransport()) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index ab0c6f0da70..b4b66bd5121 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -20,6 +20,7 @@ #define _OBJECT_H #include "Common.h" +#include "Position.h" #include "UpdateMask.h" #include "GridReference.h" #include "ObjectDefines.h" @@ -246,6 +247,10 @@ class Object uint16 _fieldNotifyFlags; + virtual void AddToObjectUpdate() = 0; + virtual void RemoveFromObjectUpdate() = 0; + void AddToObjectUpdateIfNeeded(); + bool m_objectUpdated; private: @@ -259,141 +264,6 @@ class Object Object& operator=(Object const& right) = delete; }; -struct Position -{ - Position(float x = 0, float y = 0, float z = 0, float o = 0) - : m_positionX(x), m_positionY(y), m_positionZ(z), _orientation(NormalizeOrientation(o)) { } - - Position(Position const& loc) { Relocate(loc); } - - struct PositionXYZStreamer - { - explicit PositionXYZStreamer(Position& pos) : Pos(&pos) { } - Position* Pos; - }; - - struct PositionXYZOStreamer - { - explicit PositionXYZOStreamer(Position& pos) : Pos(&pos) { } - Position* Pos; - }; - - float m_positionX; - float m_positionY; - float m_positionZ; -// Better to limit access to _orientation field, to guarantee the value is normalized -private: - float _orientation; - -public: - bool operator==(Position const &a); - - inline bool operator!=(Position const &a) - { - return !(operator==(a)); - } - - void Relocate(float x, float y) - { m_positionX = x; m_positionY = y;} - void Relocate(float x, float y, float z) - { m_positionX = x; m_positionY = y; m_positionZ = z; } - void Relocate(float x, float y, float z, float orientation) - { m_positionX = x; m_positionY = y; m_positionZ = z; SetOrientation(orientation); } - void Relocate(Position const &pos) - { m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; SetOrientation(pos._orientation); } - void Relocate(Position const* pos) - { m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; SetOrientation(pos->_orientation); } - void RelocateOffset(Position const &offset); - void SetOrientation(float orientation) - { _orientation = NormalizeOrientation(orientation); } - - float GetPositionX() const { return m_positionX; } - float GetPositionY() const { return m_positionY; } - float GetPositionZ() const { return m_positionZ; } - float GetOrientation() const { return _orientation; } - - void GetPosition(float &x, float &y) const - { x = m_positionX; y = m_positionY; } - void GetPosition(float &x, float &y, float &z) const - { x = m_positionX; y = m_positionY; z = m_positionZ; } - void GetPosition(float &x, float &y, float &z, float &o) const - { x = m_positionX; y = m_positionY; z = m_positionZ; o = _orientation; } - - Position GetPosition() const - { - return *this; - } - - Position::PositionXYZStreamer PositionXYZStream() - { - return PositionXYZStreamer(*this); - } - Position::PositionXYZOStreamer PositionXYZOStream() - { - return PositionXYZOStreamer(*this); - } - - bool IsPositionValid() const; - - float GetExactDist2dSq(float x, float y) const - { float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy; } - float GetExactDist2d(const float x, const float y) const - { return std::sqrt(GetExactDist2dSq(x, y)); } - float GetExactDist2dSq(Position const* pos) const - { float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy; } - float GetExactDist2d(Position const* pos) const - { return std::sqrt(GetExactDist2dSq(pos)); } - float GetExactDistSq(float x, float y, float z) const - { float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz; } - float GetExactDist(float x, float y, float z) const - { return std::sqrt(GetExactDistSq(x, y, z)); } - float GetExactDistSq(Position const* pos) const - { float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz; } - float GetExactDist(Position const* pos) const - { return std::sqrt(GetExactDistSq(pos)); } - - void GetPositionOffsetTo(Position const & endPos, Position & retOffset) const; - Position GetPositionWithOffset(Position const& offset) const; - - float GetAngle(Position const* pos) const; - float GetAngle(float x, float y) const; - float GetRelativeAngle(Position const* pos) const - { return GetAngle(pos) - _orientation; } - float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - _orientation; } - void GetSinCos(float x, float y, float &vsin, float &vcos) const; - - bool IsInDist2d(float x, float y, float dist) const - { return GetExactDist2dSq(x, y) < dist * dist; } - bool IsInDist2d(Position const* pos, float dist) const - { return GetExactDist2dSq(pos) < dist * dist; } - bool IsInDist(float x, float y, float z, float dist) const - { return GetExactDistSq(x, y, z) < dist * dist; } - bool IsInDist(Position const* pos, float dist) const - { return GetExactDistSq(pos) < dist * dist; } - bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const; - bool HasInLine(WorldObject const* target, float width) const; - std::string ToString() const; - - // modulos a radian orientation to the range of 0..2PI - static float NormalizeOrientation(float o) - { - // fmod only supports positive numbers. Thus we have - // to emulate negative numbers - if (o < 0) - { - float mod = o *-1; - mod = std::fmod(mod, 2.0f * static_cast<float>(M_PI)); - mod = -mod + 2.0f * static_cast<float>(M_PI); - return mod; - } - return std::fmod(o, 2.0f * static_cast<float>(M_PI)); - } -}; -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); -ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); -ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); - struct MovementInfo { // common @@ -730,6 +600,8 @@ class WorldObject : public Object, public WorldLocation void DestroyForNearbyPlayers(); virtual void UpdateObjectVisibility(bool forced = true); void BuildUpdate(UpdateDataMapType&) override; + void AddToObjectUpdate() override; + void RemoveFromObjectUpdate() override; //relocation and visibility system functions void AddToNotify(uint16 f) { m_notifyflags |= f;} diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp index 1f9ca9736a2..4d607e59d1b 100644 --- a/src/server/game/Entities/Object/ObjectGuid.cpp +++ b/src/server/game/Entities/Object/ObjectGuid.cpp @@ -90,6 +90,22 @@ std::string ObjectGuid::ToString() const return str.str(); } +ObjectGuid ObjectGuid::Global(HighGuid type, LowType counter) +{ + return ObjectGuid(uint64(uint64(type) << 58), counter); +} + +ObjectGuid ObjectGuid::RealmSpecific(HighGuid type, LowType counter) +{ + return ObjectGuid(uint64(uint64(type) << 58 | uint64(realmHandle.Index) << 42), counter); +} + +ObjectGuid ObjectGuid::MapSpecific(HighGuid type, uint8 subType, uint16 mapId, uint32 serverId, uint32 entry, LowType counter) +{ + return ObjectGuid(uint64((uint64(type) << 58) | (uint64(realmHandle.Index & 0x1FFF) << 42) | (uint64(mapId & 0x1FFF) << 29) | (uint64(entry & 0x7FFFFF) << 6) | (uint64(subType) & 0x3F)), + uint64((uint64(serverId & 0xFFFFFF) << 40) | (counter & UI64LIT(0xFFFFFFFFFF)))); +} + std::vector<uint8> ObjectGuid::GetRawValue() const { std::vector<uint8> raw(16); @@ -121,17 +137,6 @@ void PackedGuid::Set(ObjectGuid const& guid) _packedGuid.put(1, highMask); } -template<HighGuid high> -ObjectGuid::LowType ObjectGuidGenerator<high>::Generate() -{ - if (_nextGuid >= ObjectGuid::GetMaxCounter(high) - 1) - { - TC_LOG_ERROR("", "%s guid overflow!! Can't continue, shutting down server. ", ObjectGuid::GetTypeName(high)); - World::StopNow(ERROR_EXIT_CODE); - } - return _nextGuid++; -} - ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid) { buf << guid.WriteAsPacked(); @@ -167,89 +172,11 @@ std::ostream& operator<<(std::ostream& stream, ObjectGuid const& guid) return stream; } -class GuidFormat -{ -public: - inline static ObjectGuid Global(HighGuid type, ObjectGuid::LowType counter) - { - return ObjectGuid(uint64(uint64(type) << 58), counter); - } - - inline static ObjectGuid RealmSpecific(HighGuid type, ObjectGuid::LowType counter) - { - return ObjectGuid(uint64(uint64(type) << 58 | uint64(realmHandle.Index) << 42), counter); - } - - inline static ObjectGuid MapSpecific(HighGuid type, uint8 subType, uint16 mapId, uint32 serverId, uint32 entry, ObjectGuid::LowType counter) - { - return ObjectGuid(uint64((uint64(type) << 58) | (uint64(realmHandle.Index & 0x1FFF) << 42) | (uint64(mapId & 0x1FFF) << 29) | (uint64(entry & 0x7FFFFF) << 6) | (uint64(subType) & 0x3F)), - uint64((uint64(serverId & 0xFFFFFF) << 40) | (counter & UI64LIT(0xFFFFFFFFFF)))); - } -}; - -#define GLOBAL_GUID_CREATE(highguid) template<> ObjectGuid ObjectGuid::Create<highguid>(LowType counter) { return GuidFormat::Global(highguid, counter); } -#define REALM_GUID_CREATE(highguid) template<> ObjectGuid ObjectGuid::Create<highguid>(LowType counter) { return GuidFormat::RealmSpecific(highguid, counter); } -#define MAP_GUID_CREATE(highguid) template<> ObjectGuid ObjectGuid::Create<highguid>(uint16 mapId, uint32 entry, LowType counter) { return GuidFormat::MapSpecific(highguid, 0, mapId, 0, entry, counter); } - -GLOBAL_GUID_CREATE(HighGuid::Uniq) -GLOBAL_GUID_CREATE(HighGuid::Party) -GLOBAL_GUID_CREATE(HighGuid::WowAccount) -GLOBAL_GUID_CREATE(HighGuid::BNetAccount) -GLOBAL_GUID_CREATE(HighGuid::GMTask) -GLOBAL_GUID_CREATE(HighGuid::RaidGroup) -GLOBAL_GUID_CREATE(HighGuid::Spell) -GLOBAL_GUID_CREATE(HighGuid::Mail) -GLOBAL_GUID_CREATE(HighGuid::UserRouter) -GLOBAL_GUID_CREATE(HighGuid::PVPQueueGroup) -GLOBAL_GUID_CREATE(HighGuid::UserClient) -GLOBAL_GUID_CREATE(HighGuid::UniqueUserClient) -GLOBAL_GUID_CREATE(HighGuid::BattlePet) -REALM_GUID_CREATE(HighGuid::Player) -REALM_GUID_CREATE(HighGuid::Item) // This is not exactly correct, there are 2 more unknown parts in highguid: (high >> 10 & 0xFF), (high >> 18 & 0xFFFFFF) -REALM_GUID_CREATE(HighGuid::Transport) -REALM_GUID_CREATE(HighGuid::Guild) -MAP_GUID_CREATE(HighGuid::Conversation) -MAP_GUID_CREATE(HighGuid::Creature) -MAP_GUID_CREATE(HighGuid::Vehicle) -MAP_GUID_CREATE(HighGuid::Pet) -MAP_GUID_CREATE(HighGuid::GameObject) -MAP_GUID_CREATE(HighGuid::DynamicObject) -MAP_GUID_CREATE(HighGuid::AreaTrigger) -MAP_GUID_CREATE(HighGuid::Corpse) -MAP_GUID_CREATE(HighGuid::LootObject) -MAP_GUID_CREATE(HighGuid::SceneObject) -MAP_GUID_CREATE(HighGuid::Scenario) -MAP_GUID_CREATE(HighGuid::AIGroup) -MAP_GUID_CREATE(HighGuid::DynamicDoor) -MAP_GUID_CREATE(HighGuid::Vignette) -MAP_GUID_CREATE(HighGuid::CallForHelp) -MAP_GUID_CREATE(HighGuid::AIResource) -MAP_GUID_CREATE(HighGuid::AILock) -MAP_GUID_CREATE(HighGuid::AILockTicket) - ObjectGuid const ObjectGuid::Empty = ObjectGuid(); ObjectGuid const ObjectGuid::TradeItem = ObjectGuid::Create<HighGuid::Uniq>(uint64(10)); -template<HighGuid type> -ObjectGuid ObjectGuid::Create(LowType /*counter*/) +void ObjectGuidGeneratorBase::HandleCounterOverflow(HighGuid high) { - static_assert(type == HighGuid::Count, "This guid type cannot be constructed using Create(LowType counter)."); + TC_LOG_ERROR("misc", "%s guid overflow!! Can't continue, shutting down server. ", ObjectGuid::GetTypeName(high)); + World::StopNow(ERROR_EXIT_CODE); } - -template<HighGuid type> -ObjectGuid ObjectGuid::Create(uint16 /*mapId*/, uint32 /*entry*/, LowType /*counter*/) -{ - static_assert(type == HighGuid::Count, "This guid type cannot be constructed using Create(uint16 mapId, uint32 entry, LowType counter)."); -} - -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::Player>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::Creature>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::Pet>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::Vehicle>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::Item>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::GameObject>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::DynamicObject>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::Corpse>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::LootObject>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::AreaTrigger>::Generate(); -template ObjectGuid::LowType ObjectGuidGenerator<HighGuid::Transport>::Generate(); diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index 72fda2feb5e..281bc170c3a 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -22,7 +22,7 @@ #include "Common.h" #include "ByteBuffer.h" #include <boost/functional/hash.hpp> - +#include <type_traits> #include <functional> #include <unordered_set> @@ -109,9 +109,76 @@ enum class HighGuid Count, }; +template<HighGuid high> +struct ObjectGuidTraits +{ + static bool const Global = false; + static bool const RealmSpecific = false; + static bool const MapSpecific = false; +}; + +#define GUID_TRAIT_GLOBAL(highguid) \ + template<> struct ObjectGuidTraits<highguid> \ + { \ + static bool const Global = true; \ + static bool const RealmSpecific = false; \ + static bool const MapSpecific = false; \ + }; + +#define GUID_TRAIT_REALM_SPECIFIC(highguid) \ + template<> struct ObjectGuidTraits<highguid> \ + { \ + static bool const Global = false; \ + static bool const RealmSpecific = true; \ + static bool const MapSpecific = false; \ + }; + +#define GUID_TRAIT_MAP_SPECIFIC(highguid) \ + template<> struct ObjectGuidTraits<highguid> \ + { \ + static bool const Global = false; \ + static bool const RealmSpecific = false; \ + static bool const MapSpecific = true; \ + }; + +GUID_TRAIT_GLOBAL(HighGuid::Uniq) +GUID_TRAIT_GLOBAL(HighGuid::Party) +GUID_TRAIT_GLOBAL(HighGuid::WowAccount) +GUID_TRAIT_GLOBAL(HighGuid::BNetAccount) +GUID_TRAIT_GLOBAL(HighGuid::GMTask) +GUID_TRAIT_GLOBAL(HighGuid::RaidGroup) +GUID_TRAIT_GLOBAL(HighGuid::Spell) +GUID_TRAIT_GLOBAL(HighGuid::Mail) +GUID_TRAIT_GLOBAL(HighGuid::UserRouter) +GUID_TRAIT_GLOBAL(HighGuid::PVPQueueGroup) +GUID_TRAIT_GLOBAL(HighGuid::UserClient) +GUID_TRAIT_GLOBAL(HighGuid::UniqueUserClient) +GUID_TRAIT_GLOBAL(HighGuid::BattlePet) +GUID_TRAIT_REALM_SPECIFIC(HighGuid::Player) +GUID_TRAIT_REALM_SPECIFIC(HighGuid::Item) // This is not exactly correct, there are 2 more unknown parts in highguid: (high >> 10 & 0xFF), (high >> 18 & 0xFFFFFF) +GUID_TRAIT_REALM_SPECIFIC(HighGuid::Transport) +GUID_TRAIT_REALM_SPECIFIC(HighGuid::Guild) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::Conversation) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::Creature) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::Vehicle) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::Pet) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::GameObject) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::DynamicObject) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::AreaTrigger) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::Corpse) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::LootObject) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::SceneObject) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::Scenario) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::AIGroup) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::DynamicDoor) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::Vignette) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::CallForHelp) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::AIResource) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::AILock) +GUID_TRAIT_MAP_SPECIFIC(HighGuid::AILockTicket) + class ObjectGuid; class PackedGuid; -class GuidFormat; struct PackedGuidReader { @@ -126,7 +193,6 @@ class ObjectGuid friend std::ostream& operator<<(std::ostream& stream, ObjectGuid const& guid); friend ByteBuffer& operator>>(ByteBuffer& buf, PackedGuidReader const& guid); friend class PackedGuid; - friend class GuidFormat; public: static ObjectGuid const Empty; @@ -135,10 +201,13 @@ class ObjectGuid typedef uint64 LowType; template<HighGuid type> - static ObjectGuid Create(LowType counter); + static typename std::enable_if<ObjectGuidTraits<type>::Global, ObjectGuid>::type Create(LowType counter) { return Global(type, counter); } template<HighGuid type> - static ObjectGuid Create(uint16 mapId, uint32 entry, LowType counter); + static typename std::enable_if<ObjectGuidTraits<type>::RealmSpecific, ObjectGuid>::type Create(LowType counter) { return RealmSpecific(type, counter); } + + template<HighGuid type> + static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific, ObjectGuid>::type Create(uint16 mapId, uint32 entry, LowType counter) { return MapSpecific(type, 0, mapId, 0, entry, counter); } ObjectGuid() : _low(0), _high(0) { } ObjectGuid(ObjectGuid const&) = default; @@ -253,6 +322,10 @@ class ObjectGuid bool HasEntry() const { return HasEntry(GetHigh()); } + static ObjectGuid Global(HighGuid type, LowType counter); + static ObjectGuid RealmSpecific(HighGuid type, LowType counter); + static ObjectGuid MapSpecific(HighGuid type, uint8 subType, uint16 mapId, uint32 serverId, uint32 entry, LowType counter); + ObjectGuid(uint64 high, uint64 low) : _low(low), _high(high) { } explicit ObjectGuid(uint32 const&) = delete; // no implementation, used to catch wrong type assignment @@ -288,18 +361,32 @@ class PackedGuid ByteBuffer _packedGuid; }; -template<HighGuid high> -class ObjectGuidGenerator +class ObjectGuidGeneratorBase { - public: - explicit ObjectGuidGenerator(ObjectGuid::LowType start = UI64LIT(1)) : _nextGuid(start) { } +public: + ObjectGuidGeneratorBase(ObjectGuid::LowType start = UI64LIT(1)) : _nextGuid(start) { } - void Set(uint64 val) { _nextGuid = val; } - ObjectGuid::LowType Generate(); - ObjectGuid::LowType GetNextAfterMaxUsed() const { return _nextGuid; } + virtual void Set(uint64 val) { _nextGuid = val; } + virtual ObjectGuid::LowType Generate() = 0; + ObjectGuid::LowType GetNextAfterMaxUsed() const { return _nextGuid; } - private: - uint64 _nextGuid; +protected: + static void HandleCounterOverflow(HighGuid high); + uint64 _nextGuid; +}; + +template<HighGuid high> +class ObjectGuidGenerator : public ObjectGuidGeneratorBase +{ +public: + explicit ObjectGuidGenerator(ObjectGuid::LowType start = UI64LIT(1)) : ObjectGuidGeneratorBase(start) { } + + ObjectGuid::LowType Generate() override + { + if (_nextGuid >= ObjectGuid::GetMaxCounter(high) - 1) + HandleCounterOverflow(high); + return _nextGuid++; + } }; ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid); diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp new file mode 100644 index 00000000000..530e51cd8f5 --- /dev/null +++ b/src/server/game/Entities/Object/Position.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Position.h" +#include "ByteBuffer.h" +#include "G3D/g3dmath.h" +#include "GridDefines.h" + +bool Position::operator==(Position const &a) +{ + return (G3D::fuzzyEq(a.m_positionX, m_positionX) && + G3D::fuzzyEq(a.m_positionY, m_positionY) && + G3D::fuzzyEq(a.m_positionZ, m_positionZ) && + G3D::fuzzyEq(a.m_orientation, m_orientation)); +} + +void Position::RelocateOffset(const Position & offset) +{ + m_positionX = GetPositionX() + (offset.GetPositionX() * std::cos(GetOrientation()) + offset.GetPositionY() * std::sin(GetOrientation() + float(M_PI))); + m_positionY = GetPositionY() + (offset.GetPositionY() * std::cos(GetOrientation()) + offset.GetPositionX() * std::sin(GetOrientation())); + m_positionZ = GetPositionZ() + offset.GetPositionZ(); + SetOrientation(GetOrientation() + offset.GetOrientation()); +} + +bool Position::IsPositionValid() const +{ + return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation); +} + +void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const +{ + float dx = endPos.GetPositionX() - GetPositionX(); + float dy = endPos.GetPositionY() - GetPositionY(); + + retOffset.m_positionX = dx * std::cos(GetOrientation()) + dy * std::sin(GetOrientation()); + retOffset.m_positionY = dy * std::cos(GetOrientation()) - dx * std::sin(GetOrientation()); + retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ(); + retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation()); +} + +Position Position::GetPositionWithOffset(Position const& offset) const +{ + Position ret(*this); + ret.RelocateOffset(offset); + return ret; +} + +float Position::GetAngle(const Position* obj) const +{ + if (!obj) + return 0; + + return GetAngle(obj->GetPositionX(), obj->GetPositionY()); +} + +// Return angle in range 0..2*pi +float Position::GetAngle(float x, float y) const +{ + float dx = x - GetPositionX(); + float dy = y - GetPositionY(); + + float ang = std::atan2(dy, dx); + ang = (ang >= 0) ? ang : 2 * float(M_PI) + ang; + return ang; +} + +void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) const +{ + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + + if (std::fabs(dx) < 0.001f && std::fabs(dy) < 0.001f) + { + float angle = (float)rand_norm()*static_cast<float>(2 * M_PI); + vcos = std::cos(angle); + vsin = std::sin(angle); + } + else + { + float dist = std::sqrt((dx*dx) + (dy*dy)); + vcos = dx / dist; + vsin = dy / dist; + } +} + +bool Position::HasInArc(float arc, const Position* obj, float border) const +{ + // always have self in arc + if (obj == this) + return true; + + // move arc to range 0.. 2*pi + arc = NormalizeOrientation(arc); + + float angle = GetAngle(obj); + angle -= m_orientation; + + // move angle to range -pi ... +pi + angle = NormalizeOrientation(angle); + if (angle > float(M_PI)) + angle -= 2.0f * float(M_PI); + + float lborder = -1 * (arc / border); // in range -pi..0 + float rborder = (arc / border); // in range 0..pi + return ((angle >= lborder) && (angle <= rborder)); +} + +bool Position::HasInLine(Position const* pos, float width) const +{ + if (!HasInArc(float(M_PI), pos)) + return false; + + float angle = GetRelativeAngle(pos); + return std::fabs(std::sin(angle)) * GetExactDist2d(pos->GetPositionX(), pos->GetPositionY()) < width; +} + +std::string Position::ToString() const +{ + std::stringstream sstr; + sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << m_orientation; + return sstr.str(); +} + +ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer) +{ + buf << streamer.Pos->GetPositionX(); + buf << streamer.Pos->GetPositionY(); + return buf; +} + +ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer) +{ + float x, y; + buf >> x >> y; + streamer.Pos->Relocate(x, y); + return buf; +} + +ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer) +{ + buf << streamer.Pos->GetPositionX(); + buf << streamer.Pos->GetPositionY(); + buf << streamer.Pos->GetPositionZ(); + return buf; +} + +ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer) +{ + float x, y, z; + buf >> x >> y >> z; + streamer.Pos->Relocate(x, y, z); + return buf; +} + +ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer) +{ + buf << streamer.Pos->GetPositionX(); + buf << streamer.Pos->GetPositionY(); + buf << streamer.Pos->GetPositionZ(); + buf << streamer.Pos->GetOrientation(); + return buf; +} + +ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer) +{ + float x, y, z, o; + buf >> x >> y >> z >> o; + streamer.Pos->Relocate(x, y, z, o); + return buf; +} diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h new file mode 100644 index 00000000000..5bd37567811 --- /dev/null +++ b/src/server/game/Entities/Object/Position.h @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef Trinity_game_Position_h__ +#define Trinity_game_Position_h__ + +#include "Common.h" + +class ByteBuffer; + +struct Position +{ + Position(float x = 0, float y = 0, float z = 0, float o = 0) + : m_positionX(x), m_positionY(y), m_positionZ(z), m_orientation(NormalizeOrientation(o)) { } + + Position(Position const& loc) { Relocate(loc); } + + struct PositionXYStreamer + { + explicit PositionXYStreamer(Position& pos) : Pos(&pos) { } + Position* Pos; + }; + + struct PositionXYZStreamer + { + explicit PositionXYZStreamer(Position& pos) : Pos(&pos) { } + Position* Pos; + }; + + struct PositionXYZOStreamer + { + explicit PositionXYZOStreamer(Position& pos) : Pos(&pos) { } + Position* Pos; + }; + + float m_positionX; + float m_positionY; + float m_positionZ; + // Better to limit access to _orientation field, to guarantee the value is normalized +private: + float m_orientation; + +public: + bool operator==(Position const &a); + + inline bool operator!=(Position const &a) + { + return !(operator==(a)); + } + + void Relocate(float x, float y) + { + m_positionX = x; m_positionY = y; + } + + void Relocate(float x, float y, float z) + { + m_positionX = x; m_positionY = y; m_positionZ = z; + } + + void Relocate(float x, float y, float z, float orientation) + { + m_positionX = x; m_positionY = y; m_positionZ = z; SetOrientation(orientation); + } + + void Relocate(Position const &pos) + { + m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; SetOrientation(pos.m_orientation); + } + + void Relocate(Position const* pos) + { + m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; SetOrientation(pos->m_orientation); + } + + void RelocateOffset(Position const &offset); + + void SetOrientation(float orientation) + { + m_orientation = NormalizeOrientation(orientation); + } + + float GetPositionX() const { return m_positionX; } + float GetPositionY() const { return m_positionY; } + float GetPositionZ() const { return m_positionZ; } + float GetOrientation() const { return m_orientation; } + + void GetPosition(float &x, float &y) const + { + x = m_positionX; y = m_positionY; + } + + void GetPosition(float &x, float &y, float &z) const + { + x = m_positionX; y = m_positionY; z = m_positionZ; + } + + void GetPosition(float &x, float &y, float &z, float &o) const + { + x = m_positionX; y = m_positionY; z = m_positionZ; o = m_orientation; + } + + Position GetPosition() const { return *this; } + + Position::PositionXYStreamer PositionXYStream() { return PositionXYStreamer(*this); } + Position::PositionXYZStreamer PositionXYZStream() { return PositionXYZStreamer(*this); } + Position::PositionXYZOStreamer PositionXYZOStream() { return PositionXYZOStreamer(*this); } + + bool IsPositionValid() const; + + float GetExactDist2dSq(float x, float y) const + { + float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy; + } + + float GetExactDist2d(const float x, const float y) const + { + return std::sqrt(GetExactDist2dSq(x, y)); + } + + float GetExactDist2dSq(Position const* pos) const + { + float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy; + } + + float GetExactDist2d(Position const* pos) const + { + return std::sqrt(GetExactDist2dSq(pos)); + } + + float GetExactDistSq(float x, float y, float z) const + { + float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz; + } + + float GetExactDist(float x, float y, float z) const + { + return std::sqrt(GetExactDistSq(x, y, z)); + } + + float GetExactDistSq(Position const* pos) const + { + float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz; + } + + float GetExactDist(Position const* pos) const + { + return std::sqrt(GetExactDistSq(pos)); + } + + void GetPositionOffsetTo(Position const & endPos, Position & retOffset) const; + Position GetPositionWithOffset(Position const& offset) const; + + float GetAngle(Position const* pos) const; + float GetAngle(float x, float y) const; + float GetRelativeAngle(Position const* pos) const + { + return GetAngle(pos) - m_orientation; + } + + float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - m_orientation; } + void GetSinCos(float x, float y, float &vsin, float &vcos) const; + + bool IsInDist2d(float x, float y, float dist) const + { + return GetExactDist2dSq(x, y) < dist * dist; + } + + bool IsInDist2d(Position const* pos, float dist) const + { + return GetExactDist2dSq(pos) < dist * dist; + } + + bool IsInDist(float x, float y, float z, float dist) const + { + return GetExactDistSq(x, y, z) < dist * dist; + } + + bool IsInDist(Position const* pos, float dist) const + { + return GetExactDistSq(pos) < dist * dist; + } + + bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const; + bool HasInLine(Position const* pos, float width) const; + std::string ToString() const; + + // modulos a radian orientation to the range of 0..2PI + static float NormalizeOrientation(float o) + { + // fmod only supports positive numbers. Thus we have + // to emulate negative numbers + if (o < 0) + { + float mod = o *-1; + mod = std::fmod(mod, 2.0f * static_cast<float>(M_PI)); + mod = -mod + 2.0f * static_cast<float>(M_PI); + return mod; + } + return std::fmod(o, 2.0f * static_cast<float>(M_PI)); + } +}; + +ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer); +ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer); +ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); +ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); +ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); +ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); + +#endif // Trinity_game_Position_h__ diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index dbb8c99d7c9..05d649fe632 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -69,7 +69,7 @@ void Pet::AddToWorld() if (!IsInWorld()) { ///- Register the pet for guid lookup - sObjectAccessor->AddObject(this); + GetMap()->GetObjectsStore().Insert<Pet>(GetGUID(), this); Unit::AddToWorld(); AIM_Initialize(); } @@ -93,7 +93,7 @@ void Pet::RemoveFromWorld() { ///- Don't call the function for Creature, normal mobs + totems go in a different storage Unit::RemoveFromWorld(); - sObjectAccessor->RemoveObject(this); + GetMap()->GetObjectsStore().Remove<Pet>(GetGUID()); } } @@ -177,7 +177,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c } Map* map = owner->GetMap(); - if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, petEntry)) + if (!Create(map->GenerateLowGuid<HighGuid::Pet>(), map, petEntry)) return false; CopyPhaseFrom(owner); @@ -208,7 +208,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c SetDisplayId(fields[3].GetUInt32()); SetNativeDisplayId(fields[3].GetUInt32()); uint32 petlevel = fields[4].GetUInt16(); - SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); SetName(fields[8].GetString()); switch (getPetType()) @@ -778,14 +778,14 @@ bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner) bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map) { TC_LOG_DEBUG("entities.pet", "Pet::CreateBaseForTamed"); - if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, cinfo->Entry)) + if (!Create(map->GenerateLowGuid<HighGuid::Pet>(), map, cinfo->Entry)) return false; setPowerType(POWER_FOCUS); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32(sObjectMgr->GetXPForLevel(getLevel()+1)*PET_XP_FACTOR)); - SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); if (cinfo->type == CREATURE_TYPE_BEAST) { @@ -1808,7 +1808,7 @@ bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 Entry) Object::_Create(ObjectGuid::Create<HighGuid::Pet>(map->GetId(), Entry, guidlow)); - m_DBTableGuid = guidlow; + m_spawnId = guidlow; m_originalEntry = Entry; if (!InitEntry(Entry)) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 95d209a8cd2..109b1a53657 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -31,20 +31,22 @@ #include "ChannelMgr.h" #include "CharacterDatabaseCleaner.h" #include "CharacterPackets.h" -#include "TalentPackets.h" #include "Chat.h" +#include "ChatPackets.h" #include "CombatLogPackets.h" #include "CombatPackets.h" #include "Common.h" #include "ConditionMgr.h" #include "CreatureAI.h" -#include "DatabaseEnv.h" #include "DB2Stores.h" +#include "DatabaseEnv.h" #include "DisableMgr.h" +#include "DuelPackets.h" #include "EquipmentSetPackets.h" #include "Formulas.h" #include "GameEventMgr.h" #include "GameObjectAI.h" +#include "Garrison.h" #include "GossipDef.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -52,14 +54,19 @@ #include "GroupMgr.h" #include "Guild.h" #include "GuildMgr.h" +#include "InstancePackets.h" #include "InstanceSaveMgr.h" #include "InstanceScript.h" +#include "ItemPackets.h" #include "LFGMgr.h" #include "Language.h" #include "Log.h" +#include "LootPackets.h" #include "MailPackets.h" #include "MapInstanced.h" #include "MapManager.h" +#include "MiscPackets.h" +#include "MovementPackets.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Opcodes.h" @@ -67,6 +74,7 @@ #include "OutdoorPvPMgr.h" #include "Pet.h" #include "QuestDef.h" +#include "QuestPackets.h" #include "ReputationMgr.h" #include "revision.h" #include "SkillDiscovery.h" @@ -77,27 +85,21 @@ #include "SpellHistory.h" #include "SpellMgr.h" #include "SpellPackets.h" +#include "TalentPackets.h" +#include "TradePackets.h" #include "Transport.h" #include "UpdateData.h" #include "UpdateFieldFlags.h" #include "UpdateMask.h" #include "Util.h" #include "Vehicle.h" +#include "VehiclePackets.h" #include "Weather.h" #include "WeatherMgr.h" #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" #include "WorldStatePackets.h" -#include "MiscPackets.h" -#include "ChatPackets.h" -#include "DuelPackets.h" -#include "MovementPackets.h" -#include "ItemPackets.h" -#include "QuestPackets.h" -#include "LootPackets.h" -#include "TradePackets.h" -#include "VehiclePackets.h" #define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS) @@ -2057,6 +2059,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // this will be used instead of the current location in SaveToDB m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); + m_teleport_options = options; SetFallInformation(0, z); // code for finish transfer called in WorldSession::HandleMovementOpcodes() @@ -2086,6 +2089,12 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (!sMapMgr->CanPlayerEnter(mapid, this, false)) return false; + // Seamless teleport can happen only if cosmetic maps match + if (!oldmap || + (oldmap->GetEntry()->CosmeticParentMapID != int32(mapid) && int32(GetMapId()) != mEntry->CosmeticParentMapID && + !((oldmap->GetEntry()->CosmeticParentMapID != -1) ^ (oldmap->GetEntry()->CosmeticParentMapID != mEntry->CosmeticParentMapID)))) + options &= ~TELE_TO_SEAMLESS; + //I think this always returns true. Correct me if I am wrong. // If the map is not created, assume it is possible to enter it. // It will be created in the WorldPortAck. @@ -2148,16 +2157,16 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati //remove auras before removing from map... RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING); - if (!GetSession()->PlayerLogout()) + if (!GetSession()->PlayerLogout() && !(options & TELE_TO_SEAMLESS)) { // send transfer packets WorldPackets::Movement::TransferPending transferPending; transferPending.MapID = mapid; if (Transport* transport = GetTransport()) { - transferPending.Ship.HasValue = true; - transferPending.Ship.Value.ID = transport->GetEntry(); - transferPending.Ship.Value.OriginMapID = GetMapId(); + transferPending.Ship = boost::in_place(); + transferPending.Ship->ID = transport->GetEntry(); + transferPending.Ship->OriginMapID = GetMapId(); } GetSession()->SendPacket(transferPending.Write()); @@ -2168,19 +2177,25 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati oldmap->RemovePlayerFromMap(this, false); m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); + m_teleport_options = options; SetFallInformation(0, z); // if the player is saved before worldportack (at logout for example) // this will be used instead of the current location in SaveToDB if (!GetSession()->PlayerLogout()) { + if (mEntry->IsDungeon()) + { + WorldPackets::Instance::UpdateLastInstance updateLastInstance; + updateLastInstance.MapID = mapid; + SendDirectMessage(updateLastInstance.Write()); + } + WorldPackets::Movement::NewWorld packet; packet.MapID = mapid; packet.Pos = m_teleport_dest; - packet.Reason = NEW_WORLD_NORMAL; - + packet.Reason = !(options & TELE_TO_SEAMLESS) ? NEW_WORLD_NORMAL : NEW_WORLD_SEAMLESS; SendDirectMessage(packet.Write()); - SendSavedInstances(); } // move packet sent by client always after far teleport @@ -2620,7 +2635,7 @@ bool Player::CanInteractWithQuestGiver(Object* questGiver) return false; } -Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask) +Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint64 npcflagmask) { // unit checks if (!guid) @@ -2646,7 +2661,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask) return NULL; // appropriate npc type - if (npcflagmask && !creature->HasFlag(UNIT_NPC_FLAGS, npcflagmask)) + if (npcflagmask && !creature->HasFlag64(UNIT_NPC_FLAGS, npcflagmask)) return NULL; // not allow interaction under control, but allow with own pets @@ -4136,7 +4151,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell return TRAINER_SPELL_RED; bool hasSpell = true; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i) { if (!trainer_spell->ReqAbility[i]) continue; @@ -4159,7 +4174,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell if (getLevel() < trainer_spell->ReqLevel) return TRAINER_SPELL_RED; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i) { if (!trainer_spell->ReqAbility[i]) continue; @@ -4186,7 +4201,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell // check primary prof. limit // first rank of primary profession spell when there are no proffesions avalible is disabled - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i) { if (!trainer_spell->ReqAbility[i]) continue; @@ -4560,6 +4575,26 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe stmt->setUInt64(0, guid); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE); + stmt->setUInt64(0, guid); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE_PHASES); + stmt->setUInt64(0, guid); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON); + stmt->setUInt64(0, guid); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS); + stmt->setUInt64(0, guid); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS); + stmt->setUInt64(0, guid); + trans->Append(stmt); + CharacterDatabase.CommitTransaction(trans); sWorld->DeleteCharacterInfo(playerguid); @@ -4805,7 +4840,7 @@ void Player::CreateCorpse() Corpse* corpse = new Corpse((m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH) ? CORPSE_RESURRECTABLE_PVP : CORPSE_RESURRECTABLE_PVE); SetPvPDeath(false); - if (!corpse->Create(sObjectMgr->GetGenerator<HighGuid::Corpse>()->Generate(), this)) + if (!corpse->Create(GetMap()->GenerateLowGuid<HighGuid::Corpse>(), this)) { delete corpse; return; @@ -5198,7 +5233,7 @@ void Player::UpdateLocalChannels(uint32 newZone) if (channel->Flags & CHANNEL_DBC_FLAG_CITY_ONLY) currentNameExt = sObjectMgr->GetTrinityStringForDBCLocale(LANG_CHANNEL_CITY); else - currentNameExt = current_zone->ZoneName; + currentNameExt = current_zone->AreaName_lang; snprintf(new_channel_name_buf, 100, channel->Name_lang, currentNameExt); @@ -6875,9 +6910,9 @@ void Player::SendNewCurrency(uint32 id) const WorldPackets::Misc::SetupCurrency::Record record; record.Type = entry->ID; record.Quantity = itr->second.Quantity; - record.WeeklyQuantity.Set(itr->second.WeeklyQuantity); - record.MaxWeeklyQuantity.Set(GetCurrencyWeekCap(entry) / ((entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1)); - record.TrackedQuantity.Set(itr->second.TrackedQuantity); + record.WeeklyQuantity = itr->second.WeeklyQuantity; + record.MaxWeeklyQuantity = GetCurrencyWeekCap(entry) / ((entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1); + record.TrackedQuantity = itr->second.TrackedQuantity; record.Flags = itr->second.Flags; packet.Data.push_back(record); @@ -6901,9 +6936,9 @@ void Player::SendCurrencies() const WorldPackets::Misc::SetupCurrency::Record record; record.Type = entry->ID; record.Quantity = itr->second.Quantity; - record.WeeklyQuantity.Set(itr->second.WeeklyQuantity); - record.MaxWeeklyQuantity.Set(GetCurrencyWeekCap(entry) / ((entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1)); - record.TrackedQuantity.Set(itr->second.TrackedQuantity); + record.WeeklyQuantity = itr->second.WeeklyQuantity; + record.MaxWeeklyQuantity = GetCurrencyWeekCap(entry) / ((entry->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1); + record.TrackedQuantity = itr->second.TrackedQuantity; record.Flags = itr->second.Flags; packet.Data.push_back(record); @@ -7049,8 +7084,8 @@ void Player::ModifyCurrency(uint32 id, int32 count, bool printLog/* = true*/, bo packet.Type = id; packet.Quantity = newTotalCount; packet.SuppressChatLog = !printLog; - packet.WeeklyQuantity.Set(newWeekCount); - packet.TrackedQuantity.Set(newTrackedCount); + packet.WeeklyQuantity = newWeekCount; + packet.TrackedQuantity = newTrackedCount; packet.Flags = itr->second.Flags; GetSession()->SendPacket(packet.Write()); @@ -7650,7 +7685,7 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) if (statType == -1) continue; - int32 val = item->GetItemStatValue(i); + int32 val = item->GetItemStatValue(i, this); if (val == 0) continue; @@ -7816,7 +7851,7 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply) } } - if (uint32 armor = item->GetArmor()) + if (uint32 armor = item->GetArmor(this)) { UnitModifierType modType = TOTAL_VALUE; if (proto->GetClass() == ITEM_CLASS_ARMOR) @@ -7876,7 +7911,7 @@ void Player::_ApplyWeaponDamage(uint8 slot, Item* item, bool apply) } float minDamage, maxDamage; - item->GetDamage(minDamage, maxDamage); + item->GetDamage(this, minDamage, maxDamage); if (minDamage > 0) { @@ -7986,7 +8021,7 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType att } } -void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change) +void Player::ApplyItemEquipSpell(Item* item, bool apply, bool formChange /*= false*/) { if (!item) return; @@ -8008,11 +8043,11 @@ void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change) if (!spellproto) continue; - ApplyEquipSpell(spellproto, item, apply, form_change); + ApplyEquipSpell(spellproto, item, apply, formChange); } } -void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool form_change) +void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool formChange /*= false*/) { if (apply) { @@ -8020,7 +8055,7 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, if (spellInfo->CheckShapeshift(GetShapeshiftForm()) != SPELL_CAST_OK) return; - if (form_change) // check aura active state from other form + if (formChange) // check aura active state from other form { AuraApplicationMapBounds range = GetAppliedAuras().equal_range(spellInfo->Id); for (AuraApplicationMap::const_iterator itr = range.first; itr != range.second; ++itr) @@ -8034,7 +8069,7 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, } else { - if (form_change) // check aura compatibility + if (formChange) // check aura compatibility { // Cannot be used in this stance/form if (spellInfo->CheckShapeshift(GetShapeshiftForm()) == SPELL_CAST_OK) @@ -8059,6 +8094,11 @@ void Player::UpdateEquipSpellsAtFormChange() } } + UpdateItemSetAuras(true); +} + +void Player::UpdateItemSetAuras(bool formChange /*= false*/) +{ // item set bonuses not dependent from item broken state for (size_t setindex = 0; setindex < ItemSetEff.size(); ++setindex) { @@ -8066,17 +8106,21 @@ void Player::UpdateEquipSpellsAtFormChange() if (!eff) continue; - for (uint32 y = 0; y < MAX_ITEM_SET_SPELLS; ++y) + for (ItemSetSpellEntry const* itemSetSpell : eff->SetBonuses) { - SpellInfo const* spellInfo = eff->spells[y]; - if (!spellInfo) - continue; + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID); - ApplyEquipSpell(spellInfo, NULL, false, true); // remove spells that not fit to form - ApplyEquipSpell(spellInfo, NULL, true, true); // add spells that fit form but not active + if (itemSetSpell->ChrSpecID && itemSetSpell->ChrSpecID != GetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID)) + ApplyEquipSpell(spellInfo, nullptr, false, false); // item set aura is not for current spec + else + { + ApplyEquipSpell(spellInfo, nullptr, false, formChange); // remove spells that not fit to form - removal is skipped if shapeshift condition is satisfied + ApplyEquipSpell(spellInfo, nullptr, true, formChange); // add spells that fit form but not active + } } } } + void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx) { if (!target || !target->IsAlive() || target == this) @@ -11402,10 +11446,10 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const if (!proto) return EQUIP_ERR_ITEM_NOT_FOUND; - if ((proto->GetFlags2() & ITEM_FLAGS_EXTRA_HORDE_ONLY) && GetTeam() != HORDE) + if ((proto->GetFlags2() & ITEM_FLAG2_HORDE_ONLY) && GetTeam() != HORDE) return EQUIP_ERR_CANT_EQUIP_EVER; - if ((proto->GetFlags2() & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && GetTeam() != ALLIANCE) + if ((proto->GetFlags2() & ITEM_FLAG2_ALLIANCE_ONLY) && GetTeam() != ALLIANCE) return EQUIP_ERR_CANT_EQUIP_EVER; if ((proto->GetAllowableClass() & getClassMask()) == 0 || (proto->GetAllowableRace() & getRaceMask()) == 0) @@ -11995,7 +12039,7 @@ void Player::MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool // in case trade we already have item in other player inventory pLastItem->SetState(in_characterInventoryDB ? ITEM_CHANGED : ITEM_NEW, this); - if (pLastItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE)) + if (pLastItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE)) AddTradeableItem(pLastItem); } } @@ -12012,7 +12056,7 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) DestroyItem(slot, i, update); - if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) + if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT); @@ -12085,7 +12129,7 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) // Delete rolled money / loot from db. // MUST be done before RemoveFromWorld() or GetTemplate() fails if (ItemTemplate const* pTmp = pItem->GetTemplate()) - if (pTmp->GetFlags() & ITEM_PROTO_FLAG_OPENABLE) + if (pTmp->GetFlags() & ITEM_FLAG_OPENABLE) pItem->ItemContainerDeleteLootMoneyAndLootItemsFromDB(); if (IsInWorld() && update) @@ -13669,11 +13713,11 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool if (menuItemBounds.first == menuItemBounds.second && menuId == GetDefaultGossipMenuForSource(source)) menuItemBounds = sObjectMgr->GetGossipMenuItemsMapBounds(0); - uint32 npcflags = 0; + uint64 npcflags = 0; if (source->GetTypeId() == TYPEID_UNIT) { - npcflags = source->GetUInt32Value(UNIT_NPC_FLAGS); + npcflags = source->GetUInt64Value(UNIT_NPC_FLAGS); if (showQuests && npcflags & UNIT_NPC_FLAG_QUESTGIVER) PrepareQuestMenu(source->GetGUID()); } @@ -13706,7 +13750,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool VendorItemData const* vendorItems = creature->GetVendorItems(); if (!vendorItems || vendorItems->Empty()) { - TC_LOG_ERROR("sql.sql", "Creature %s (%s DB GUID: " UI64FMTD ") has UNIT_NPC_FLAG_VENDOR set but has an empty trading item list.", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), creature->GetDBTableGUIDLow()); + TC_LOG_ERROR("sql.sql", "Creature %s (%s DB GUID: " UI64FMTD ") has UNIT_NPC_FLAG_VENDOR set but has an empty trading item list.", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), creature->GetSpawnId()); canTalk = false; } break; @@ -13895,7 +13939,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men break; } case GOSSIP_OPTION_OUTDOORPVP: - sOutdoorPvPMgr->HandleGossipOption(this, source->GetGUID(), gossipListId); + sOutdoorPvPMgr->HandleGossipOption(this, source->ToCreature(), gossipListId); break; case GOSSIP_OPTION_SPIRITHEALER: if (isDead()) @@ -14114,7 +14158,7 @@ void Player::SendPreparedQuest(ObjectGuid guid) return; } - if (object->GetTypeId() != TYPEID_UNIT || object->ToCreature()->GetUInt32Value(UNIT_NPC_FLAGS) & UNIT_NPC_FLAG_GOSSIP) + if (object->GetTypeId() != TYPEID_UNIT || object->GetUInt64Value(UNIT_NPC_FLAGS) & UNIT_NPC_FLAG_GOSSIP) { if (quest->IsAutoAccept() && CanAddQuest(quest, true) && CanTakeQuest(quest, true)) AddQuestAndCheckCompletion(quest, object); @@ -14635,7 +14679,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, DestroyItemCount(obj.ObjectID, obj.Amount, true); break; case QUEST_OBJECTIVE_CURRENCY: - ModifyCurrency(obj.ObjectID, -int32(obj.Amount)); + ModifyCurrency(obj.ObjectID, -int32(obj.Amount), false, true); break; } } @@ -16847,8 +16891,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) ObjectGuid transGUID = ObjectGuid::Create<HighGuid::Transport>(transLowGUID); Transport* transport = NULL; - if (GameObject* go = HashMapHolder<GameObject>::Find(transGUID)) - transport = go->ToTransport(); + if (Transport* go = HashMapHolder<Transport>::Find(transGUID)) + transport = go; if (transport) { @@ -17307,6 +17351,12 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) _LoadCUFProfiles(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES)); + std::unique_ptr<Garrison> garrison(new Garrison(this)); + if (garrison->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON), + holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS), + holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS))) + _garrison = std::move(garrison); + return true; } @@ -17758,13 +17808,13 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F remove = true; } // "Conjured items disappear if you are logged out for more than 15 minutes" - else if (timeDiff > 15 * MINUTE && proto->GetFlags() & ITEM_PROTO_FLAG_CONJURED) + else if (timeDiff > 15 * MINUTE && proto->GetFlags() & ITEM_FLAG_CONJURED) { TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s', diff: %u) has conjured item (%s, entry: %u) with expired lifetime (15 minutes). Deleting item.", GetGUID().ToString().c_str(), GetName().c_str(), timeDiff, item->GetGUID().ToString().c_str(), item->GetEntry()); remove = true; } - else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) + else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE)) { if (item->GetPlayedTime() > (2 * HOUR)) { @@ -17775,7 +17825,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F stmt->setUInt64(0, item->GetGUID().GetCounter()); trans->Append(stmt); - item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE); + item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE); } else { @@ -17793,11 +17843,11 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F { TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s') has item (%s, entry: %u) with refundable flags, but without data in item_refund_instance. Removing flag.", GetGUID().ToString().c_str(), GetName().c_str(), item->GetGUID().ToString().c_str(), item->GetEntry()); - item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE); + item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE); } } } - else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE)) + else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE)) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ITEM_BOP_TRADE); stmt->setUInt64(0, item->GetGUID().GetCounter()); @@ -17819,9 +17869,9 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F } else { - TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s') has item (%s, entry: %u) with ITEM_FLAG_BOP_TRADEABLE flag, but without data in item_soulbound_trade_data. Removing flag.", + TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s') has item (%s, entry: %u) with ITEM_FIELD_FLAG_BOP_TRADEABLE flag, but without data in item_soulbound_trade_data. Removing flag.", GetGUID().ToString().c_str(), GetName().c_str(), item->GetGUID().ToString().c_str(), item->GetEntry()); - item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE); + item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE); } } else if (proto->GetHolidayID()) @@ -18547,48 +18597,6 @@ void Player::SendRaidInfo() GetSession()->SendPacket(&data); } -/* -- called on every successful teleportation to a map -*/ -void Player::SendSavedInstances() -{ - bool hasBeenSaved = false; - WorldPacket data; - - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) - { - if (itr->second.perm) // only permanent binds are sent - { - hasBeenSaved = true; - break; - } - } - } - - //Send opcode SMSG_UPDATE_INSTANCE_OWNERSHIP. true or false means, whether you have current raid/heroic instances - data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP, 4); - data << uint32(hasBeenSaved); - GetSession()->SendPacket(&data); - - if (!hasBeenSaved) - return; - - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) - { - if (itr->second.perm) - { - data.Initialize(SMSG_UPDATE_LAST_INSTANCE, 4); - data << uint32(itr->second.save->GetMapId()); - GetSession()->SendPacket(&data); - } - } - } -} - /// convert the player's binds to the group void Player::ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader) { @@ -19106,6 +19114,8 @@ void Player::SaveToDB(bool create /*=false*/) _SaveInstanceTimeRestrictions(trans); _SaveCurrency(trans); _SaveCUFProfiles(trans); + if (_garrison) + _garrison->SaveToDB(trans); // check if stats should only be saved on logout // save stats can be out of transaction @@ -21234,9 +21244,9 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c if (!bStore) AutoUnequipOffhandIfNeed(); - if (pProto->GetFlags() & ITEM_PROTO_FLAG_REFUNDABLE && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1) + if (pProto->GetFlags() & ITEM_FLAG_REFUNDABLE && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1) { - it->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE); + it->SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE); it->SetRefundRecipient(GetGUID()); it->SetPaidMoney(price); it->SetPaidExtendedCost(crItem->ExtendedCost); @@ -21426,7 +21436,7 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin return false; } - if (!IsGameMaster() && ((pProto->GetFlags2() & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeam() == ALLIANCE) || (pProto->GetFlags2() == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeam() == HORDE))) + if (!IsGameMaster() && ((pProto->GetFlags2() & ITEM_FLAG2_HORDE_ONLY && GetTeam() == ALLIANCE) || (pProto->GetFlags2() == ITEM_FLAG2_ALLIANCE_ONLY && GetTeam() == HORDE))) return false; Creature* creature = GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); @@ -22275,7 +22285,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi m_clientGUIDs.erase(target->GetGUID()); #ifdef TRINITY_DEBUG - TC_LOG_DEBUG("maps", "Object %u (%s) is out of range for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target)); + TC_LOG_DEBUG("maps", "Object %s (%u) is out of range for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target)); #endif } } @@ -22287,7 +22297,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi UpdateVisibilityOf_helper(m_clientGUIDs, target, visibleNow); #ifdef TRINITY_DEBUG - TC_LOG_DEBUG("maps", "Object %u (%s) is visible now for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target)); + TC_LOG_DEBUG("maps", "Object %s (%u) is visible now for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target)); #endif } } @@ -22545,12 +22555,12 @@ void Player::SendInitialPacketsBeforeAddToMap() /// SMSG_WORLD_SERVER_INFO WorldPackets::Misc::WorldServerInfo worldServerInfo; - worldServerInfo.IneligibleForLootMask.Clear(); /// @todo + // worldServerInfo.IneligibleForLootMask; /// @todo worldServerInfo.WeeklyReset = sWorld->GetNextWeeklyQuestsResetTime() - WEEK; - worldServerInfo.InstanceGroupSize.Set(GetMap()->GetMapDifficulty()->MaxPlayers); - worldServerInfo.IsTournamentRealm = 0; /// @todo - worldServerInfo.RestrictedAccountMaxLevel.Clear(); /// @todo - worldServerInfo.RestrictedAccountMaxMoney.Clear(); /// @todo + worldServerInfo.InstanceGroupSize = GetMap()->GetMapDifficulty()->MaxPlayers; + worldServerInfo.IsTournamentRealm = 0; /// @todo + // worldServerInfo.RestrictedAccountMaxLevel; /// @todo + // worldServerInfo.RestrictedAccountMaxMoney; /// @todo worldServerInfo.DifficultyID = GetMap()->GetDifficultyID(); SendDirectMessage(worldServerInfo.Write()); @@ -22614,6 +22624,9 @@ void Player::SendInitialPacketsAfterAddToMap() } else if (GetMap()->IsNonRaidDungeon()) SendDungeonDifficulty(); + + if (_garrison) + _garrison->SendRemoteInfo(); } void Player::SendUpdateToOutOfRangeGroupMembers() @@ -22666,7 +22679,7 @@ void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint3 void Player::ApplyEquipCooldown(Item* pItem) { - if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_PROTO_FLAG_NO_EQUIP_COOLDOWN)) + if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_NO_EQUIP_COOLDOWN)) return; ItemTemplate const* proto = pItem->GetTemplate(); @@ -23056,7 +23069,7 @@ void Player::SetMonthlyQuestStatus(uint32 quest_id) m_MonthlyQuestChanged = true; } -void Player::ResetDailyQuestStatus() +void Player::DailyReset() { for (uint32 questId : GetDynamicValues(PLAYER_DYNAMIC_FIELD_DAILY_QUESTS)) if (uint32 questBit = GetQuestUniqueBitFlag(questId)) @@ -23069,6 +23082,9 @@ void Player::ResetDailyQuestStatus() // DB data deleted in caller m_DailyQuestChanged = false; m_lastDailyQuestTime = 0; + + if (_garrison) + _garrison->ResetFollowerActivationLimit(); } void Player::ResetWeeklyQuestStatus() @@ -23340,7 +23356,7 @@ void Player::UpdateForQuestWorldObjects() { if (itr->IsGameObject()) { - if (GameObject* obj = HashMapHolder<GameObject>::Find(*itr)) + if (GameObject* obj = ObjectAccessor::GetGameObject(*this, *itr)) obj->BuildValuesUpdateBlockForPlayer(&udata, this); } else if (itr->IsCreatureOrVehicle()) @@ -23350,7 +23366,7 @@ void Player::UpdateForQuestWorldObjects() continue; // check if this unit requires quest specific flags - if (!obj->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) + if (!obj->HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) continue; SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry()); @@ -23530,10 +23546,11 @@ bool Player::CanNoReagentCast(SpellInfo const* spellInfo) const return true; // Check no reagent use mask - flag96 noReagentMask; + flag128 noReagentMask; noReagentMask[0] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1); - noReagentMask[1] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1+1); - noReagentMask[2] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1+2); + noReagentMask[1] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1 + 1); + noReagentMask[2] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1 + 2); + noReagentMask[3] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1 + 3); if (spellInfo->SpellFamilyFlags & noReagentMask) return true; @@ -24228,7 +24245,7 @@ bool Player::CanCaptureTowerPoint() IsAlive()); // live player } -uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, BarberShopStyleEntry const* newSkin) +uint32 Player::GetBarberShopCost(BarberShopStyleEntry const* newHairStyle, uint8 newHairColor, BarberShopStyleEntry const* newFacialHair, BarberShopStyleEntry const* newSkin /*= nullptr*/, BarberShopStyleEntry const* newFace /*= nullptr*/) { uint8 level = getLevel(); @@ -24239,30 +24256,33 @@ uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 n uint8 haircolor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID); uint8 facialhair = GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE); uint8 skincolor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID); + uint8 face = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID); - if ((hairstyle == newhairstyle) && (haircolor == newhaircolor) && (facialhair == newfacialhair) && (!newSkin || (newSkin->Data == skincolor))) + if ((hairstyle == newHairStyle->Data) && (haircolor == newHairColor) && (facialhair == newFacialHair->Data) && (!newSkin || (newSkin->Data == skincolor)) && (!newFace || (newFace->Data == face))) return 0; GtBarberShopCostBaseEntry const* bsc = sGtBarberShopCostBaseStore.EvaluateTable(level - 1, 0); - if (!bsc) // shouldn't happen return 0xFFFFFFFF; - float cost = 0; + uint32 cost = 0; - if (hairstyle != newhairstyle) - cost += bsc->cost; // full price + if (hairstyle != newHairStyle->Data) + cost += uint32(bsc->cost * newHairStyle->CostModifier); - if ((haircolor != newhaircolor) && (hairstyle == newhairstyle)) - cost += bsc->cost * 0.5f; // +1/2 of price + if ((haircolor != newHairColor) && (hairstyle == newHairStyle->Data)) + cost += uint32(bsc->cost * 0.5f); // +1/2 of price - if (facialhair != newfacialhair) - cost += bsc->cost * 0.75f; // +3/4 of price + if (facialhair != newFacialHair->Data) + cost += uint32(bsc->cost * newFacialHair->CostModifier); if (newSkin && skincolor != newSkin->Data) - cost += bsc->cost * 0.75f; // +5/6 of price + cost += uint32(bsc->cost * newSkin->CostModifier); + + if (newFace && face != newFace->Data) + cost += uint32(bsc->cost * newFace->CostModifier); - return uint32(cost); + return cost; } void Player::InitGlyphsForLevel() @@ -24335,10 +24355,9 @@ void Player::SetTitle(CharTitlesEntry const* title, bool lost) SetFlag(PLAYER__FIELD_KNOWN_TITLES + fieldIndexOffset, flag); } - WorldPacket data(SMSG_TITLE_EARNED, 4 + 4); - data << uint32(title->MaskID); - data << uint32(lost ? 0 : 1); // 1 - earned, 0 - lost - GetSession()->SendPacket(&data); + WorldPackets::Character::TitleEarned packet(lost ? SMSG_TITLE_LOST : SMSG_TITLE_EARNED); + packet.Index = title->MaskID; + GetSession()->SendPacket(packet.Write()); } bool Player::isTotalImmunity() @@ -24647,7 +24666,7 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot) --loot->unlootedCount; if (sObjectMgr->GetItemTemplate(item->itemid)) - if (newitem->GetQuality() > ITEM_QUALITY_EPIC || (newitem->GetQuality() == ITEM_QUALITY_EPIC && newitem->GetItemLevel() >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) + if (newitem->GetQuality() > ITEM_QUALITY_EPIC || (newitem->GetQuality() == ITEM_QUALITY_EPIC && newitem->GetItemLevel(this) >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) if (Guild* guild = GetGuild()) guild->AddGuildNews(GUILD_NEWS_ITEM_LOOTED, GetGUID(), 0, item->itemid); @@ -24833,7 +24852,7 @@ InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limi InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8 except_slot, uint32 limit_count) const { // check unique-equipped on item - if (itemProto->GetFlags() & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED) + if (itemProto->GetFlags() & ITEM_FLAG_UNIQUE_EQUIPPED) { // there is an equip limit on this item if (HasItemOrGemWithIdEquipped(itemProto->GetId(), 1, except_slot)) @@ -25057,6 +25076,7 @@ void Player::LearnTalentSpecialization(uint32 talentSpec) LearnSpecializationSpells(); SendTalentsInfoData(); + UpdateItemSetAuras(false); } void Player::ResetTalentSpecialization() @@ -25077,6 +25097,7 @@ void Player::ResetTalentSpecialization() RemoveSpecializationSpells(); SendTalentsInfoData(); + UpdateItemSetAuras(false); } void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode) @@ -25126,7 +25147,7 @@ bool Player::IsPetNeedBeTemporaryUnsummoned() const bool Player::CanSeeSpellClickOn(Creature const* c) const { - if (!c->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) + if (!c->HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) return false; SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(c->GetEntry()); @@ -25633,6 +25654,7 @@ void Player::ActivateTalentGroup(uint8 spec) SetPower(POWER_MANA, 0); // Mana must be 0 even if it isn't the active power type. SetPower(pw, 0); + UpdateItemSetAuras(false); if (!sChrSpecializationStore.LookupEntry(GetSpecId(GetActiveTalentGroup()))) ResetTalents(true); @@ -25689,10 +25711,10 @@ void Player::DeleteRefundReference(ObjectGuid it) void Player::SendRefundInfo(Item* item) { - // This function call unsets ITEM_FLAGS_REFUNDABLE if played time is over 2 hours. + // This function call unsets ITEM_FIELD_FLAG_REFUNDABLE if played time is over 2 hours. item->UpdatePlayedTime(this); - if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) + if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE)) { TC_LOG_DEBUG("entities.player.items", "Item refund: item not refundable!"); return; @@ -25840,7 +25862,7 @@ void Player::SendItemRefundResult(Item* item, ItemExtendedCostEntry const* iece, void Player::RefundItem(Item* item) { - if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) + if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE)) { TC_LOG_DEBUG("entities.player.items", "Item refund: item not refundable!"); return; @@ -25928,7 +25950,7 @@ void Player::RefundItem(Item* item) uint32 count = iece->RequiredCurrencyCount[i]; uint32 currencyid = iece->RequiredCurrency[i]; if (count && currencyid) - ModifyCurrency(currencyid, count); + ModifyCurrency(currencyid, count, true, true); } // Grant back money @@ -25989,7 +26011,7 @@ float Player::GetAverageItemLevel() continue; if (m_items[i] && m_items[i]->GetTemplate()) - sum += m_items[i]->GetItemLevel(); + sum += m_items[i]->GetItemLevel(this); ++count; } @@ -26144,6 +26166,13 @@ void Player::OnCombatExit() m_holyPowerRegenTimerCount = 20000; // first charge of holy power decays 20 seconds after leaving combat } +void Player::CreateGarrison(uint32 garrSiteId) +{ + std::unique_ptr<Garrison> garrison(new Garrison(this)); + if (garrison->Create(garrSiteId)) + _garrison = std::move(garrison); +} + void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply) { WorldPackets::Movement::MoveSetFlag packet(apply ? SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY : SMSG_MOVE_DISABLE_TRANSITION_BETWEEN_SWIM_AND_FLY); @@ -26210,9 +26239,9 @@ std::string Player::GetMapAreaAndZoneString() std::string zoneName = "Unknown"; if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId)) { - areaName = area->ZoneName; + areaName = area->AreaName_lang; if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID)) - zoneName = zone->ZoneName; + zoneName = zone->AreaName_lang; } std::ostringstream str; @@ -26281,8 +26310,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy Map* map = GetMap(); uint32 pet_number = sObjectMgr->GeneratePetNumber(); - - if (!pet->Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, entry)) + if (!pet->Create(map->GenerateLowGuid<HighGuid::Pet>(), map, entry)) { TC_LOG_ERROR("misc", "no such creature entry %u", entry); delete pet; @@ -26295,7 +26323,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction()); pet->setPowerType(POWER_MANA); - pet->SetUInt32Value(UNIT_NPC_FLAGS, 0); + pet->SetUInt64Value(UNIT_NPC_FLAGS, 0); pet->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); pet->InitStatsForLevel(getLevel()); @@ -26668,3 +26696,26 @@ uint32 Player::GetDefaultSpecId() const return entry->DefaultSpec; return 0; } + +void Player::SendSpellCategoryCooldowns() +{ + WorldPackets::Spells::CategoryCooldown cooldowns; + + Unit::AuraEffectList const& categoryCooldownAuras = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN); + for (AuraEffect* aurEff : categoryCooldownAuras) + { + uint32 categoryId = aurEff->GetMiscValue(); + auto cItr = std::find_if(cooldowns.CategoryCooldowns.begin(), cooldowns.CategoryCooldowns.end(), + [categoryId](WorldPackets::Spells::CategoryCooldown::CategoryCooldownInfo const& cooldown) + { + return cooldown.Category == categoryId; + }); + + if (cItr == cooldowns.CategoryCooldowns.end()) + cooldowns.CategoryCooldowns.emplace_back(categoryId, -aurEff->GetAmount()); + else + cItr->ModCooldown -= aurEff->GetAmount(); + } + + SendDirectMessage(cooldowns.Write()); +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 85a44857943..eeb5a118adc 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -47,6 +47,7 @@ class ReputationMgr; class Channel; class Creature; class DynamicObject; +class Garrison; class Group; class Guild; class OutdoorPvP; @@ -919,7 +920,8 @@ enum TeleportToOptions TELE_TO_NOT_LEAVE_TRANSPORT = 0x02, TELE_TO_NOT_LEAVE_COMBAT = 0x04, TELE_TO_NOT_UNSUMMON_PET = 0x08, - TELE_TO_SPELL = 0x10 + TELE_TO_SPELL = 0x10, + TELE_TO_SEAMLESS = 0x20 }; /// Type of environmental damages @@ -984,6 +986,9 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE, PLAYER_LOGIN_QUERY_LOAD_CURRENCY, PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, + PLAYER_LOGIN_QUERY_LOAD_GARRISON, + PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS, + PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS, MAX_PLAYER_LOGIN_QUERY }; @@ -1365,7 +1370,7 @@ class Player : public Unit, public GridObject<Player> void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time); bool CanInteractWithQuestGiver(Object* questGiver); - Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask); + Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint64 npcflagmask); GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, GameobjectTypes type) const; void ToggleAFK(); @@ -1375,7 +1380,7 @@ class Player : public Unit, public GridObject<Player> uint8 GetChatFlags() const; std::string autoReplyMsg; - uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, BarberShopStyleEntry const* newSkin=NULL); + uint32 GetBarberShopCost(BarberShopStyleEntry const* newHairStyle, uint8 newHairColor, BarberShopStyleEntry const* newFacialHair, BarberShopStyleEntry const* newSkin = nullptr, BarberShopStyleEntry const* newFace = nullptr); PlayerSocial* GetSocial() { return m_social; } void RemoveSocial(); @@ -1677,7 +1682,7 @@ class Player : public Unit, public GridObject<Player> void SetWeeklyQuestStatus(uint32 quest_id); void SetMonthlyQuestStatus(uint32 quest_id); void SetSeasonalQuestStatus(uint32 quest_id); - void ResetDailyQuestStatus(); + void DailyReset(); void ResetWeeklyQuestStatus(); void ResetMonthlyQuestStatus(); void ResetSeasonalQuestStatus(uint16 event_id); @@ -1882,6 +1887,8 @@ class Player : public Unit, public GridObject<Player> void RemoveOverrideSpell(uint32 overridenSpellId, uint32 newSpellId); void LearnSpecializationSpells(); void RemoveSpecializationSpells(); + void SendSpellCategoryCooldowns(); + void SetReputation(uint32 factionentry, uint32 value); uint32 GetReputation(uint32 factionentry) const; std::string GetGuildName(); @@ -2187,6 +2194,7 @@ class Player : public Unit, public GridObject<Player> bool IsBeingTeleported() const { return mSemaphoreTeleport_Near || mSemaphoreTeleport_Far; } bool IsBeingTeleportedNear() const { return mSemaphoreTeleport_Near; } bool IsBeingTeleportedFar() const { return mSemaphoreTeleport_Far; } + bool IsBeingTeleportedSeamlessly() const { return IsBeingTeleportedFar() && m_teleport_options & TELE_TO_SEAMLESS; } void SetSemaphoreTeleportNear(bool semphsetting) { mSemaphoreTeleport_Near = semphsetting; } void SetSemaphoreTeleportFar(bool semphsetting) { mSemaphoreTeleport_Far = semphsetting; } void ProcessDelayedOperations(); @@ -2278,9 +2286,11 @@ class Player : public Unit, public GridObject<Player> void CorrectMetaGemEnchants(uint8 slot, bool apply); void InitDataForForm(bool reapplyMods = false); - void ApplyItemEquipSpell(Item* item, bool apply, bool form_change = false); - void ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool form_change = false); + void ApplyItemEquipSpell(Item* item, bool apply, bool formChange = false); + void ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool formChange = false); void UpdateEquipSpellsAtFormChange(); + void UpdateItemSetAuras(bool formChange = false); + void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx); void CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 castCount, uint32 misc); void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto); @@ -2490,7 +2500,6 @@ class Player : public Unit, public GridObject<Player> void SetPendingBind(uint32 instanceId, uint32 bindTimer); bool HasPendingBind() const { return _pendingBindId > 0; } void SendRaidInfo(); - void SendSavedInstances(); static void ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader); bool Satisfy(AccessRequirement const* ar, uint32 target_map, bool report = false); bool CheckInstanceLoginValid(); @@ -2621,6 +2630,9 @@ class Player : public Unit, public GridObject<Player> void OnCombatExit(); + void CreateGarrison(uint32 garrSiteId); + Garrison* GetGarrison() { return _garrison.get(); } + protected: // Gamemaster whisper whitelist GuidList WhisperList; @@ -2970,6 +2982,8 @@ class Player : public Unit, public GridObject<Player> uint32 _activeCheats; uint32 _maxPersonalArenaRate; + + std::unique_ptr<Garrison> _garrison; }; void AddItemsSetItem(Player* player, Item* item); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 6ad2bd52130..7034f7fbdc5 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -36,7 +36,7 @@ Transport::Transport() : GameObject(), _transportInfo(NULL), _isMoving(true), _pendingStop(false), _triggeredArrivalEvent(false), _triggeredDepartureEvent(false), - _passengerTeleportItr(_passengers.begin()), _delayedAddModel(false) + _passengerTeleportItr(_passengers.begin()), _delayedAddModel(false), _delayedTeleport(false) { m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION; } @@ -104,6 +104,7 @@ bool Transport::Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, void Transport::CleanupsBeforeDelete(bool finalCleanup /*= true*/) { + HashMapHolder<Transport>::Remove(this); UnloadStaticPassengers(); while (!_passengers.empty()) { @@ -129,7 +130,7 @@ void Transport::Update(uint32 diff) if (IsMoving() || !_pendingStop) m_goValue.Transport.PathProgress += diff; - uint32 timer = m_goValue.Transport.PathProgress % GetPeriod(); + uint32 timer = m_goValue.Transport.PathProgress % GetTransportPeriod(); // Set current waypoint // Desired outcome: _currentFrame->DepartureTime < timer < _nextFrame->ArriveTime @@ -151,8 +152,8 @@ void Transport::Update(uint32 diff) if (_pendingStop && GetGoState() != GO_STATE_READY) { SetGoState(GO_STATE_READY); - m_goValue.Transport.PathProgress = (m_goValue.Transport.PathProgress / GetPeriod()); - m_goValue.Transport.PathProgress *= GetPeriod(); + m_goValue.Transport.PathProgress = (m_goValue.Transport.PathProgress / GetTransportPeriod()); + m_goValue.Transport.PathProgress *= GetTransportPeriod(); m_goValue.Transport.PathProgress += _currentFrame->ArriveTime; } break; // its a stop frame and we are waiting @@ -230,6 +231,14 @@ void Transport::Update(uint32 diff) sScriptMgr->OnTransportUpdate(this, diff); } +void Transport::DelayedUpdate(uint32 diff) +{ + if (GetKeyFrames().size() <= 1) + return; + + DelayedTeleportTransport(); +} + void Transport::AddPassenger(WorldObject* passenger) { if (!IsInWorld()) @@ -456,7 +465,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu pos.GetPosition(x, y, z, o); CalculatePassengerPosition(x, y, z, &o); - if (!summon->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), map, 0, entry, x, y, z, o, nullptr, vehId)) + if (!summon->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, 0, entry, x, y, z, o, nullptr, vehId)) { delete summon; return NULL; @@ -606,36 +615,8 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl if (oldMap->GetId() != newMapid) { - Map* newMap = sMapMgr->CreateBaseMap(newMapid); + _delayedTeleport = true; UnloadStaticPassengers(); - GetMap()->RemoveFromMap<Transport>(this, false); - SetMap(newMap); - - for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();) - { - WorldObject* obj = (*_passengerTeleportItr++); - - float destX, destY, destZ, destO; - obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO); - TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o); - - switch (obj->GetTypeId()) - { - case TYPEID_PLAYER: - if (!obj->ToPlayer()->TeleportTo(newMapid, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT)) - RemovePassenger(obj); - break; - case TYPEID_DYNAMICOBJECT: - obj->AddObjectToRemoveList(); - break; - default: - RemovePassenger(obj); - break; - } - } - - Relocate(x, y, z, o); - GetMap()->AddToMap<Transport>(this); return true; } else @@ -658,6 +639,48 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl } } +void Transport::DelayedTeleportTransport() +{ + if (!_delayedTeleport) + return; + + _delayedTeleport = false; + Map* newMap = sMapMgr->CreateBaseMap(_nextFrame->Node->MapID); + GetMap()->RemoveFromMap<Transport>(this, false); + SetMap(newMap); + + float x = _nextFrame->Node->Loc.X, + y = _nextFrame->Node->Loc.Y, + z = _nextFrame->Node->Loc.Z, + o =_nextFrame->InitialOrientation; + + for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();) + { + WorldObject* obj = (*_passengerTeleportItr++); + + float destX, destY, destZ, destO; + obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO); + TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o); + + switch (obj->GetTypeId()) + { + case TYPEID_PLAYER: + if (!obj->ToPlayer()->TeleportTo(_nextFrame->Node->MapID, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT)) + RemovePassenger(obj); + break; + case TYPEID_DYNAMICOBJECT: + obj->AddObjectToRemoveList(); + break; + default: + RemovePassenger(obj); + break; + } + } + + Relocate(x, y, z, o); + GetMap()->AddToMap<Transport>(this); +} + void Transport::UpdatePassengerPositions(PassengerSet& passengers) { for (PassengerSet::iterator itr = passengers.begin(); itr != passengers.end(); ++itr) diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index a24c8179ead..d6598a0036c 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -39,6 +39,7 @@ class Transport : public GameObject, public TransportBase void CleanupsBeforeDelete(bool finalCleanup = true) override; void Update(uint32 diff) override; + void DelayedUpdate(uint32 diff); void BuildUpdate(UpdateDataMapType& data_map) override; @@ -79,7 +80,7 @@ class Transport : public GameObject, public TransportBase TransportBase::CalculatePassengerOffset(x, y, z, o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); } - uint32 GetPeriod() const { return GetUInt32Value(GAMEOBJECT_LEVEL); } + uint32 GetTransportPeriod() const override { return GetUInt32Value(GAMEOBJECT_LEVEL); } void SetPeriod(uint32 period) { SetUInt32Value(GAMEOBJECT_LEVEL, period); } uint32 GetTimer() const { return GetGOValue()->Transport.PathProgress; } @@ -103,6 +104,7 @@ class Transport : public GameObject, public TransportBase void MoveToNextWaypoint(); float CalculateSegmentPos(float perc); bool TeleportTransport(uint32 newMapid, float x, float y, float z, float o); + void DelayedTeleportTransport(); void UpdatePassengerPositions(PassengerSet& passengers); void DoEventIfAny(KeyFrame const& node, bool departure); @@ -127,6 +129,7 @@ class Transport : public GameObject, public TransportBase PassengerSet _staticPassengers; bool _delayedAddModel; + bool _delayedTeleport; }; #endif diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0394911d9fe..7ae20779fa7 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3787,7 +3787,7 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except) UpdateInterruptMask(); } -void Unit::RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID) +void Unit::RemoveAurasWithFamily(SpellFamilyNames family, flag128 const& familyFlag, ObjectGuid casterGUID) { for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) { @@ -3795,7 +3795,7 @@ void Unit::RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, ui if (!casterGUID || aura->GetCasterGUID() == casterGUID) { SpellInfo const* spell = aura->GetSpellInfo(); - if (spell->SpellFamilyName == uint32(family) && spell->SpellFamilyFlags & flag96(familyFlag1, familyFlag2, familyFlag3)) + if (spell->SpellFamilyName == uint32(family) && spell->SpellFamilyFlags & familyFlag) { RemoveAura(iter); continue; @@ -4051,13 +4051,13 @@ AuraEffect* Unit::GetAuraEffect(AuraType type, SpellFamilyNames name, uint32 ico return NULL; } -AuraEffect* Unit::GetAuraEffect(AuraType type, SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID) const +AuraEffect* Unit::GetAuraEffect(AuraType type, SpellFamilyNames family, flag128 const& familyFlag, ObjectGuid casterGUID) const { AuraEffectList const& auras = GetAuraEffectsByType(type); for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) { SpellInfo const* spell = (*i)->GetSpellInfo(); - if (spell->SpellFamilyName == uint32(family) && spell->SpellFamilyFlags & flag96(familyFlag1, familyFlag2, familyFlag3)) + if (spell->SpellFamilyName == uint32(family) && spell->SpellFamilyFlags & familyFlag) { if (!casterGUID.IsEmpty() && (*i)->GetCasterGUID() != casterGUID) continue; @@ -4914,13 +4914,12 @@ void Unit::SendAttackStateUpdate(CalcDamageInfo* damageInfo) int32 overkill = damageInfo->damage - damageInfo->target->GetHealth(); packet.OverDamage = (overkill < 0 ? -1 : overkill); - WorldPackets::Combat::SubDamage& subDmg = packet.SubDmg.Value; - subDmg.SchoolMask = damageInfo->damageSchoolMask; // School of sub damage - subDmg.FDamage = damageInfo->damage; // sub damage - subDmg.Damage = damageInfo->damage; // Sub Damage - subDmg.Absorbed = damageInfo->absorb; - subDmg.Resisted = damageInfo->resist; - packet.SubDmg.HasValue = true; + packet.SubDmg = WorldPackets::Combat::SubDamage(); + packet.SubDmg->SchoolMask = damageInfo->damageSchoolMask; // School of sub damage + packet.SubDmg->FDamage = damageInfo->damage; // sub damage + packet.SubDmg->Damage = damageInfo->damage; // Sub Damage + packet.SubDmg->Absorbed = damageInfo->absorb; + packet.SubDmg->Resisted = damageInfo->resist; packet.VictimState = damageInfo->TargetState; packet.BlockAmount = damageInfo->blocked_amount; @@ -5521,7 +5520,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return false; // try to find spell Rip on the target - if (AuraEffect const* AurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00800000, 0x0, 0x0, GetGUID())) + if (AuraEffect const* AurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, flag128(0x00800000, 0x0, 0x0), GetGUID())) { // Rip's max duration, note: spells which modifies Rip's duration also counted uint32 CountMin = AurEff->GetBase()->GetMaxDuration(); @@ -6046,7 +6045,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (!target) return false; // try to find spell Flame Shock on the target - if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0x0, 0x0, GetGUID())) + if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, flag128(0x10000000, 0x0, 0x0), GetGUID())) { Aura* flameShock = aurEff->GetBase(); int32 maxDuration = flameShock->GetMaxDuration(); @@ -6082,7 +6081,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (dummySpell->SpellIconID == 3059) { // Lightning Shield - if (GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0)) + if (GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, flag128(0x400, 0, 0))) { uint32 spell = 26364; @@ -8108,19 +8107,41 @@ void Unit::UnsummonAllTotems() } } -void Unit::SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical) +void Unit::SendHealSpellLog(Unit* victim, uint32 spellID, uint32 health, uint32 overHeal, uint32 absorbed, bool crit) { - // we guess size - WorldPacket data(SMSG_SPELL_HEAL_LOG, 8 + 8 + 4 + 4 + 4 + 4 + 1 + 1); - data << victim->GetPackGUID(); - data << GetPackGUID(); - data << uint32(SpellID); - data << uint32(Damage); - data << uint32(OverHeal); - data << uint32(Absorb); // Absorb amount - data << uint8(critical ? 1 : 0); - data << uint8(0); // unused - SendMessageToSet(&data, true); + WorldPackets::CombatLog::SpellHealLog spellHealLog; + + TC_LOG_DEBUG("spells", "HealSpellLog -- SpellId: %u Caster: %s Target: %s (Health: %u OverHeal: %u Absorbed: %u Crit: %d)", spellID, GetGUID().ToString().c_str(), victim->GetGUID().ToString().c_str(), + health, overHeal, absorbed, crit); + + spellHealLog.TargetGUID = victim->GetGUID(); + spellHealLog.CasterGUID = GetGUID(); + + spellHealLog.SpellID = spellID; + spellHealLog.Health = health; + spellHealLog.OverHeal = overHeal; + spellHealLog.Absorbed = absorbed; + + spellHealLog.Crit = crit; + + /// @todo: 6.x Has to be implemented + /* + packet.ReadBit("Multistrike"); + + var hasCritRollMade = packet.ReadBit("HasCritRollMade"); + var hasCritRollNeeded = packet.ReadBit("HasCritRollNeeded"); + var hasLogData = packet.ReadBit("HasLogData"); + + if (hasCritRollMade) + packet.ReadSingle("CritRollMade"); + + if (hasCritRollNeeded) + packet.ReadSingle("CritRollNeeded"); + + if (hasLogData) + SpellParsers.ReadSpellCastLogData(packet); + */ + SendMessageToSet(spellHealLog.Write(), true); } int32 Unit::HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHealth, bool critical) @@ -8358,7 +8379,7 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage } case 5481: // Starfire Bonus { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002, 0, 0)) + if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, flag128(0x200002, 0, 0))) AddPct(DoneTotalMod, (*i)->GetAmount()); break; } @@ -8397,7 +8418,7 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage { // Glyph of Smite if (AuraEffect* aurEff = GetAuraEffect(55692, 0)) - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x100000, 0, 0, GetGUID())) + if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, flag128(0x100000, 0, 0), GetGUID())) AddPct(DoneTotalMod, aurEff->GetAmount()); } break; @@ -8687,7 +8708,7 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto { // Improved Insect Swarm if (AuraEffect const* aurEff = GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0)) - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00000002, 0, 0)) + if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, flag128(0x00000002, 0, 0))) crit_chance += aurEff->GetAmount(); break; } @@ -8718,7 +8739,7 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto // Lava Burst if (spellProto->SpellFamilyFlags[1] & 0x00001000) { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0, 0, GetGUID())) + if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, flag128(0x10000000, 0, 0), GetGUID())) if (victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE) > -100) return 100.0f; break; @@ -8972,7 +8993,7 @@ float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const break; case 7798: // Glyph of Regrowth { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0)) + if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, flag128(0x40, 0, 0))) AddPct(DoneTotalMod, (*i)->GetAmount()); break; } @@ -8997,7 +9018,7 @@ float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const } case 7871: // Glyph of Lesser Healing Wave { - if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0, GetGUID())) + if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, flag128(0, 0x00000400, 0), GetGUID())) AddPct(DoneTotalMod, (*i)->GetAmount()); break; } @@ -9036,7 +9057,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[1] & 0x2000000) { // Rejuvenation, Regrowth, Lifebloom, or Wild Growth - if (GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x50, 0x4000010, 0)) + if (GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, flag128(0x50, 0x4000010, 0))) // increase healing by 20% TakenTotalMod *= 1.2f; } @@ -9654,9 +9675,9 @@ void Unit::Dismount() if (Player* thisPlayer = ToPlayer()) thisPlayer->SendMovementSetCollisionHeight(thisPlayer->GetCollisionHeight(false)); - WorldPacket data(SMSG_DISMOUNT, 8); - data << GetPackGUID(); - SendMessageToSet(&data, true); + WorldPackets::Misc::Dismount data; + data.Guid = GetGUID(); + SendMessageToSet(data.Write(), true); // dismount as a vehicle if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit()) @@ -9742,7 +9763,7 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const bool Unit::IsServiceProvider() const { - return HasFlag(UNIT_NPC_FLAGS, + return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_FLIGHTMASTER | UNIT_NPC_FLAG_PETITIONER | UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER | UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_SPIRITHEALER | @@ -9880,7 +9901,7 @@ void Unit::ClearInCombat() if (HasFlag(OBJECT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TAPPED)) SetUInt32Value(OBJECT_DYNAMIC_FLAGS, creature->GetCreatureTemplate()->dynamicflags); - if (creature->IsPet()) + if (creature->IsPet() || creature->IsGuardian()) { if (Unit* owner = GetOwner()) for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) @@ -14255,7 +14276,7 @@ void Unit::RemoveVehicleKit(bool onRemoveFromWorld /*= false*/) m_updateFlag &= ~UPDATEFLAG_VEHICLE; m_unitTypeMask &= ~UNIT_MASK_VEHICLE; - RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK | UNIT_NPC_FLAG_PLAYER_VEHICLE); + RemoveFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK | UNIT_NPC_FLAG_PLAYER_VEHICLE); } bool Unit::IsOnVehicle(const Unit* vehicle) const @@ -15400,7 +15421,7 @@ void Unit::SendTeleportPacket(Position& pos) ObjectGuid transGuid = GetTransGUID(); if (!transGuid.IsEmpty()) - selfPacket.TransportGUID.Set(transGuid); + selfPacket.TransportGUID = transGuid; selfPacket.Pos.Relocate(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); selfPacket.Facing = GetOrientation(); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e6f6ff13f37..252f044b4ef 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -729,40 +729,45 @@ enum UnitFlags2 }; /// Non Player Character flags -enum NPCFlags : uint32 -{ - UNIT_NPC_FLAG_NONE = 0x00000000, - UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100% - UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // 100% - UNIT_NPC_FLAG_UNK1 = 0x00000004, - UNIT_NPC_FLAG_UNK2 = 0x00000008, - UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100% - UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // 100% - UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // 100% - UNIT_NPC_FLAG_VENDOR = 0x00000080, // 100% - UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // 100%, general goods vendor - UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // 100% - UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // guessed - UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // 100% - UNIT_NPC_FLAG_REPAIR = 0x00001000, // 100% - UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // 100% - UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // guessed - UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // guessed - UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // 100% - UNIT_NPC_FLAG_BANKER = 0x00020000, // 100% - UNIT_NPC_FLAG_PETITIONER = 0x00040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions - UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // 100% - UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // 100% - UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100% - UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100% - UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode - UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click) - UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set - UNIT_NPC_FLAG_MAILBOX = 0x04000000, // mailbox - UNIT_NPC_FLAG_REFORGER = 0x08000000, // reforging - UNIT_NPC_FLAG_TRANSMOGRIFIER = 0x10000000, // transmogrification - UNIT_NPC_FLAG_VAULTKEEPER = 0x20000000, // void storage - UNIT_NPC_FLAG_BLACK_MARKET = 0x80000000 // black market +enum NPCFlags : uint64 +{ + UNIT_NPC_FLAG_NONE = 0x0000000000, + UNIT_NPC_FLAG_GOSSIP = 0x0000000001, // 100% + UNIT_NPC_FLAG_QUESTGIVER = 0x0000000002, // 100% + UNIT_NPC_FLAG_UNK1 = 0x0000000004, + UNIT_NPC_FLAG_UNK2 = 0x0000000008, + UNIT_NPC_FLAG_TRAINER = 0x0000000010, // 100% + UNIT_NPC_FLAG_TRAINER_CLASS = 0x0000000020, // 100% + UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x0000000040, // 100% + UNIT_NPC_FLAG_VENDOR = 0x0000000080, // 100% + UNIT_NPC_FLAG_VENDOR_AMMO = 0x0000000100, // 100%, general goods vendor + UNIT_NPC_FLAG_VENDOR_FOOD = 0x0000000200, // 100% + UNIT_NPC_FLAG_VENDOR_POISON = 0x0000000400, // guessed + UNIT_NPC_FLAG_VENDOR_REAGENT = 0x0000000800, // 100% + UNIT_NPC_FLAG_REPAIR = 0x0000001000, // 100% + UNIT_NPC_FLAG_FLIGHTMASTER = 0x0000002000, // 100% + UNIT_NPC_FLAG_SPIRITHEALER = 0x0000004000, // guessed + UNIT_NPC_FLAG_SPIRITGUIDE = 0x0000008000, // guessed + UNIT_NPC_FLAG_INNKEEPER = 0x0000010000, // 100% + UNIT_NPC_FLAG_BANKER = 0x0000020000, // 100% + UNIT_NPC_FLAG_PETITIONER = 0x0000040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions + UNIT_NPC_FLAG_TABARDDESIGNER = 0x0000080000, // 100% + UNIT_NPC_FLAG_BATTLEMASTER = 0x0000100000, // 100% + UNIT_NPC_FLAG_AUCTIONEER = 0x0000200000, // 100% + UNIT_NPC_FLAG_STABLEMASTER = 0x0000400000, // 100% + UNIT_NPC_FLAG_GUILD_BANKER = 0x0000800000, // cause client to send 997 opcode + UNIT_NPC_FLAG_SPELLCLICK = 0x0001000000, // cause client to send 1015 opcode (spell click) + UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x0002000000, // players with mounts that have vehicle data should have it set + UNIT_NPC_FLAG_MAILBOX = 0x0004000000, // mailbox + UNIT_NPC_FLAG_REFORGER = 0x0008000000, // reforging + UNIT_NPC_FLAG_TRANSMOGRIFIER = 0x0010000000, // transmogrification + UNIT_NPC_FLAG_VAULTKEEPER = 0x0020000000, // void storage + UNIT_NPC_FLAG_BLACK_MARKET = 0x0080000000, // black market + UNIT_NPC_FLAG_ITEM_UPGRADE_MASTER = 0x0100000000, + UNIT_NPC_FLAG_GARRISON_ARCHITECT = 0x0200000000, + UNIT_NPC_FLAG_SHIPMENT_CRAFTER = 0x2000000000, + UNIT_NPC_FLAG_GARRISON_MISSION_NPC = 0x4000000000, + UNIT_NPC_FLAG_TRADESKILL_NPC = 0x8000000000 }; enum MovementFlags @@ -1547,22 +1552,22 @@ class Unit : public WorldObject MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType) const; MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const; - bool IsVendor() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR); } - bool IsTrainer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER); } - bool IsQuestGiver() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); } - bool IsGossip() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); } - bool IsTaxi() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER); } - bool IsGuildMaster() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER); } - bool IsBattleMaster() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER); } - bool IsBanker() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER); } - bool IsInnkeeper() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER); } - bool IsSpiritHealer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER); } - bool IsSpiritGuide() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE); } - bool IsTabardDesigner()const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER); } - bool IsAuctioner() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER); } - bool IsArmorer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR); } + bool IsVendor() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR); } + bool IsTrainer() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER); } + bool IsQuestGiver() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); } + bool IsGossip() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); } + bool IsTaxi() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER); } + bool IsGuildMaster() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER); } + bool IsBattleMaster() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER); } + bool IsBanker() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER); } + bool IsInnkeeper() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER); } + bool IsSpiritHealer() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER); } + bool IsSpiritGuide() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE); } + bool IsTabardDesigner()const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER); } + bool IsAuctioner() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER); } + bool IsArmorer() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR); } bool IsServiceProvider() const; - bool IsSpiritService() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE); } + bool IsSpiritService() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE); } bool IsCritter() const { return GetCreatureType() == CREATURE_TYPE_CRITTER; } bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); } @@ -1600,7 +1605,7 @@ class Unit : public WorldObject virtual void UpdateUnderwaterState(Map* m, float x, float y, float z); bool isInAccessiblePlaceFor(Creature const* c) const; - void SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical = false); + void SendHealSpellLog(Unit* victim, uint32 spellID, uint32 health, uint32 overHeal, uint32 absorbed, bool crit = false); int32 HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHealth, bool critical = false); void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, Powers powertype); void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype); @@ -1798,7 +1803,7 @@ class Unit : public WorldObject void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0, bool phaseid = false); void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = 0); void RemoveAurasWithAttribute(uint32 flags); - void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID); + void RemoveAurasWithFamily(SpellFamilyNames family, flag128 const& familyFlag, ObjectGuid casterGUID); void RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode = AURA_REMOVE_BY_DEFAULT, uint32 except = 0); void RemoveMovementImpairingAuras(); @@ -1821,7 +1826,7 @@ class Unit : public WorldObject AuraEffect* GetAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID = ObjectGuid::Empty) const; AuraEffect* GetAuraEffectOfRankedSpell(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID = ObjectGuid::Empty) const; AuraEffect* GetAuraEffect(AuraType type, SpellFamilyNames name, uint32 iconId, uint8 effIndex) const; // spell mustn't have familyflags - AuraEffect* GetAuraEffect(AuraType type, SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID = ObjectGuid::Empty) const; + AuraEffect* GetAuraEffect(AuraType type, SpellFamilyNames family, flag128 const& familyFlag, ObjectGuid casterGUID = ObjectGuid::Empty) const; AuraEffect* GetDummyAuraEffect(SpellFamilyNames name, uint32 iconId, uint8 effIndex) const; AuraApplication * GetAuraApplication(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, AuraApplication * except = NULL) const; diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 89356307b2f..08efa9b9cae 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -50,9 +50,9 @@ UsableSeatNum(0), _me(unit), _vehicleInfo(vehInfo), _creatureEntry(creatureEntry // Set or remove correct flags based on available seats. Will overwrite db data (if wrong). if (UsableSeatNum) - _me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); + _me->SetFlag64(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); else - _me->RemoveFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); + _me->RemoveFlag64(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); InitMovementInfoForBase(); } @@ -147,7 +147,7 @@ void Vehicle::Reset(bool evading /*= false*/) if (GetBase()->GetTypeId() != TYPEID_UNIT) return; - TC_LOG_DEBUG("entities.vehicle", "Vehicle::Reset (Entry: %u, %s, DBGuid: " UI64FMTD ")", GetCreatureEntry(), _me->GetGUID().ToString().c_str(), _me->ToCreature()->GetDBTableGUIDLow()); + TC_LOG_DEBUG("entities.vehicle", "Vehicle::Reset (Entry: %u, %s, DBGuid: " UI64FMTD ")", GetCreatureEntry(), _me->GetGUID().ToString().c_str(), _me->ToCreature()->GetSpawnId()); ApplyAllImmunities(); InstallAllAccessories(evading); @@ -407,7 +407,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) TC_LOG_DEBUG("entities.vehicle", "Unit %s scheduling enter vehicle (entry: %u, vehicleId: %u, %s (dbguid: " UI64FMTD ") on seat %d", unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->ID, _me->GetGUID().ToString().c_str(), - uint64(_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : UI64LIT(0)), (int32)seatId); + uint64(_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetSpawnId() : UI64LIT(0)), (int32)seatId); // The seat selection code may kick other passengers off the vehicle. // While the validity of the following may be arguable, it is possible that when such a passenger @@ -479,7 +479,7 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit) unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->ID, _me->GetGUID().ToString().c_str(), (int32)seat->first); if (seat->second.SeatInfo->CanEnterOrExit() && ++UsableSeatNum) - _me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); + _me->SetFlag64(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK)); // Remove UNIT_FLAG_NOT_SELECTABLE if passenger did not have it before entering vehicle if (seat->second.SeatInfo->Flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE && !seat->second.Passenger.IsUnselectable) @@ -768,9 +768,9 @@ bool VehicleJoinEvent::Execute(uint64, uint32) if (!Target->UsableSeatNum) { if (Target->GetBase()->GetTypeId() == TYPEID_PLAYER) - Target->GetBase()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); + Target->GetBase()->RemoveFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE); else - Target->GetBase()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + Target->GetBase()->RemoveFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); } } diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index efb38cf2777..0d6b971ec15 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -715,7 +715,7 @@ void GameEventMgr::LoadFromDB() ObjectGuid::LowType guid = fields[0].GetUInt64(); uint16 event_id = fields[1].GetUInt8(); - uint32 npcflag = fields[2].GetUInt32(); + uint64 npcflag = fields[2].GetUInt64(); if (event_id >= mGameEvent.size()) { @@ -916,10 +916,10 @@ void GameEventMgr::LoadFromDB() } } -uint32 GameEventMgr::GetNPCFlag(Creature* cr) +uint64 GameEventMgr::GetNPCFlag(Creature* cr) { - uint32 mask = 0; - ObjectGuid::LowType guid = cr->GetDBTableGUIDLow(); + uint64 mask = 0; + ObjectGuid::LowType guid = cr->GetSpawnId(); for (ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr) { @@ -1117,25 +1117,34 @@ void GameEventMgr::ApplyNewEvent(uint16 event_id) void GameEventMgr::UpdateEventNPCFlags(uint16 event_id) { + std::unordered_map<uint32, std::unordered_set<ObjectGuid::LowType>> creaturesByMap; + // go through the creatures whose npcflags are changed in the event for (NPCFlagList::iterator itr = mGameEventNPCFlags[event_id].begin(); itr != mGameEventNPCFlags[event_id].end(); ++itr) - { // get the creature data from the low guid to get the entry, to be able to find out the whole guid if (CreatureData const* data = sObjectMgr->GetCreatureData(itr->first)) + creaturesByMap[data->mapid].insert(itr->first); + + for (auto const& p : creaturesByMap) + { + sMapMgr->DoForAllMapsWithMapId(p.first, [this, &p](Map* map) { - Creature* cr = HashMapHolder<Creature>::Find(ObjectGuid::Create<HighGuid::Creature>(data->mapid, data->id, itr->first)); - // if we found the creature, modify its npcflag - if (cr) + for (auto& spawnId : p.second) { - uint32 npcflag = GetNPCFlag(cr); - if (const CreatureTemplate* ci = cr->GetCreatureTemplate()) - npcflag |= ci->npcflag; - cr->SetUInt32Value(UNIT_NPC_FLAGS, npcflag); - // reset gossip options, since the flag change might have added / removed some - //cr->ResetGossipOptions(); + auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(spawnId); + for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr) + { + Creature* creature = itr->second; + uint32 npcflag = GetNPCFlag(creature); + if (CreatureTemplate const* creatureTemplate = creature->GetCreatureTemplate()) + npcflag |= creatureTemplate->npcflag; + + creature->SetUInt64Value(UNIT_NPC_FLAGS, npcflag); + // reset gossip options, since the flag change might have added / removed some + //cr->ResetGossipOptions(); + } } - // if we didn't find it, then the npcflag will be updated when the creature is loaded - } + }); } } @@ -1254,8 +1263,16 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) { sObjectMgr->RemoveCreatureFromGrid(*itr, data); - if (Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid::Create<HighGuid::Creature>(data->mapid, data->id, *itr), (Creature*)NULL)) - creature->AddObjectToRemoveList(); + sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map) + { + auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(*itr); + for (auto itr2 = creatureBounds.first; itr2 != creatureBounds.second;) + { + Creature* creature = itr2->second; + ++itr2; + creature->AddObjectToRemoveList(); + } + }); } } @@ -1276,10 +1293,19 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) { sObjectMgr->RemoveGameobjectFromGrid(*itr, data); - if (GameObject* pGameobject = ObjectAccessor::GetObjectInWorld(ObjectGuid::Create<HighGuid::GameObject>(data->mapid, data->id, *itr), (GameObject*)NULL)) - pGameobject->AddObjectToRemoveList(); + sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map) + { + auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(*itr); + for (auto itr2 = gameobjectBounds.first; itr2 != gameobjectBounds.second;) + { + GameObject* go = itr2->second; + ++itr2; + go->AddObjectToRemoveList(); + } + }); } } + if (internal_event_id < 0 || internal_event_id >= int32(mGameEventPoolIds.size())) { TC_LOG_ERROR("gameevent", "GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %u (size: %zu)", internal_event_id, mGameEventPoolIds.size()); @@ -1302,53 +1328,43 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) continue; // Update if spawned - Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid::Create<HighGuid::Creature>(data->mapid, data->id, itr->first), (Creature*)NULL); - if (creature) + sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr, activate](Map* map) { - if (activate) + auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(itr->first); + for (auto itr2 = creatureBounds.first; itr2 != creatureBounds.second; ++itr2) { - itr->second.equipement_id_prev = creature->GetCurrentEquipmentId(); - itr->second.modelid_prev = creature->GetDisplayId(); - creature->LoadEquipment(itr->second.equipment_id, true); - if (itr->second.modelid > 0 && itr->second.modelid_prev != itr->second.modelid && - sObjectMgr->GetCreatureModelInfo(itr->second.modelid)) + Creature* creature = itr2->second; + if (activate) { - creature->SetDisplayId(itr->second.modelid); - creature->SetNativeDisplayId(itr->second.modelid); + itr->second.equipement_id_prev = creature->GetCurrentEquipmentId(); + itr->second.modelid_prev = creature->GetDisplayId(); + creature->LoadEquipment(itr->second.equipment_id, true); + if (itr->second.modelid > 0 && itr->second.modelid_prev != itr->second.modelid && + sObjectMgr->GetCreatureModelInfo(itr->second.modelid)) + { + creature->SetDisplayId(itr->second.modelid); + creature->SetNativeDisplayId(itr->second.modelid); + } } - } - else - { - creature->LoadEquipment(itr->second.equipement_id_prev, true); - if (itr->second.modelid_prev > 0 && itr->second.modelid_prev != itr->second.modelid && - sObjectMgr->GetCreatureModelInfo(itr->second.modelid_prev)) + else { - creature->SetDisplayId(itr->second.modelid_prev); - creature->SetNativeDisplayId(itr->second.modelid_prev); + creature->LoadEquipment(itr->second.equipement_id_prev, true); + if (itr->second.modelid_prev > 0 && itr->second.modelid_prev != itr->second.modelid && + sObjectMgr->GetCreatureModelInfo(itr->second.modelid_prev)) + { + creature->SetDisplayId(itr->second.modelid_prev); + creature->SetNativeDisplayId(itr->second.modelid_prev); + } } } - } - else // If not spawned - { - CreatureData const* data2 = sObjectMgr->GetCreatureData(itr->first); - if (data2 && activate) - { - CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(data2->id); - uint32 displayID = ObjectMgr::ChooseDisplayId(cinfo, data2); - sObjectMgr->GetCreatureModelRandomGender(&displayID); - - if (data2->equipmentId == 0) - itr->second.equipement_id_prev = 0; ///@todo: verify this line - else if (data2->equipmentId != -1) - itr->second.equipement_id_prev = data->equipmentId; - itr->second.modelid_prev = displayID; - } - } + }); + // now last step: put in data - // just to have write access to it CreatureData& data2 = sObjectMgr->NewOrExistCreatureData(itr->first); if (activate) { + itr->second.modelid_prev = data2.displayid; + itr->second.equipement_id_prev = data2.equipmentId; data2.displayid = itr->second.modelid; data2.equipmentId = itr->second.equipment_id; } @@ -1598,24 +1614,43 @@ void GameEventMgr::SendWorldStateUpdate(Player* player, uint16 event_id) } } -void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate) +class GameEventAIHookWorker { - //! Iterate over every supported source type (creature and gameobject) - //! Not entirely sure how this will affect units in non-loaded grids. +public: + GameEventAIHookWorker(uint16 eventId, bool activate) : _eventId(eventId), _activate(activate) { } + + void Visit(std::unordered_map<ObjectGuid, Creature*>& creatureMap) { - boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Creature>::GetLock()); - HashMapHolder<Creature>::MapType const& m = ObjectAccessor::GetCreatures(); - for (HashMapHolder<Creature>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter) - if (iter->second->IsInWorld()) - iter->second->AI()->sOnGameEvent(activate, event_id); + for (auto const& p : creatureMap) + if (p.second->IsInWorld() && p.second->IsAIEnabled) + p.second->AI()->sOnGameEvent(_activate, _eventId); } + + void Visit(std::unordered_map<ObjectGuid, GameObject*>& gameObjectMap) { - boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<GameObject>::GetLock()); - HashMapHolder<GameObject>::MapType const& m = ObjectAccessor::GetGameObjects(); - for (HashMapHolder<GameObject>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter) - if (iter->second->IsInWorld()) - iter->second->AI()->OnGameEvent(activate, event_id); + for (auto const& p : gameObjectMap) + if (p.second->IsInWorld()) + p.second->AI()->OnGameEvent(_activate, _eventId); } + + template<class T> + void Visit(std::unordered_map<ObjectGuid, T*>&) { } + +private: + uint16 _eventId; + bool _activate; +}; + +void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate) +{ + //! Iterate over every supported source type (creature and gameobject) + //! Not entirely sure how this will affect units in non-loaded grids. + sMapMgr->DoForAllMaps([event_id, activate](Map* map) + { + GameEventAIHookWorker worker(event_id, activate); + TypeContainerVisitor<GameEventAIHookWorker, MapStoredObjectTypesContainer> visitor(worker); + visitor.Visit(map->GetObjectsStore()); + }); } uint16 GameEventMgr::GetEventIdForQuest(Quest const* quest) const diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index bbddd5698d8..5edd6f3da2d 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -124,7 +124,7 @@ class GameEventMgr void StopEvent(uint16 event_id, bool overwrite = false); void HandleQuestComplete(uint32 quest_id); // called on world event type quest completions void HandleWorldEventGossip(Player* player, Creature* c); - uint32 GetNPCFlag(Creature* cr); + uint64 GetNPCFlag(Creature* cr); uint32 GetNpcTextId(uint32 guid); uint16 GetEventIdForQuest(Quest const* quest) const; private: @@ -162,7 +162,7 @@ class GameEventMgr typedef std::list<NPCVendorEntry> NPCVendorList; typedef std::vector<NPCVendorList> GameEventNPCVendorMap; typedef std::map<uint32 /*quest id*/, GameEventQuestToEventConditionNum> QuestIdToEventConditionMap; - typedef std::pair<ObjectGuid::LowType /*guid*/, uint32 /*npcflag*/> GuidNPCFlagPair; + typedef std::pair<ObjectGuid::LowType /*guid*/, uint64 /*npcflag*/> GuidNPCFlagPair; typedef std::list<GuidNPCFlagPair> NPCFlagList; typedef std::vector<NPCFlagList> GameEventNPCFlagMap; typedef std::vector<uint32> GameEventBitmask; diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp new file mode 100644 index 00000000000..35c07e1590c --- /dev/null +++ b/src/server/game/Garrison/Garrison.cpp @@ -0,0 +1,554 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Garrison.h" +#include "GameObject.h" +#include "GarrisonMgr.h" +#include "MapManager.h" +#include "ObjectMgr.h" + +Garrison::Garrison(Player* owner) : _owner(owner), _siteLevel(nullptr), _followerActivationsRemainingToday(1) +{ +} + +bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings) +{ + if (!garrison) + return false; + + Field* fields = garrison->Fetch(); + _siteLevel = sGarrSiteLevelStore.LookupEntry(fields[0].GetUInt32()); + _followerActivationsRemainingToday = fields[1].GetUInt32(); + if (!_siteLevel) + return false; + + InitializePlots(); + + if (blueprints) + { + do + { + fields = blueprints->Fetch(); + if (GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(fields[0].GetUInt32())) + _knownBuildings.insert(building->ID); + + } while (blueprints->NextRow()); + } + + if (buildings) + { + do + { + fields = buildings->Fetch(); + uint32 plotInstanceId = fields[0].GetUInt32(); + uint32 buildingId = fields[1].GetUInt32(); + time_t timeBuilt = time_t(fields[2].GetUInt64()); + bool active = fields[3].GetBool(); + + + Plot* plot = GetPlot(plotInstanceId); + if (!plot) + continue; + + if (!sGarrBuildingStore.LookupEntry(buildingId)) + continue; + + plot->BuildingInfo.PacketInfo = boost::in_place(); + plot->BuildingInfo.PacketInfo->GarrPlotInstanceID = plotInstanceId; + plot->BuildingInfo.PacketInfo->GarrBuildingID = buildingId; + plot->BuildingInfo.PacketInfo->TimeBuilt = timeBuilt; + plot->BuildingInfo.PacketInfo->Active = active; + + } while (buildings->NextRow()); + } + + return true; +} + +void Garrison::SaveToDB(SQLTransaction& trans) +{ + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON); + stmt->setUInt64(0, _owner->GetGUID().GetCounter()); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS); + stmt->setUInt64(0, _owner->GetGUID().GetCounter()); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS); + stmt->setUInt64(0, _owner->GetGUID().GetCounter()); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON); + stmt->setUInt64(0, _owner->GetGUID().GetCounter()); + stmt->setUInt32(1, _siteLevel->ID); + stmt->setUInt32(2, _followerActivationsRemainingToday); + trans->Append(stmt); + + for (uint32 building : _knownBuildings) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS); + stmt->setUInt64(0, _owner->GetGUID().GetCounter()); + stmt->setUInt32(1, building); + trans->Append(stmt); + } + + for (auto const& p : _plots) + { + Plot const& plot = p.second; + if (plot.BuildingInfo.PacketInfo) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS); + stmt->setUInt64(0, _owner->GetGUID().GetCounter()); + stmt->setUInt32(1, plot.BuildingInfo.PacketInfo->GarrPlotInstanceID); + stmt->setUInt32(2, plot.BuildingInfo.PacketInfo->GarrBuildingID); + stmt->setUInt64(3, plot.BuildingInfo.PacketInfo->TimeBuilt); + stmt->setBool(4, plot.BuildingInfo.PacketInfo->Active); + trans->Append(stmt); + } + } +} + +bool Garrison::Create(uint32 garrSiteId) +{ + _siteLevel = sGarrisonMgr.GetGarrSiteLevelEntry(garrSiteId, 1); + if (!_siteLevel) + return false; + + InitializePlots(); + + WorldPackets::Garrison::GarrisonCreateResult garrisonCreateResult; + garrisonCreateResult.GarrSiteLevelID = _siteLevel->ID; + _owner->SendDirectMessage(garrisonCreateResult.Write()); + _owner->SendUpdatePhasing(); + SendRemoteInfo(); + return true; +} + +void Garrison::InitializePlots() +{ + if (std::vector<GarrSiteLevelPlotInstEntry const*> const* plots = sGarrisonMgr.GetGarrPlotInstForSiteLevel(_siteLevel->ID)) + { + for (std::size_t i = 0; i < plots->size(); ++i) + { + uint32 garrPlotInstanceId = plots->at(i)->GarrPlotInstanceID; + GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId); + GameObjectsEntry const* gameObject = sGarrisonMgr.GetPlotGameObject(_siteLevel->MapID, garrPlotInstanceId); + if (!plotInstance || !gameObject) + continue; + + GarrPlotEntry const* plot = sGarrPlotStore.LookupEntry(plotInstance->GarrPlotID); + if (!plot) + continue; + + Plot& plotInfo = _plots[garrPlotInstanceId]; + plotInfo.PacketInfo.GarrPlotInstanceID = garrPlotInstanceId; + plotInfo.PacketInfo.PlotPos.Relocate(gameObject->Position.X, gameObject->Position.Y, gameObject->Position.Z, 2 * std::acos(gameObject->RotationW)); + plotInfo.PacketInfo.PlotType = plot->PlotType; + plotInfo.EmptyGameObjectId = gameObject->ID; + plotInfo.GarrSiteLevelPlotInstId = plots->at(i)->ID; + } + } +} + +void Garrison::Upgrade() +{ +} + +void Garrison::Enter() const +{ + WorldLocation loc(_siteLevel->MapID); + loc.Relocate(_owner); + _owner->TeleportTo(loc, TELE_TO_SEAMLESS); +} + +void Garrison::Leave() const +{ + if (MapEntry const* map = sMapStore.LookupEntry(_siteLevel->MapID)) + { + WorldLocation loc(map->ParentMapID); + loc.Relocate(_owner); + _owner->TeleportTo(loc, TELE_TO_SEAMLESS); + } +} + +GarrisonFactionIndex Garrison::GetFaction() const +{ + return _owner->GetTeam() == HORDE ? GARRISON_FACTION_INDEX_HORDE : GARRISON_FACTION_INDEX_ALLIANCE; +} + +std::vector<Garrison::Plot*> Garrison::GetPlots() +{ + std::vector<Plot*> plots; + plots.reserve(_plots.size()); + for (auto& p : _plots) + plots.push_back(&p.second); + + return plots; +} + +Garrison::Plot* Garrison::GetPlot(uint32 garrPlotInstanceId) +{ + auto itr = _plots.find(garrPlotInstanceId); + if (itr != _plots.end()) + return &itr->second; + + return nullptr; +} + +Garrison::Plot const* Garrison::GetPlot(uint32 garrPlotInstanceId) const +{ + auto itr = _plots.find(garrPlotInstanceId); + if (itr != _plots.end()) + return &itr->second; + + return nullptr; +} + +void Garrison::LearnBlueprint(uint32 garrBuildingId) +{ + WorldPackets::Garrison::GarrisonLearnBlueprintResult learnBlueprintResult; + learnBlueprintResult.BuildingID = garrBuildingId; + learnBlueprintResult.Result = GARRISON_SUCCESS; + + if (!sGarrBuildingStore.LookupEntry(garrBuildingId)) + learnBlueprintResult.Result = GARRISON_ERROR_INVALID_BUILDINGID; + else if (_knownBuildings.count(garrBuildingId)) + learnBlueprintResult.Result = GARRISON_ERROR_BLUEPRINT_KNOWN; + else + _knownBuildings.insert(garrBuildingId); + + _owner->SendDirectMessage(learnBlueprintResult.Write()); +} + +void Garrison::UnlearnBlueprint(uint32 garrBuildingId) +{ + WorldPackets::Garrison::GarrisonUnlearnBlueprintResult unlearnBlueprintResult; + unlearnBlueprintResult.BuildingID = garrBuildingId; + unlearnBlueprintResult.Result = GARRISON_SUCCESS; + + if (!sGarrBuildingStore.LookupEntry(garrBuildingId)) + unlearnBlueprintResult.Result = GARRISON_ERROR_INVALID_BUILDINGID; + else if (!_knownBuildings.count(garrBuildingId)) + unlearnBlueprintResult.Result = GARRISON_ERROR_BLUEPRINT_NOT_KNOWN; + else + _knownBuildings.erase(garrBuildingId); + + _owner->SendDirectMessage(unlearnBlueprintResult.Write()); +} + +void Garrison::PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId) +{ + WorldPackets::Garrison::GarrisonPlaceBuildingResult placeBuildingResult; + placeBuildingResult.Result = CheckBuildingPlacement(garrPlotInstanceId, garrBuildingId); + if (placeBuildingResult.Result == GARRISON_SUCCESS) + { + placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId; + placeBuildingResult.BuildingInfo.GarrBuildingID = garrBuildingId; + placeBuildingResult.BuildingInfo.TimeBuilt = time(nullptr); + + Plot* plot = GetPlot(garrPlotInstanceId); + uint32 oldBuildingId = 0; + Map* map = FindMap(); + GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(garrBuildingId); + if (map) + plot->DeleteGameObject(map); + + if (plot->BuildingInfo.PacketInfo) + { + oldBuildingId = plot->BuildingInfo.PacketInfo->GarrBuildingID; + if (sGarrBuildingStore.AssertEntry(oldBuildingId)->Type != building->Type) + plot->ClearBuildingInfo(_owner); + } + + plot->SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner); + if (map) + if (GameObject* go = plot->CreateGameObject(map, GetFaction())) + map->AddToMap(go); + + _owner->ModifyCurrency(building->CostCurrencyID, -building->CostCurrencyAmount, false, true); + _owner->ModifyMoney(-building->CostMoney * GOLD, false); + + if (oldBuildingId) + { + WorldPackets::Garrison::GarrisonBuildingRemoved buildingRemoved; + buildingRemoved.Result = GARRISON_SUCCESS; + buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId; + buildingRemoved.GarrBuildingID = oldBuildingId; + _owner->SendDirectMessage(buildingRemoved.Write()); + } + } + + _owner->SendDirectMessage(placeBuildingResult.Write()); +} + +void Garrison::CancelBuildingConstruction(uint32 garrPlotInstanceId) +{ + WorldPackets::Garrison::GarrisonBuildingRemoved buildingRemoved; + buildingRemoved.Result = CheckBuildingRemoval(garrPlotInstanceId); + if (buildingRemoved.Result == GARRISON_SUCCESS) + { + Plot* plot = GetPlot(garrPlotInstanceId); + + buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId; + buildingRemoved.GarrBuildingID = plot->BuildingInfo.PacketInfo->GarrBuildingID; + + Map* map = FindMap(); + if (map) + plot->DeleteGameObject(map); + + plot->ClearBuildingInfo(_owner); + _owner->SendDirectMessage(buildingRemoved.Write()); + + GarrBuildingEntry const* constructing = sGarrBuildingStore.AssertEntry(buildingRemoved.GarrBuildingID); + // Refund construction/upgrade cost + _owner->ModifyCurrency(constructing->CostCurrencyID, constructing->CostCurrencyAmount, false, true); + _owner->ModifyMoney(constructing->CostMoney * GOLD, false); + + if (constructing->Level > 1) + { + // Restore previous level building + GarrBuildingEntry const* restored = sGarrisonMgr.GetPreviousLevelBuilding(constructing->Type, constructing->Level); + ASSERT(restored); + + WorldPackets::Garrison::GarrisonPlaceBuildingResult placeBuildingResult; + placeBuildingResult.Result = GARRISON_SUCCESS; + placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId; + placeBuildingResult.BuildingInfo.GarrBuildingID = restored->ID; + placeBuildingResult.BuildingInfo.TimeBuilt = time(nullptr); + placeBuildingResult.BuildingInfo.Active = true; + + plot->SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner); + _owner->SendDirectMessage(placeBuildingResult.Write()); + } + + if (map) + if (GameObject* go = plot->CreateGameObject(map, GetFaction())) + map->AddToMap(go); + } + else + _owner->SendDirectMessage(buildingRemoved.Write()); +} + +void Garrison::SendInfo() +{ + WorldPackets::Garrison::GetGarrisonInfoResult garrisonInfo; + garrisonInfo.GarrSiteID = _siteLevel->SiteID; + garrisonInfo.GarrSiteLevelID = _siteLevel->ID; + garrisonInfo.FactionIndex = GetFaction(); + garrisonInfo.NumFollowerActivationsRemaining = _followerActivationsRemainingToday; + for (auto& p : _plots) + { + Plot& plot = p.second; + garrisonInfo.Plots.push_back(&plot.PacketInfo); + if (plot.BuildingInfo.PacketInfo) + garrisonInfo.Buildings.push_back(plot.BuildingInfo.PacketInfo.get_ptr()); + } + + _owner->SendDirectMessage(garrisonInfo.Write()); +} + +void Garrison::SendRemoteInfo() const +{ + MapEntry const* garrisonMap = sMapStore.LookupEntry(_siteLevel->MapID); + if (!garrisonMap || int32(_owner->GetMapId()) != garrisonMap->ParentMapID) + return; + + WorldPackets::Garrison::GarrisonRemoteInfo remoteInfo; + remoteInfo.Sites.resize(1); + + WorldPackets::Garrison::GarrisonRemoteSiteInfo& remoteSiteInfo = remoteInfo.Sites[0]; + remoteSiteInfo.GarrSiteLevelID = _siteLevel->ID; + for (auto const& p : _plots) + if (p.second.BuildingInfo.PacketInfo) + remoteSiteInfo.Buildings.emplace_back(p.first, p.second.BuildingInfo.PacketInfo->GarrBuildingID); + + _owner->SendDirectMessage(remoteInfo.Write()); +} + +void Garrison::SendBlueprintAndSpecializationData() +{ + WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationDataResult data; + data.BlueprintsKnown = &_knownBuildings; + _owner->SendDirectMessage(data.Write()); +} + +void Garrison::SendBuildingLandmarks(Player* receiver) const +{ + WorldPackets::Garrison::GarrisonBuildingLandmarks buildingLandmarks; + buildingLandmarks.Landmarks.reserve(_plots.size()); + + for (auto const& p : _plots) + { + Plot const& plot = p.second; + if (plot.BuildingInfo.PacketInfo) + if (uint32 garrBuildingPlotInstId = sGarrisonMgr.GetGarrBuildingPlotInst(plot.BuildingInfo.PacketInfo->GarrBuildingID, plot.GarrSiteLevelPlotInstId)) + buildingLandmarks.Landmarks.emplace_back(garrBuildingPlotInstId, plot.PacketInfo.PlotPos); + } + + receiver->SendDirectMessage(buildingLandmarks.Write()); +} + +Map* Garrison::FindMap() const +{ + return sMapMgr->FindMap(_siteLevel->MapID, _owner->GetGUID().GetCounter()); +} + +GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const +{ + GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId); + Plot const* plot = GetPlot(garrPlotInstanceId); + if (!plotInstance || !plot) + return GARRISON_ERROR_INVALID_PLOT; + + GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(garrBuildingId); + if (!building) + return GARRISON_ERROR_INVALID_BUILDINGID; + + if (!sGarrisonMgr.IsPlotMatchingBuilding(plotInstance->GarrPlotID, garrBuildingId)) + return GARRISON_ERROR_INVALID_PLOT_BUILDING; + + // Cannot place buldings of higher level than garrison level + if (building->Level > _siteLevel->Level) + return GARRISON_ERROR_INVALID_BUILDINGID; + + if (building->Flags & GARRISON_BUILDING_FLAG_NEEDS_PLAN) + { + if (!_knownBuildings.count(garrBuildingId)) + return GARRISON_ERROR_BLUEPRINT_NOT_KNOWN; + } + else // Building is built as a quest reward + return GARRISON_ERROR_INVALID_BUILDINGID; + + // Check all plots to find if we already have this building + GarrBuildingEntry const* existingBuilding; + for (auto const& p : _plots) + { + if (p.second.BuildingInfo.PacketInfo) + { + existingBuilding = sGarrBuildingStore.AssertEntry(p.second.BuildingInfo.PacketInfo->GarrBuildingID); + if (existingBuilding->Type == building->Type) + if (p.first != garrPlotInstanceId || existingBuilding->Level + 1 != building->Level) // check if its an upgrade in same plot + return GARRISON_ERROR_BUILDING_EXISTS; + } + } + + if (!_owner->HasCurrency(building->CostCurrencyID, building->CostCurrencyAmount)) + return GARRISON_ERROR_NOT_ENOUGH_CURRENCY; + + if (!_owner->HasEnoughMoney(uint64(building->CostMoney * GOLD))) + return GARRISON_ERROR_NOT_ENOUGH_GOLD; + + // New building cannot replace another building currently under construction + if (plot->BuildingInfo.PacketInfo) + if (!plot->BuildingInfo.PacketInfo->Active) + return GARRISON_ERROR_NO_BUILDING; + + return GARRISON_SUCCESS; +} + +GarrisonError Garrison::CheckBuildingRemoval(uint32 garrPlotInstanceId) const +{ + Plot const* plot = GetPlot(garrPlotInstanceId); + if (!plot) + return GARRISON_ERROR_INVALID_PLOT; + + if (!plot->BuildingInfo.PacketInfo) + return GARRISON_ERROR_NO_BUILDING; + + if (plot->BuildingInfo.CanActivate()) + return GARRISON_ERROR_BUILDING_EXISTS; + + return GARRISON_SUCCESS; +} + +GameObject* Garrison::Plot::CreateGameObject(Map* map, GarrisonFactionIndex faction) +{ + uint32 entry = EmptyGameObjectId; + if (BuildingInfo.PacketInfo) + { + GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.AssertEntry(PacketInfo.GarrPlotInstanceID); + GarrPlotEntry const* plot = sGarrPlotStore.AssertEntry(plotInstance->GarrPlotID); + GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(BuildingInfo.PacketInfo->GarrBuildingID); + if (BuildingInfo.PacketInfo->Active) + entry = faction == GARRISON_FACTION_INDEX_HORDE ? building->HordeGameObjectID : building->AllianceGameObjectID; + else + entry = faction == GARRISON_FACTION_INDEX_HORDE ? plot->HordeConstructionGameObjectID : plot->AllianceConstructionGameObjectID; + } + + if (!sObjectMgr->GetGameObjectTemplate(entry)) + { + TC_LOG_ERROR("garrison", "Garrison attempted to spawn gameobject whose template doesn't exist (%u)", entry); + return nullptr; + } + + Position const& pos = PacketInfo.PlotPos; + GameObject* go = new GameObject(); + if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, 0, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), + 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_ACTIVE)) + { + delete go; + return nullptr; + } + + BuildingInfo.Guid = go->GetGUID(); + return go; +} + +void Garrison::Plot::DeleteGameObject(Map* map) +{ + if (BuildingInfo.Guid.IsEmpty()) + return; + + if (GameObject* oldBuilding = map->GetGameObject(BuildingInfo.Guid)) + oldBuilding->Delete(); + + BuildingInfo.Guid.Clear(); +} + +void Garrison::Plot::ClearBuildingInfo(Player* owner) +{ + WorldPackets::Garrison::GarrisonPlotPlaced plotPlaced; + plotPlaced.PlotInfo = &PacketInfo; + owner->SendDirectMessage(plotPlaced.Write()); + + BuildingInfo.PacketInfo = boost::none; +} + +void Garrison::Plot::SetBuildingInfo(WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo, Player* owner) +{ + if (!BuildingInfo.PacketInfo) + { + WorldPackets::Garrison::GarrisonPlotRemoved plotRemoved; + plotRemoved.GarrPlotInstanceID = PacketInfo.GarrPlotInstanceID; + owner->SendDirectMessage(plotRemoved.Write()); + } + + BuildingInfo.PacketInfo = buildingInfo; +} + +bool Garrison::Building::CanActivate() const +{ + if (PacketInfo) + { + GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(PacketInfo->GarrBuildingID); + if (PacketInfo->TimeBuilt + building->BuildDuration <= time(nullptr)) + return true; + } + + return false; +} diff --git a/src/server/game/Garrison/Garrison.h b/src/server/game/Garrison/Garrison.h new file mode 100644 index 00000000000..1b12ac62263 --- /dev/null +++ b/src/server/game/Garrison/Garrison.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef Garrison_h__ +#define Garrison_h__ + +#include "Player.h" +#include "GarrisonPackets.h" + +enum GarrisonFactionIndex +{ + GARRISON_FACTION_INDEX_HORDE = 0, + GARRISON_FACTION_INDEX_ALLIANCE = 1 +}; + +enum GarrisonBuildingFlags +{ + GARRISON_BUILDING_FLAG_NEEDS_PLAN = 0x1 +}; + +enum GarrisonError +{ + GARRISON_SUCCESS = 0, + GARRISON_ERROR_INVALID_PLOT = 1, + GARRISON_ERROR_INVALID_BUILDINGID = 2, + GARRISON_ERROR_INVALID_PLOT_BUILDING = 7, + GARRISON_ERROR_NO_BUILDING = 8, + GARRISON_ERROR_SPECIALIZATION_KNOWN = 19, + GARRISON_ERROR_BLUEPRINT_KNOWN = 21, + GARRISON_ERROR_BLUEPRINT_NOT_KNOWN = 22, + GARRISON_ERROR_BUILDING_EXISTS = 24, + GARRISON_ERROR_NOT_ENOUGH_CURRENCY = 46, + GARRISON_ERROR_NOT_ENOUGH_GOLD = 47 +}; + +enum GarrisonFollowerStatus +{ + FOLLOWER_STATUS_FAVORITE = 0x01, + FOLLOWER_STATUS_EXHAUSTED = 0x02, + FOLLOWER_STATUS_INACTIVE = 0x04 +}; + +class GameObject; +class Map; + +class Garrison +{ +public: + struct Building + { + bool CanActivate() const; + + ObjectGuid Guid; + Optional<WorldPackets::Garrison::GarrisonBuildingInfo> PacketInfo; + }; + + struct Plot + { + GameObject* CreateGameObject(Map* map, GarrisonFactionIndex faction); + void DeleteGameObject(Map* map); + void ClearBuildingInfo(Player* owner); + void SetBuildingInfo(WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo, Player* owner); + + WorldPackets::Garrison::GarrisonPlotInfo PacketInfo; + uint32 EmptyGameObjectId = 0; + uint32 GarrSiteLevelPlotInstId = 0; + Building BuildingInfo; + }; + + explicit Garrison(Player* owner); + + bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings); + void SaveToDB(SQLTransaction& trans); + + bool Create(uint32 garrSiteId); + void Upgrade(); + + void Enter() const; + void Leave() const; + + GarrisonFactionIndex GetFaction() const; + std::vector<Plot*> GetPlots(); + Plot* GetPlot(uint32 garrPlotInstanceId); + Plot const* GetPlot(uint32 garrPlotInstanceId) const; + + void LearnBlueprint(uint32 garrBuildingId); + void UnlearnBlueprint(uint32 garrBuildingId); + void PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId); + void CancelBuildingConstruction(uint32 garrPlotInstanceId); + + void SendInfo(); + void SendRemoteInfo() const; + void SendBlueprintAndSpecializationData(); + void SendBuildingLandmarks(Player* receiver) const; + + void ResetFollowerActivationLimit() { _followerActivationsRemainingToday = 1; } + +private: + Map* FindMap() const; + void InitializePlots(); + GarrisonError CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const; + GarrisonError CheckBuildingRemoval(uint32 garrPlotInstanceId) const; + Player* _owner; + GarrSiteLevelEntry const* _siteLevel; + uint32 _followerActivationsRemainingToday; + + std::unordered_map<uint32 /*garrPlotInstanceId*/, Plot> _plots; + std::unordered_set<uint32 /*garrBuildingId*/> _knownBuildings; +}; + +#endif // Garrison_h__ diff --git a/src/server/game/Garrison/GarrisonMap.cpp b/src/server/game/Garrison/GarrisonMap.cpp new file mode 100644 index 00000000000..7316504d185 --- /dev/null +++ b/src/server/game/Garrison/GarrisonMap.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "GarrisonMap.h" +#include "Garrison.h" +#include "ObjectAccessor.h" +#include "ObjectGridLoader.h" +#include "GameObject.h" + +class GarrisonGridLoader +{ +public: + GarrisonGridLoader(NGridType* grid, GarrisonMap* map, Cell const& cell) + : i_cell(cell), i_grid(grid), i_map(map), i_garrison(map->GetGarrison()), i_gameObjects(0), i_creatures(0) + { } + + void Visit(GameObjectMapType& m); + void Visit(CreatureMapType& m); + + void LoadN(); + + template<class T> static void SetObjectCell(T* obj, CellCoord const& cellCoord); + template<class T> void Visit(GridRefManager<T>& /*m*/) { } + +private: + Cell i_cell; + NGridType* i_grid; + GarrisonMap* i_map; + Garrison* i_garrison; + uint32 i_gameObjects; + uint32 i_creatures; +}; + +void GarrisonGridLoader::LoadN() +{ + if (i_garrison) + { + i_cell.data.Part.cell_y = 0; + for (uint32 x = 0; x < MAX_NUMBER_OF_CELLS; ++x) + { + i_cell.data.Part.cell_x = x; + for (uint32 y = 0; y < MAX_NUMBER_OF_CELLS; ++y) + { + i_cell.data.Part.cell_y = y; + + //Load creatures and game objects + TypeContainerVisitor<GarrisonGridLoader, GridTypeMapContainer> visitor(*this); + i_grid->VisitGrid(x, y, visitor); + } + } + } + + TC_LOG_DEBUG("maps", "%u GameObjects and %u Creatures loaded for grid %u on map %u", i_gameObjects, i_creatures, i_grid->GetGridId(), i_map->GetId()); +} + +void GarrisonGridLoader::Visit(GameObjectMapType& m) +{ + std::vector<Garrison::Plot*> plots = i_garrison->GetPlots(); + if (!plots.empty()) + { + CellCoord cellCoord = i_cell.GetCellCoord(); + for (Garrison::Plot* plot : plots) + { + Position const& spawn = plot->PacketInfo.PlotPos; + if (cellCoord != Trinity::ComputeCellCoord(spawn.GetPositionX(), spawn.GetPositionY())) + continue; + + GameObject* go = plot->CreateGameObject(i_map, i_garrison->GetFaction()); + if (!go) + continue; + + go->AddToGrid(m); + ObjectGridLoader::SetObjectCell(go, cellCoord); + go->AddToWorld(); + ++i_gameObjects; + } + } +} + +void GarrisonGridLoader::Visit(CreatureMapType& /*m*/) +{ + +} + +GarrisonMap::GarrisonMap(uint32 id, time_t expiry, uint32 instanceId, Map* parent, ObjectGuid const& owner) + : Map(id, expiry, instanceId, DIFFICULTY_NORMAL, parent), _owner(owner) +{ + GarrisonMap::InitVisibilityDistance(); +} + +void GarrisonMap::LoadGridObjects(NGridType* grid, Cell const& cell) +{ + Map::LoadGridObjects(grid, cell); + + GarrisonGridLoader loader(grid, this, cell); + loader.LoadN(); +} + +Garrison* GarrisonMap::GetGarrison() +{ + if (Player* owner = ObjectAccessor::FindConnectedPlayer(_owner)) + return owner->GetGarrison(); + + return nullptr; +} + +void GarrisonMap::InitVisibilityDistance() +{ + //init visibility distance for instances + m_VisibleDistance = World::GetMaxVisibleDistanceInBGArenas(); + m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInBGArenas(); +} diff --git a/src/server/game/Garrison/GarrisonMap.h b/src/server/game/Garrison/GarrisonMap.h new file mode 100644 index 00000000000..0ccc77b05fa --- /dev/null +++ b/src/server/game/Garrison/GarrisonMap.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GarrisonMap_h__ +#define GarrisonMap_h__ + +#include "Map.h" + +class Garrison; + +class GarrisonMap : public Map +{ +public: + GarrisonMap(uint32 id, time_t, uint32 instanceId, Map* parent, ObjectGuid const& owner); + + void LoadGridObjects(NGridType* grid, Cell const& cell) override; + Garrison* GetGarrison(); + + void InitVisibilityDistance() override; + +private: + ObjectGuid _owner; +}; + +#endif // GarrisonMap_h__ diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp new file mode 100644 index 00000000000..f81baa6ddf1 --- /dev/null +++ b/src/server/game/Garrison/GarrisonMgr.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "GarrisonMgr.h" +#include "ObjectDefines.h" + +void GarrisonMgr::Initialize() +{ + for (GarrSiteLevelPlotInstEntry const* plotInstance : sGarrSiteLevelPlotInstStore) + _garrisonPlotInstBySiteLevel[plotInstance->GarrSiteLevelID].push_back(plotInstance); + + for (GameObjectsEntry const* gameObject : sGameObjectsStore) + if (gameObject->Type == GAMEOBJECT_TYPE_GARRISON_PLOT) + _garrisonPlots[gameObject->MapID][gameObject->Data[0]] = gameObject; + + for (GarrPlotBuildingEntry const* plotBuilding : sGarrPlotBuildingStore) + _garrisonBuildingsByPlot[plotBuilding->GarrPlotID].insert(plotBuilding->GarrBuildingID); + + for (GarrBuildingPlotInstEntry const* buildingPlotInst : sGarrBuildingPlotInstStore) + _garrisonBuildingPlotInstances[MAKE_PAIR64(buildingPlotInst->GarrBuildingID, buildingPlotInst->GarrSiteLevelPlotInstID)] = buildingPlotInst->ID; + + for (GarrBuildingEntry const* building : sGarrBuildingStore) + _garrisonBuildingsByType[building->Type].push_back(building); +} + +GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const +{ + for (GarrSiteLevelEntry const* garrSiteLevel : sGarrSiteLevelStore) + if (garrSiteLevel->SiteID == garrSiteId && garrSiteLevel->Level == level) + return garrSiteLevel; + + return nullptr; +} + +std::vector<GarrSiteLevelPlotInstEntry const*> const* GarrisonMgr::GetGarrPlotInstForSiteLevel(uint32 garrSiteLevelId) const +{ + auto itr = _garrisonPlotInstBySiteLevel.find(garrSiteLevelId); + if (itr != _garrisonPlotInstBySiteLevel.end()) + return &itr->second; + + return nullptr; +} + +GameObjectsEntry const* GarrisonMgr::GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const +{ + auto mapItr = _garrisonPlots.find(mapId); + if (mapItr != _garrisonPlots.end()) + { + auto plotItr = mapItr->second.find(garrPlotInstanceId); + if (plotItr != mapItr->second.end()) + return plotItr->second; + } + + return nullptr; +} + +bool GarrisonMgr::IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const +{ + auto plotItr = _garrisonBuildingsByPlot.find(garrPlotId); + if (plotItr != _garrisonBuildingsByPlot.end()) + return plotItr->second.count(garrBuildingId) > 0; + + return false; +} + +uint32 GarrisonMgr::GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const +{ + auto itr = _garrisonBuildingPlotInstances.find(MAKE_PAIR64(garrBuildingId, garrSiteLevelPlotInstId)); + if (itr != _garrisonBuildingPlotInstances.end()) + return itr->second; + + return 0; +} + +GarrBuildingEntry const* GarrisonMgr::GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const +{ + auto itr = _garrisonBuildingsByType.find(buildingType); + if (itr != _garrisonBuildingsByType.end()) + for (GarrBuildingEntry const* building : itr->second) + if (building->Level == currentLevel - 1) + return building; + + return nullptr; +} diff --git a/src/server/game/Garrison/GarrisonMgr.h b/src/server/game/Garrison/GarrisonMgr.h new file mode 100644 index 00000000000..89fd90f25c3 --- /dev/null +++ b/src/server/game/Garrison/GarrisonMgr.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GarrisonMgr_h__ +#define GarrisonMgr_h__ + +#include <unordered_set> + +#include "DB2Stores.h" + +class GarrisonMgr +{ +public: + static GarrisonMgr& Instance() + { + static GarrisonMgr instance; + return instance; + } + + void Initialize(); + + GarrSiteLevelEntry const* GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const; + std::vector<GarrSiteLevelPlotInstEntry const*> const* GetGarrPlotInstForSiteLevel(uint32 garrSiteLevelId) const; + GameObjectsEntry const* GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const; + bool IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const; + uint32 GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const; + GarrBuildingEntry const* GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const; + +private: + std::unordered_map<uint32 /*garrSiteId*/, std::vector<GarrSiteLevelPlotInstEntry const*>> _garrisonPlotInstBySiteLevel; + std::unordered_map<uint32 /*mapId*/, std::unordered_map<uint32 /*garrPlotId*/, GameObjectsEntry const*>> _garrisonPlots; + std::unordered_map<uint32 /*garrPlotId*/, std::unordered_set<uint32/*garrBuildingId*/>> _garrisonBuildingsByPlot; + std::unordered_map<uint64 /*garrBuildingId | garrSiteLevelPlotInstId << 32*/, uint32 /*garrBuildingPlotInstId*/> _garrisonBuildingPlotInstances; + std::unordered_map<uint32 /*buildingType*/, std::vector<GarrBuildingEntry const*>> _garrisonBuildingsByType; +}; + +#define sGarrisonMgr GarrisonMgr::Instance() + +#endif // GarrisonMgr_h__ diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index 44e7271ca70..474b608a846 100644 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -36,6 +36,7 @@ #include "Opcodes.h" #include "Pet.h" #include "Player.h" +#include "Transport.h" #include "Vehicle.h" #include "World.h" #include "WorldPacket.h" @@ -46,42 +47,7 @@ ObjectAccessor::ObjectAccessor() { } ObjectAccessor::~ObjectAccessor() { } -template<class T> T* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, ObjectGuid guid, T* /*fake*/) -{ - T* obj = HashMapHolder<T>::Find(guid); - if (!obj || obj->GetMapId() != mapid) - return NULL; - - CellCoord p = Trinity::ComputeCellCoord(x, y); - if (!p.IsCoordValid()) - { - TC_LOG_ERROR("misc", "ObjectAccessor::GetObjectInWorld: invalid coordinates supplied X:%f Y:%f grid cell [%u:%u]", x, y, p.x_coord, p.y_coord); - return NULL; - } - - CellCoord q = Trinity::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY()); - if (!q.IsCoordValid()) - { - TC_LOG_ERROR("misc", "ObjectAccessor::GetObjecInWorld: object (%s) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID().ToString().c_str(), obj->GetPositionX(), obj->GetPositionY(), q.x_coord, q.y_coord); - return NULL; - } - - int32 dx = int32(p.x_coord) - int32(q.x_coord); - int32 dy = int32(p.y_coord) - int32(q.y_coord); - - if (dx > -2 && dx < 2 && dy > -2 && dy < 2) - return obj; - else - return NULL; -} - -Player* ObjectAccessor::GetObjectInWorld(ObjectGuid guid, Player* /*typeSpecifier*/) -{ - Player* player = HashMapHolder<Player>::Find(guid); - return player && player->IsInWorld() ? player : NULL; -} - -WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid guid) +WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid const& guid) { switch (guid.GetHigh()) { @@ -98,7 +64,7 @@ WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid gui } } -Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid guid, uint32 typemask) +Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid const& guid, uint32 typemask) { switch (guid.GetHigh()) { @@ -140,56 +106,67 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid gui return NULL; } -Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, ObjectGuid guid) +Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, ObjectGuid const& guid) { - return GetObjectInMap(guid, u.GetMap(), (Corpse*)NULL); + return u.GetMap()->GetCorpse(guid); } -GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid guid) +GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid const& guid) { - return GetObjectInMap(guid, u.GetMap(), (GameObject*)NULL); + return u.GetMap()->GetGameObject(guid); } -Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid guid) +Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid const& guid) { - if (!guid.IsMOTransport()) - return NULL; + return u.GetMap()->GetTransport(guid); +} - GameObject* go = GetGameObject(u, guid); - return go ? go->ToTransport() : NULL; +DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid const& guid) +{ + return u.GetMap()->GetDynamicObject(guid); } -DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid guid) +AreaTrigger* ObjectAccessor::GetAreaTrigger(WorldObject const& u, ObjectGuid const& guid) { - return GetObjectInMap(guid, u.GetMap(), (DynamicObject*)NULL); + return u.GetMap()->GetAreaTrigger(guid); } -AreaTrigger* ObjectAccessor::GetAreaTrigger(WorldObject const& u, ObjectGuid guid) +Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid const& guid) { - return GetObjectInMap(guid, u.GetMap(), (AreaTrigger*)NULL); + if (guid.IsPlayer()) + return GetPlayer(u, guid); + + if (guid.IsPet()) + return GetPet(u, guid); + + return GetCreature(u, guid); } -Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid guid) +Creature* ObjectAccessor::GetCreature(WorldObject const& u, ObjectGuid const& guid) { - return GetObjectInMap(guid, u.GetMap(), (Unit*)NULL); + return u.GetMap()->GetCreature(guid); } -Creature* ObjectAccessor::GetCreature(WorldObject const& u, ObjectGuid guid) +Pet* ObjectAccessor::GetPet(WorldObject const& u, ObjectGuid const& guid) { - return GetObjectInMap(guid, u.GetMap(), (Creature*)NULL); + return u.GetMap()->GetPet(guid); } -Pet* ObjectAccessor::GetPet(WorldObject const& u, ObjectGuid guid) +Player* ObjectAccessor::GetPlayer(Map const* m, ObjectGuid const& guid) { - return GetObjectInMap(guid, u.GetMap(), (Pet*)NULL); + if (Player* player = HashMapHolder<Player>::Find(guid)) + if (player->IsInWorld() && player->GetMap() == m) + return player; + + return nullptr; } -Player* ObjectAccessor::GetPlayer(WorldObject const& u, ObjectGuid guid) +Player* ObjectAccessor::GetPlayer(WorldObject const& u, ObjectGuid const& guid) { - return GetObjectInMap(guid, u.GetMap(), (Player*)NULL); + return GetPlayer(u.GetMap(), guid); } -Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, ObjectGuid guid) +Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, ObjectGuid const& guid) { if (guid.IsPet()) return GetPet(u, guid); @@ -200,26 +177,17 @@ Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const& u, Object return NULL; } -Pet* ObjectAccessor::FindPet(ObjectGuid guid) -{ - return GetObjectInWorld(guid, (Pet*)NULL); -} - -Player* ObjectAccessor::FindPlayer(ObjectGuid guid) +Player* ObjectAccessor::FindPlayer(ObjectGuid const& guid) { - return GetObjectInWorld(guid, (Player*)NULL); + Player* player = HashMapHolder<Player>::Find(guid); + return player && player->IsInWorld() ? player : nullptr; } -Player* ObjectAccessor::FindConnectedPlayer(ObjectGuid guid) +Player* ObjectAccessor::FindConnectedPlayer(ObjectGuid const& guid) { return HashMapHolder<Player>::Find(guid); } -Unit* ObjectAccessor::FindUnit(ObjectGuid guid) -{ - return GetObjectInWorld(guid, (Unit*)NULL); -} - Player* ObjectAccessor::FindPlayerByName(std::string const& name) { boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock()); @@ -267,7 +235,7 @@ void ObjectAccessor::SaveAllPlayers() itr->second->SaveToDB(); } -Corpse* ObjectAccessor::GetCorpseForPlayerGUID(ObjectGuid guid) +Corpse* ObjectAccessor::GetCorpseForPlayerGUID(ObjectGuid const& guid) { boost::shared_lock<boost::shared_mutex> lock(_corpseLock); @@ -299,7 +267,6 @@ void ObjectAccessor::RemoveCorpse(Corpse* corpse) } } else - corpse->RemoveFromWorld(); // Critical section @@ -359,7 +326,7 @@ void ObjectAccessor::AddCorpsesToGrid(GridCoord const& gridpair, GridType& grid, } } -Corpse* ObjectAccessor::ConvertCorpseForPlayer(ObjectGuid player_guid, bool insignia /*=false*/) +Corpse* ObjectAccessor::ConvertCorpseForPlayer(ObjectGuid const& player_guid, bool insignia /*=false*/) { Corpse* corpse = GetCorpseForPlayerGUID(player_guid); if (!corpse) @@ -398,12 +365,11 @@ Corpse* ObjectAccessor::ConvertCorpseForPlayer(ObjectGuid player_guid, bool insi bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); bones->SetGridCoord(corpse->GetGridCoord()); - // bones->m_time = m_time; // don't overwrite time - // bones->m_type = m_type; // don't overwrite type bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); bones->SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Empty); + bones->SetGuidValue(OBJECT_FIELD_DATA, corpse->GetGuidValue(OBJECT_FIELD_DATA)); for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) { @@ -439,27 +405,6 @@ void ObjectAccessor::RemoveOldCorpses() } } -void ObjectAccessor::Update(uint32 /*diff*/) -{ - UpdateDataMapType update_players; - - while (!i_objects.empty()) - { - Object* obj = *i_objects.begin(); - ASSERT(obj && obj->IsInWorld()); - i_objects.erase(i_objects.begin()); - obj->BuildUpdate(update_players); - } - - WorldPacket packet; // here we allocate a std::vector with a size of 0x10000 - for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) - { - iter->second.BuildPacket(&packet); - iter->first->GetSession()->SendPacket(&packet); - packet.clear(); // clean the string - } -} - void ObjectAccessor::UnloadAll() { for (Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr) @@ -475,17 +420,5 @@ template <class T> typename HashMapHolder<T>::MapType HashMapHolder<T>::_objectM template <class T> boost::shared_mutex HashMapHolder<T>::_lock; /// Global definitions for the hashmap storage - template class HashMapHolder<Player>; -template class HashMapHolder<Pet>; -template class HashMapHolder<GameObject>; -template class HashMapHolder<DynamicObject>; -template class HashMapHolder<Creature>; -template class HashMapHolder<Corpse>; - -template Player* ObjectAccessor::GetObjectInWorld<Player>(uint32 mapid, float x, float y, ObjectGuid guid, Player* /*fake*/); -template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float y, ObjectGuid guid, Pet* /*fake*/); -template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, ObjectGuid guid, Creature* /*fake*/); -template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, ObjectGuid guid, Corpse* /*fake*/); -template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, ObjectGuid guid, GameObject* /*fake*/); -template DynamicObject* ObjectAccessor::GetObjectInWorld<DynamicObject>(uint32 mapid, float x, float y, ObjectGuid guid, DynamicObject* /*fake*/); +template class HashMapHolder<Transport>; diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h index 47fc7aa6cef..e4c1ac3aa41 100644 --- a/src/server/game/Globals/ObjectAccessor.h +++ b/src/server/game/Globals/ObjectAccessor.h @@ -30,7 +30,6 @@ #include "UpdateData.h" #include "Object.h" - class Creature; class Corpse; class Unit; @@ -46,6 +45,9 @@ template <class T> class HashMapHolder { public: + static_assert(std::is_same<Player, T>::value + || std::is_same<Transport, T>::value, + "Only Player and Transport can be registered in global HashMapHolder"); typedef std::unordered_map<ObjectGuid, T*> MapType; @@ -100,78 +102,28 @@ class ObjectAccessor return &instance; } - template<class T> static T* GetObjectInOrOutOfWorld(ObjectGuid guid, T* /*typeSpecifier*/) - { - return HashMapHolder<T>::Find(guid); - } - - static Unit* GetObjectInOrOutOfWorld(ObjectGuid guid, Unit* /*typeSpecifier*/) - { - if (guid.IsPlayer()) - return (Unit*)GetObjectInOrOutOfWorld(guid, (Player*)NULL); - - if (guid.IsPet()) - return (Unit*)GetObjectInOrOutOfWorld(guid, (Pet*)NULL); - - return (Unit*)GetObjectInOrOutOfWorld(guid, (Creature*)NULL); - } - - // returns object if is in world - template<class T> static T* GetObjectInWorld(ObjectGuid guid, T* /*typeSpecifier*/) - { - return HashMapHolder<T>::Find(guid); - } - - // Player may be not in world while in ObjectAccessor - static Player* GetObjectInWorld(ObjectGuid guid, Player* /*typeSpecifier*/); - - static Unit* GetObjectInWorld(ObjectGuid guid, Unit* /*typeSpecifier*/) - { - if (guid.IsPlayer()) - return (Unit*)GetObjectInWorld(guid, (Player*)NULL); - - if (guid.IsPet()) - return (Unit*)GetObjectInWorld(guid, (Pet*)NULL); - - return (Unit*)GetObjectInWorld(guid, (Creature*)NULL); - } - - // returns object if is in map - template<class T> static T* GetObjectInMap(ObjectGuid guid, Map* map, T* /*typeSpecifier*/) - { - ASSERT(map); - if (T * obj = GetObjectInWorld(guid, (T*)NULL)) - if (obj->GetMap() == map) - return obj; - return NULL; - } - - template<class T> static T* GetObjectInWorld(uint32 mapid, float x, float y, ObjectGuid guid, T* /*fake*/); - // these functions return objects only if in map of specified object - static WorldObject* GetWorldObject(WorldObject const&, ObjectGuid); - static Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid, uint32 typemask); - static Corpse* GetCorpse(WorldObject const& u, ObjectGuid guid); - static GameObject* GetGameObject(WorldObject const& u, ObjectGuid guid); - static Transport* GetTransport(WorldObject const& u, ObjectGuid guid); - static DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid guid); - static AreaTrigger* GetAreaTrigger(WorldObject const& u, ObjectGuid guid); - static Unit* GetUnit(WorldObject const&, ObjectGuid guid); - static Creature* GetCreature(WorldObject const& u, ObjectGuid guid); - static Pet* GetPet(WorldObject const&, ObjectGuid guid); - static Player* GetPlayer(WorldObject const&, ObjectGuid guid); - static Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid); + static WorldObject* GetWorldObject(WorldObject const&, ObjectGuid const&); + static Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const&, uint32 typemask); + static Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid); + static GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid); + static Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid); + static DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid); + static AreaTrigger* GetAreaTrigger(WorldObject const& u, ObjectGuid const& guid); + static Unit* GetUnit(WorldObject const&, ObjectGuid const& guid); + static Creature* GetCreature(WorldObject const& u, ObjectGuid const& guid); + static Pet* GetPet(WorldObject const&, ObjectGuid const& guid); + static Player* GetPlayer(Map const*, ObjectGuid const& guid); + static Player* GetPlayer(WorldObject const&, ObjectGuid const& guid); + static Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid const&); // these functions return objects if found in whole world // ACCESS LIKE THAT IS NOT THREAD SAFE - static Pet* FindPet(ObjectGuid); - static Player* FindPlayer(ObjectGuid); - static Creature* FindCreature(ObjectGuid); - static Unit* FindUnit(ObjectGuid); + static Player* FindPlayer(ObjectGuid const&); static Player* FindPlayerByName(std::string const& name); // this returns Player even if he is not in world, for example teleporting - static Player* FindConnectedPlayer(ObjectGuid); + static Player* FindConnectedPlayer(ObjectGuid const&); static Player* FindConnectedPlayerByName(std::string const& name); // when using this, you must use the hashmapholder's lock @@ -180,18 +132,6 @@ class ObjectAccessor return HashMapHolder<Player>::GetContainer(); } - // when using this, you must use the hashmapholder's lock - static HashMapHolder<Creature>::MapType const& GetCreatures() - { - return HashMapHolder<Creature>::GetContainer(); - } - - // when using this, you must use the hashmapholder's lock - static HashMapHolder<GameObject>::MapType const& GetGameObjects() - { - return HashMapHolder<GameObject>::GetContainer(); - } - template<class T> static void AddObject(T* object) { HashMapHolder<T>::Insert(object); @@ -205,42 +145,24 @@ class ObjectAccessor static void SaveAllPlayers(); //non-static functions - void AddUpdateObject(Object* obj) - { - std::lock_guard<std::mutex> lock(_objectLock); - i_objects.insert(obj); - } - - void RemoveUpdateObject(Object* obj) - { - std::lock_guard<std::mutex> lock(_objectLock); - i_objects.erase(obj); - } //Thread safe - Corpse* GetCorpseForPlayerGUID(ObjectGuid guid); + Corpse* GetCorpseForPlayerGUID(ObjectGuid const& guid); void RemoveCorpse(Corpse* corpse); void AddCorpse(Corpse* corpse); void AddCorpsesToGrid(GridCoord const& gridpair, GridType& grid, Map* map); - Corpse* ConvertCorpseForPlayer(ObjectGuid player_guid, bool insignia = false); + Corpse* ConvertCorpseForPlayer(ObjectGuid const& player_guid, bool insignia = false); //Thread unsafe - void Update(uint32 diff); void RemoveOldCorpses(); void UnloadAll(); private: - static void _buildChangeObjectForPlayer(WorldObject*, UpdateDataMapType&); - static void _buildPacket(Player*, Object*, UpdateDataMapType&); - void _update(); - typedef std::unordered_map<ObjectGuid, Corpse*> Player2CorpsesMapType; typedef std::unordered_map<Player*, UpdateData>::value_type UpdateDataValueType; - std::set<Object*> i_objects; Player2CorpsesMapType i_player2corpse; - std::mutex _objectLock; boost::shared_mutex _corpseLock; }; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index fda6779c30f..ac87f58af5c 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -239,24 +239,6 @@ bool SpellClickInfo::IsFitToRequirements(Unit const* clicker, Unit const* clicke return true; } -template<> ObjectGuidGenerator<HighGuid::Player>* ObjectMgr::GetGenerator() { return &_playerGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::Creature>* ObjectMgr::GetGenerator() { return &_creatureGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::Pet>* ObjectMgr::GetGenerator() { return &_petGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::Vehicle>* ObjectMgr::GetGenerator() { return &_vehicleGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::Item>* ObjectMgr::GetGenerator() { return &_itemGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::GameObject>* ObjectMgr::GetGenerator() { return &_gameObjectGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::DynamicObject>* ObjectMgr::GetGenerator() { return &_dynamicObjectGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::Corpse>* ObjectMgr::GetGenerator() { return &_corpseGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::LootObject>* ObjectMgr::GetGenerator() { return &_lootObjectGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::AreaTrigger>* ObjectMgr::GetGenerator() { return &_areaTriggerGuidGenerator; } -template<> ObjectGuidGenerator<HighGuid::Transport>* ObjectMgr::GetGenerator() { return &_moTransportGuidGenerator; } - -template<HighGuid type> -ObjectGuidGenerator<type>* ObjectMgr::GetGenerator() -{ - return nullptr; -} - ObjectMgr::ObjectMgr(): _auctionId(1), _equipmentSetGuid(1), @@ -264,6 +246,8 @@ ObjectMgr::ObjectMgr(): _mailId(1), _hiPetNumber(1), _voidItemId(1), + _creatureSpawnId(1), + _gameObjectSpawnId(1), DBCLocaleIndex(LOCALE_enUS) { for (uint8 i = 0; i < MAX_CLASSES; ++i) @@ -490,7 +474,7 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields) creatureTemplate.expansion = fields[17].GetInt16(); creatureTemplate.expansionUnknown = fields[18].GetUInt16(); creatureTemplate.faction = fields[19].GetUInt16(); - creatureTemplate.npcflag = fields[20].GetUInt32(); + creatureTemplate.npcflag = fields[20].GetUInt64(); creatureTemplate.speed_walk = fields[21].GetFloat(); creatureTemplate.speed_run = fields[22].GetFloat(); creatureTemplate.scale = fields[23].GetFloat(); @@ -694,9 +678,9 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) if (cInfo->npcflag != difficultyInfo->npcflag) { - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, `npcflag`: %u) has different `npcflag` in difficulty %u mode (Entry: %u, `npcflag`: %u).", + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, `npcflag`: " UI64FMTD ") has different `npcflag` in difficulty %u mode (Entry: %u, `npcflag`: " UI64FMTD ").", cInfo->Entry, cInfo->npcflag, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->npcflag); - TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `npcflag`=%u WHERE `entry`=%u;", + TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `npcflag`=" UI64FMTD " WHERE `entry`=%u;", cInfo->npcflag, cInfo->DifficultyEntry[diff]); continue; } @@ -1187,7 +1171,7 @@ void ObjectMgr::LoadEquipmentTemplates() uint32 oldMSTime = getMSTime(); // 0 1 2 3 4 - QueryResult result = WorldDatabase.Query("SELECT entry, id, itemEntry1, itemEntry2, itemEntry3 FROM creature_equip_template"); + QueryResult result = WorldDatabase.Query("SELECT CreatureID, ID, ItemID1, ItemID2, ItemID3 FROM creature_equip_template"); if (!result) { @@ -1204,7 +1188,7 @@ void ObjectMgr::LoadEquipmentTemplates() if (!sObjectMgr->GetCreatureTemplate(entry)) { - TC_LOG_ERROR("sql.sql", "Creature template (Entry: %u) does not exist but has a record in `creature_equip_template`", entry); + TC_LOG_ERROR("sql.sql", "Creature template (CreatureID: %u) does not exist but has a record in `creature_equip_template`", entry); continue; } @@ -1230,7 +1214,7 @@ void ObjectMgr::LoadEquipmentTemplates() if (!dbcItem) { - TC_LOG_ERROR("sql.sql", "Unknown item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u and id=%u, forced to 0.", + TC_LOG_ERROR("sql.sql", "Unknown item (ID=%u) in creature_equip_template.ItemID%u for CreatureID = %u and ID=%u, forced to 0.", equipmentInfo.ItemEntry[i], i+1, entry, id); equipmentInfo.ItemEntry[i] = 0; continue; @@ -1246,7 +1230,7 @@ void ObjectMgr::LoadEquipmentTemplates() dbcItem->InventoryType != INVTYPE_THROWN && dbcItem->InventoryType != INVTYPE_RANGEDRIGHT) { - TC_LOG_ERROR("sql.sql", "Item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u and id = %u is not equipable in a hand, forced to 0.", + TC_LOG_ERROR("sql.sql", "Item (ID=%u) in creature_equip_template.ItemID%u for CreatureID = %u and ID = %u is not equipable in a hand, forced to 0.", equipmentInfo.ItemEntry[i], i+1, entry, id); equipmentInfo.ItemEntry[i] = 0; } @@ -1277,7 +1261,7 @@ uint32 ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData co return cinfo->GetRandomValidModelId(); } -void ObjectMgr::ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, const CreatureData* data /*= NULL*/) +void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cinfo, uint64& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data /*= NULL*/) { npcflag = cinfo->npcflag; unit_flags = cinfo->unit_flags; @@ -1759,11 +1743,11 @@ void ObjectMgr::LoadCreatures() data.spawnMask = fields[15].GetUInt32(); int16 gameEvent = fields[16].GetInt8(); uint32 PoolId = fields[17].GetUInt32(); - data.npcflag = fields[18].GetUInt32(); + data.npcflag = fields[18].GetUInt64(); data.unit_flags = fields[19].GetUInt32(); data.dynamicflags = fields[20].GetUInt32(); - data.phaseid = fields[21].GetUInt32(); - data.phaseGroup = fields[22].GetUInt32(); + data.phaseid = fields[21].GetUInt32(); + data.phaseGroup = fields[22].GetUInt32(); MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); if (!mapEntry) @@ -1841,6 +1825,25 @@ void ObjectMgr::LoadCreatures() data.phaseGroup = 0; } + if (data.phaseid) + { + PhaseEntry const* phase = sPhaseStore.LookupEntry(data.phaseid); + if (!phase) + { + TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: " UI64FMTD " Entry: %u) with `phaseid` %u does not exist, set to 0", guid, data.id, data.phaseid); + data.phaseid = 0; + } + } + + if (data.phaseGroup) + { + if (sDB2Manager.GetPhasesForGroup(data.phaseGroup).empty()) + { + TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: " UI64FMTD " Entry: %u) with `phasegroup` %u does not exist, set to 0", guid, data.id, data.phaseGroup); + data.phaseGroup = 0; + } + } + if (sWorld->getBoolConfig(CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA)) { uint32 zoneId = 0; @@ -1903,7 +1906,7 @@ ObjectGuid::LowType ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, fl if (!map) return UI64LIT(0); - ObjectGuid::LowType guid = GetGenerator<HighGuid::GameObject>()->Generate(); + ObjectGuid::LowType guid = GenerateGameObjectSpawnId(); GameObjectData& data = NewGOData(guid); data.id = entry; data.mapid = mapId; @@ -1943,39 +1946,6 @@ ObjectGuid::LowType ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, fl return guid; } -bool ObjectMgr::MoveCreData(ObjectGuid::LowType guid, uint32 mapId, const Position& pos) -{ - CreatureData& data = NewOrExistCreatureData(guid); - if (!data.id) - return false; - - RemoveCreatureFromGrid(guid, &data); - if (data.posX == pos.GetPositionX() && data.posY == pos.GetPositionY() && data.posZ == pos.GetPositionZ()) - return true; - data.posX = pos.GetPositionX(); - data.posY = pos.GetPositionY(); - data.posZ = pos.GetPositionZ(); - data.orientation = pos.GetOrientation(); - AddCreatureToGrid(guid, &data); - - // Spawn if necessary (loaded grids only) - if (Map* map = sMapMgr->CreateBaseMap(mapId)) - { - // We use spawn coords to spawn - if (!map->Instanceable() && map->IsGridLoaded(data.posX, data.posY)) - { - Creature* creature = new Creature(); - if (!creature->LoadCreatureFromDB(guid, map)) - { - TC_LOG_ERROR("misc", "MoveCreData: Cannot add creature guid " UI64FMTD " to map", guid); - delete creature; - return false; - } - } - } - return true; -} - ObjectGuid::LowType ObjectMgr::AddCreData(uint32 entry, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay /*= 0*/) { CreatureTemplate const* cInfo = GetCreatureTemplate(entry); @@ -1984,8 +1954,11 @@ ObjectGuid::LowType ObjectMgr::AddCreData(uint32 entry, uint32 mapId, float x, f uint32 level = cInfo->minlevel == cInfo->maxlevel ? cInfo->minlevel : urand(cInfo->minlevel, cInfo->maxlevel); // Only used for extracting creature base stats CreatureBaseStats const* stats = GetCreatureBaseStats(level, cInfo->unit_class); + Map* map = sMapMgr->CreateBaseMap(mapId); + if (!map) + return UI64LIT(0); - ObjectGuid::LowType guid = GetGenerator<HighGuid::Creature>()->Generate(); + ObjectGuid::LowType guid = GenerateCreatureSpawnId(); CreatureData& data = NewOrExistCreatureData(guid); data.id = entry; data.mapid = mapId; @@ -2010,19 +1983,15 @@ ObjectGuid::LowType ObjectMgr::AddCreData(uint32 entry, uint32 mapId, float x, f AddCreatureToGrid(guid, &data); - // Spawn if necessary (loaded grids only) - if (Map* map = sMapMgr->CreateBaseMap(mapId)) + // We use spawn coords to spawn + if (!map->Instanceable() && !map->IsRemovalGrid(x, y)) { - // We use spawn coords to spawn - if (!map->Instanceable() && !map->IsRemovalGrid(x, y)) + Creature* creature = new Creature(); + if (!creature->LoadCreatureFromDB(guid, map)) { - Creature* creature = new Creature(); - if (!creature->LoadCreatureFromDB(guid, map)) - { - TC_LOG_ERROR("misc", "AddCreature: Cannot add creature entry %u to map", entry); - delete creature; - return UI64LIT(0); - } + TC_LOG_ERROR("misc", "AddCreature: Cannot add creature entry %u to map", entry); + delete creature; + return UI64LIT(0); } } @@ -2134,8 +2103,8 @@ void ObjectMgr::LoadGameobjects() int16 gameEvent = fields[15].GetInt8(); uint32 PoolId = fields[16].GetUInt32(); - data.phaseid = fields[17].GetUInt32(); - data.phaseGroup = fields[18].GetUInt32(); + data.phaseid = fields[17].GetUInt32(); + data.phaseGroup = fields[18].GetUInt32(); if (data.phaseGroup && data.phaseid) { @@ -2143,6 +2112,25 @@ void ObjectMgr::LoadGameobjects() data.phaseGroup = 0; } + if (data.phaseid) + { + PhaseEntry const* phase = sPhaseStore.LookupEntry(data.phaseid); + if (!phase) + { + TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: " UI64FMTD " Entry: %u) with `phaseid` %u does not exist, set to 0", guid, data.id, data.phaseid); + data.phaseid = 0; + } + } + + if (data.phaseGroup) + { + if (sDB2Manager.GetPhasesForGroup(data.phaseGroup).empty()) + { + TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: " UI64FMTD " Entry: %u) with `phaseGroup` %u does not exist, set to 0", guid, data.id, data.phaseGroup); + data.phaseGroup = 0; + } + } + if (std::abs(data.orientation) > 2 * float(M_PI)) { TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: " UI64FMTD " Entry: %u) with abs(`orientation`) > 2*PI (orientation is expressed in radians), normalized.", guid, data.id); @@ -2378,7 +2366,7 @@ void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill, { *disenchantID = 0; *(int32*)requiredDisenchantSkill = -1; - if ((itemTemplate.GetFlags() & (ITEM_PROTO_FLAG_CONJURED | ITEM_PROTO_FLAG_UNK6)) || + if ((itemTemplate.GetFlags() & (ITEM_FLAG_CONJURED | ITEM_FLAG_UNK6)) || itemTemplate.GetBonding() == BIND_QUEST_ITEM || itemTemplate.GetArea() || itemTemplate.GetMap() || itemTemplate.GetMaxStackSize() > 1 || itemTemplate.GetQuality() < ITEM_QUALITY_UNCOMMON || itemTemplate.GetQuality() > ITEM_QUALITY_EPIC || @@ -6263,29 +6251,21 @@ void ObjectMgr::SetHighestGuids() { QueryResult result = CharacterDatabase.Query("SELECT MAX(guid) FROM characters"); if (result) - _playerGuidGenerator.Set((*result)[0].GetUInt64() + 1); - - result = WorldDatabase.Query("SELECT MAX(guid) FROM creature"); - if (result) - _creatureGuidGenerator.Set((*result)[0].GetUInt64() + 1); + GetGuidSequenceGenerator<HighGuid::Player>().Set((*result)[0].GetUInt64() + 1); result = CharacterDatabase.Query("SELECT MAX(guid) FROM item_instance"); if (result) - _itemGuidGenerator.Set((*result)[0].GetUInt64() + 1); + GetGuidSequenceGenerator<HighGuid::Item>().Set((*result)[0].GetUInt64() + 1); // Cleanup other tables from nonexistent guids ( >= _hiItemGuid) - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", _itemGuidGenerator.GetNextAfterMaxUsed()); // One-time query - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", _itemGuidGenerator.GetNextAfterMaxUsed()); // One-time query - CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", _itemGuidGenerator.GetNextAfterMaxUsed()); // One-time query - CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", _itemGuidGenerator.GetNextAfterMaxUsed()); // One-time query - - result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject"); - if (result) - _gameObjectGuidGenerator.Set((*result)[0].GetUInt64() + 1); + CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item >= '%u'", GetGuidSequenceGenerator<HighGuid::Item>().GetNextAfterMaxUsed()); // One-time query + CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid >= '%u'", GetGuidSequenceGenerator<HighGuid::Item>().GetNextAfterMaxUsed()); // One-time query + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE itemguid >= '%u'", GetGuidSequenceGenerator<HighGuid::Item>().GetNextAfterMaxUsed()); // One-time query + CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE item_guid >= '%u'", GetGuidSequenceGenerator<HighGuid::Item>().GetNextAfterMaxUsed()); // One-time query result = WorldDatabase.Query("SELECT MAX(guid) FROM transports"); if (result) - _moTransportGuidGenerator.Set((*result)[0].GetUInt64() + 1); + GetGuidSequenceGenerator<HighGuid::Transport>().Set((*result)[0].GetUInt64() + 1); result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse"); if (result) @@ -6295,10 +6275,6 @@ void ObjectMgr::SetHighestGuids() if (result) _mailId = (*result)[0].GetUInt32()+1; - result = CharacterDatabase.Query("SELECT MAX(corpseGuid) FROM corpse"); - if (result) - _corpseGuidGenerator.Set((*result)[0].GetUInt64() + 1); - result = CharacterDatabase.Query("SELECT MAX(arenateamid) FROM arena_team"); if (result) sArenaTeamMgr->SetNextArenaTeamId((*result)[0].GetUInt32()+1); @@ -6318,6 +6294,14 @@ void ObjectMgr::SetHighestGuids() result = CharacterDatabase.Query("SELECT MAX(itemId) from character_void_storage"); if (result) _voidItemId = (*result)[0].GetUInt64()+1; + + result = WorldDatabase.Query("SELECT MAX(guid) FROM creature"); + if (result) + _creatureSpawnId = (*result)[0].GetUInt64() + 1; + + result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject"); + if (result) + _gameObjectSpawnId = (*result)[0].GetUInt64() + 1; } uint32 ObjectMgr::GenerateAuctionID() @@ -6350,6 +6334,36 @@ uint32 ObjectMgr::GenerateMailID() return _mailId++; } +uint32 ObjectMgr::GeneratePetNumber() +{ + return ++_hiPetNumber; +} + +uint64 ObjectMgr::GenerateVoidStorageItemId() +{ + return ++_voidItemId; +} + +uint64 ObjectMgr::GenerateCreatureSpawnId() +{ + if (_creatureSpawnId >= uint64(0xFFFFFFFFFFFFFFFELL)) + { + TC_LOG_ERROR("misc", "Creature spawn id overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return _creatureSpawnId++; +} + +uint64 ObjectMgr::GenerateGameObjectSpawnId() +{ + if (_gameObjectSpawnId >= uint64(0xFFFFFFFFFFFFFFFELL)) + { + TC_LOG_ERROR("misc", "Creature spawn id overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return _gameObjectSpawnId++; +} + void ObjectMgr::LoadGameObjectLocales() { uint32 oldMSTime = getMSTime(); @@ -6445,6 +6459,22 @@ void ObjectMgr::LoadGameObjectTemplate() { uint32 oldMSTime = getMSTime(); + for (GameObjectsEntry const* db2go : sGameObjectsStore) + { + GameObjectTemplate& go = _gameObjectTemplateStore[db2go->ID]; + go.entry = db2go->ID; + go.type = db2go->Type; + go.displayId = db2go->DisplayID; + go.name = db2go->Name->Str[sWorld->GetDefaultDbcLocale()]; + go.faction = 0; + go.flags = 0; + go.size = db2go->Size; + memset(go.raw.data, 0, sizeof(go.raw.data)); + memcpy(go.raw.data, db2go->Data, std::min(sizeof(db2go->Data), sizeof(go.raw.data))); + go.unkInt32 = 0; + go.ScriptId = 0; + } + // 0 1 2 3 4 5 6 7 8 9 QueryResult result = WorldDatabase.Query("SELECT entry, type, displayId, name, IconName, castBarCaption, unk1, faction, flags, size, " // 10 11 12 13 14 15 16 17 18 19 20 21 22 @@ -6583,7 +6613,7 @@ void ObjectMgr::LoadGameObjectTemplate() { if (got.moTransport.taxiPathID >= sTaxiPathNodesByPath.size() || sTaxiPathNodesByPath[got.moTransport.taxiPathID].empty()) TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist.", - entry, got.type, got.moTransport.taxiPathID, got.moTransport.taxiPathID); + entry, got.type, got.moTransport.taxiPathID, got.moTransport.taxiPathID); } if (uint32 transportMap = got.moTransport.mapID) _transportMaps.insert(transportMap); @@ -6734,77 +6764,6 @@ std::string ObjectMgr::GeneratePetName(uint32 entry) return *(list0.begin()+urand(0, list0.size()-1)) + *(list1.begin()+urand(0, list1.size()-1)); } -uint32 ObjectMgr::GeneratePetNumber() -{ - return ++_hiPetNumber; -} - -uint64 ObjectMgr::GenerateVoidStorageItemId() -{ - return ++_voidItemId; -} - -void ObjectMgr::LoadCorpses() -{ - uint32 oldMSTime = getMSTime(); - - std::unordered_map<uint32, std::list<uint32>> phases; - - // 0 1 - // SELECT Guid, PhaseId FROM corpse_phases - PreparedQueryResult phaseResult = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_PHASES)); - if (phaseResult) - { - do - { - Field* fields = phaseResult->Fetch(); - uint32 guid = fields[0].GetUInt32(); - uint32 phaseId = fields[1].GetUInt32(); - - phases[guid].push_back(phaseId); - - } while (phaseResult->NextRow()); - } - - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, corpseGuid, guid FROM corpse WHERE corpseType <> 0 - PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES)); - if (!result) - { - TC_LOG_INFO("server.loading", ">> Loaded 0 corpses. DB table `corpse` is empty."); - return; - } - - uint32 count = 0; - do - { - Field* fields = result->Fetch(); - uint32 guid = fields[14].GetUInt32(); - CorpseType type = CorpseType(fields[12].GetUInt8()); - if (type >= MAX_CORPSE_TYPE) - { - TC_LOG_ERROR("misc", "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type); - continue; - } - - Corpse* corpse = new Corpse(type); - if (!corpse->LoadCorpseFromDB(guid, fields)) - { - delete corpse; - continue; - } - - for (auto phaseId : phases[guid]) - corpse->SetInPhase(phaseId, false, true); - - sObjectAccessor->AddCorpse(corpse); - ++count; - } - while (result->NextRow()); - - TC_LOG_INFO("server.loading", ">> Loaded %u corpses in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); -} - void ObjectMgr::LoadReputationRewardRate() { uint32 oldMSTime = getMSTime(); @@ -7170,6 +7129,9 @@ void ObjectMgr::LoadQuestPOI() int32 PlayerConditionID = fields[12].GetInt32(); int32 WoDUnk1 = fields[13].GetInt32(); + if (!sObjectMgr->GetQuestTemplate(QuestID)) + TC_LOG_ERROR("sql.sql", "`quest_poi` quest id (%u) Idx1 (%u) does not exist in `quest_template`", QuestID, Idx1); + QuestPOI POI(BlobIndex, ObjectiveIndex, QuestObjectiveID, QuestObjectID, MapID, WorldMapAreaId, Floor, Priority, Flags, WorldEffectID, PlayerConditionID, WoDUnk1); if (QuestID < int32(POIs.size()) && Idx1 < int32(POIs[QuestID].size())) { @@ -8293,7 +8255,7 @@ void ObjectMgr::LoadGossipMenuItems() gMenuItem.OptionText = fields[3].GetString(); gMenuItem.OptionBroadcastTextId = fields[4].GetUInt32(); gMenuItem.OptionType = fields[5].GetUInt8(); - gMenuItem.OptionNpcflag = fields[6].GetUInt32(); + gMenuItem.OptionNpcflag = fields[6].GetUInt64(); gMenuItem.ActionMenuId = fields[7].GetUInt32(); gMenuItem.ActionPoiId = fields[8].GetUInt32(); gMenuItem.BoxCoded = fields[9].GetBool(); @@ -9028,7 +8990,7 @@ VehicleAccessoryList const* ObjectMgr::GetVehicleAccessoryList(Vehicle* veh) con if (Creature* cre = veh->GetBase()->ToCreature()) { // Give preference to GUID-based accessories - VehicleAccessoryContainer::const_iterator itr = _vehicleAccessoryStore.find(cre->GetDBTableGUIDLow()); + VehicleAccessoryContainer::const_iterator itr = _vehicleAccessoryStore.find(cre->GetSpawnId()); if (itr != _vehicleAccessoryStore.end()) return &itr->second; } @@ -9133,6 +9095,81 @@ void ObjectMgr::LoadRaceAndClassExpansionRequirements() TC_LOG_INFO("server.loading", ">> Loaded 0 class expansion requirements. DB table `class_expansion_requirement` is empty."); } +void ObjectMgr::LoadCharacterTemplates() +{ + uint32 oldMSTime = getMSTime(); + _characterTemplateStore.clear(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TEMPLATES); + PreparedQueryResult templates = CharacterDatabase.Query(stmt); + + if (!templates) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 character templates. DB table `character_template` is empty."); + return; + } + + PreparedQueryResult classes; + uint32 count = 0; + + do + { + Field* fields = templates->Fetch(); + + uint32 templateSetId = fields[0].GetUInt32(); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TEMPLATE_CLASSES); + stmt->setUInt32(0, templateSetId); + classes = CharacterDatabase.Query(stmt); + + if (classes) + { + CharacterTemplate templ; + templ.TemplateSetId = templateSetId; + templ.Name = fields[1].GetString(); + templ.Description = fields[2].GetString(); + templ.Level = fields[3].GetUInt8(); + + do + { + fields = classes->Fetch(); + + uint8 factionGroup = fields[0].GetUInt8(); + uint8 classID = fields[1].GetUInt8(); + + if (!((factionGroup & (FACTION_MASK_PLAYER | FACTION_MASK_ALLIANCE)) == (FACTION_MASK_PLAYER | FACTION_MASK_ALLIANCE)) && + !((factionGroup & (FACTION_MASK_PLAYER | FACTION_MASK_HORDE)) == (FACTION_MASK_PLAYER | FACTION_MASK_HORDE))) + { + TC_LOG_ERROR("sql.sql", "Faction group %u defined for character template %u in `character_template_class` is invalid. Skipped.", factionGroup, templateSetId); + continue; + } + + ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(classID); + if (!classEntry) + { + TC_LOG_ERROR("sql.sql", "Class %u defined for character template %u in `character_template_class` does not exists, skipped.", classID, templateSetId); + continue; + } + + templ.Classes.emplace_back(factionGroup, classID); + + } while (classes->NextRow()); + + if (!templ.Classes.empty()) + { + _characterTemplateStore[templateSetId] = templ; + ++count; + } + } + else + { + TC_LOG_ERROR("sql.sql", "Character template %u does not have any classes defined in `character_template_class`. Skipped.", templateSetId); + continue; + } + } while (templates->NextRow()); + TC_LOG_INFO("server.loading", ">> Loaded %u character templates in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); +} + void ObjectMgr::LoadRealmNames() { uint32 oldMSTime = getMSTime(); @@ -9227,4 +9264,4 @@ void ObjectMgr::LoadCreatureQuestItems() while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u creature quest items in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); -}
\ No newline at end of file +} diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index feee679a87b..dc26e30773c 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -36,24 +36,20 @@ #include "ObjectAccessor.h" #include "ObjectDefines.h" #include "VehicleDefines.h" +#include "ConditionMgr.h" +#include "DB2Stores.h" #include <string> #include <map> #include <limits> -#include "ConditionMgr.h" #include <functional> -#include "DB2Stores.h" +#include <memory> class Item; struct AccessRequirement; struct PlayerInfo; struct PlayerLevelInfo; -// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif struct PageText { @@ -81,12 +77,7 @@ private: uint8 _summonGroup; ///< Summon's group id }; -// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif // DB scripting commands enum ScriptCommands @@ -519,7 +510,7 @@ struct GossipMenuItems std::string OptionText; uint32 OptionBroadcastTextId; uint32 OptionType; - uint32 OptionNpcflag; + uint64 OptionNpcflag; uint32 ActionMenuId; uint32 ActionPoiId; bool BoxCoded; @@ -606,6 +597,26 @@ typedef std::unordered_map<uint32, TrainerSpellData> CacheTrainerSpellContainer; typedef std::unordered_map<uint8, uint8> ExpansionRequirementContainer; typedef std::unordered_map<uint32, std::string> RealmNameContainer; +struct CharcterTemplateClass +{ + CharcterTemplateClass(uint8 factionGroup, uint8 classID) : + FactionGroup(factionGroup), ClassID(classID) { } + + uint8 FactionGroup; + uint8 ClassID; +}; + +struct CharacterTemplate +{ + uint32 TemplateSetId; + std::vector<CharcterTemplateClass> Classes; + std::string Name; + std::string Description; + uint8 Level; +}; + +typedef std::unordered_map<uint32, CharacterTemplate> CharacterTemplateContainer; + enum SkillRangeType { SKILL_RANGE_LANGUAGE, // 300..300 @@ -717,7 +728,7 @@ class ObjectMgr CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId); CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID); static uint32 ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = NULL); - static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = NULL); + static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint64& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = NULL); EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id); CreatureAddon const* GetCreatureAddon(ObjectGuid::LowType lowguid); GameObjectAddon const* GetGameObjectAddon(ObjectGuid::LowType lowguid); @@ -1005,7 +1016,6 @@ class ObjectMgr void LoadExplorationBaseXP(); void LoadPetNames(); void LoadPetNumber(); - void LoadCorpses(); void LoadFishingBaseSkillLevel(); void LoadReputationRewardRate(); @@ -1046,13 +1056,21 @@ class ObjectMgr CreatureBaseStats const* GetCreatureBaseStats(uint8 level, uint8 unitClass); void SetHighestGuids(); + template<HighGuid type> - ObjectGuidGenerator<type>* GetGenerator(); + inline ObjectGuidGeneratorBase& GetGenerator() + { + static_assert(ObjectGuidTraits<type>::Global || ObjectGuidTraits<type>::RealmSpecific, "Only global guid can be generated in ObjectMgr context"); + return GetGuidSequenceGenerator<type>(); + } + uint32 GenerateAuctionID(); uint64 GenerateEquipmentSetGuid(); uint32 GenerateMailID(); uint32 GeneratePetNumber(); uint64 GenerateVoidStorageItemId(); + uint64 GenerateCreatureSpawnId(); + uint64 GenerateGameObjectSpawnId(); typedef std::multimap<int32, uint32> ExclusiveQuestGroups; typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> ExclusiveQuestGroupsBounds; @@ -1188,7 +1206,6 @@ class ObjectMgr void RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectData const* data); ObjectGuid::LowType AddGOData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0, float rotation0 = 0, float rotation1 = 0, float rotation2 = 0, float rotation3 = 0); ObjectGuid::LowType AddCreData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0); - bool MoveCreData(ObjectGuid::LowType guid, uint32 map, const Position& pos); // reserved names void LoadReservedPlayersNames(); @@ -1297,6 +1314,7 @@ class ObjectMgr bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId) != 0; } void LoadRaceAndClassExpansionRequirements(); + void LoadCharacterTemplates(); void LoadRealmNames(); std::string GetRealmName(uint32 realm) const; @@ -1319,6 +1337,16 @@ class ObjectMgr return EXPANSION_CLASSIC; } + CharacterTemplateContainer const& GetCharacterTemplates() const { return _characterTemplateStore; } + CharacterTemplate const* GetCharacterTemplate(uint32 id) const + { + auto itr = _characterTemplateStore.find(id); + if (itr != _characterTemplateStore.end()) + return &itr->second; + + return nullptr; + } + private: // first free id for selected id type uint32 _auctionId; @@ -1327,19 +1355,21 @@ class ObjectMgr uint32 _mailId; uint32 _hiPetNumber; uint64 _voidItemId; + uint64 _creatureSpawnId; + uint64 _gameObjectSpawnId; // first free low guid for selected guid type - ObjectGuidGenerator<HighGuid::Player> _playerGuidGenerator; - ObjectGuidGenerator<HighGuid::Creature> _creatureGuidGenerator; - ObjectGuidGenerator<HighGuid::Pet> _petGuidGenerator; - ObjectGuidGenerator<HighGuid::Vehicle> _vehicleGuidGenerator; - ObjectGuidGenerator<HighGuid::Item> _itemGuidGenerator; - ObjectGuidGenerator<HighGuid::GameObject> _gameObjectGuidGenerator; - ObjectGuidGenerator<HighGuid::DynamicObject> _dynamicObjectGuidGenerator; - ObjectGuidGenerator<HighGuid::Corpse> _corpseGuidGenerator; - ObjectGuidGenerator<HighGuid::LootObject> _lootObjectGuidGenerator; - ObjectGuidGenerator<HighGuid::AreaTrigger> _areaTriggerGuidGenerator; - ObjectGuidGenerator<HighGuid::Transport> _moTransportGuidGenerator; + template<HighGuid high> + inline ObjectGuidGeneratorBase& GetGuidSequenceGenerator() + { + auto itr = _guidGenerators.find(high); + if (itr == _guidGenerators.end()) + itr = _guidGenerators.insert(std::make_pair(high, std::unique_ptr<ObjectGuidGenerator<high>>(new ObjectGuidGenerator<high>()))).first; + + return *itr->second; + } + + std::map<HighGuid, std::unique_ptr<ObjectGuidGeneratorBase>> _guidGenerators; QuestMap _questTemplates; @@ -1467,6 +1497,8 @@ class ObjectMgr ExpansionRequirementContainer _classExpansionRequirementStore; RealmNameContainer _realmNameStore; + CharacterTemplateContainer _characterTemplateStore; + enum CreatureLinkedRespawnType { CREATURE_TO_CREATURE, diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h index 4f3e774ea56..da25e89c423 100644 --- a/src/server/game/Grids/GridDefines.h +++ b/src/server/game/Grids/GridDefines.h @@ -59,6 +59,7 @@ class AreaTrigger; // Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case) typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes; typedef TYPELIST_5(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/, AreaTrigger) AllGridObjectTypes; +typedef TYPELIST_6(Creature, GameObject, DynamicObject, Pet, Corpse, AreaTrigger) AllMapStoredObjectTypes; typedef GridRefManager<Corpse> CorpseMapType; typedef GridRefManager<Creature> CreatureMapType; diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 0936f8ff753..8a5386684bb 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -742,7 +742,7 @@ namespace Trinity GameObjectWithDbGUIDCheck(WorldObject const& /*obj*/, ObjectGuid::LowType db_guid) : i_db_guid(db_guid) { } bool operator()(GameObject const* go) const { - return go->GetDBTableGUIDLow() == i_db_guid; + return go->GetSpawnId() == i_db_guid; } private: ObjectGuid::LowType i_db_guid; @@ -855,7 +855,7 @@ namespace Trinity CreatureWithDbGUIDCheck(WorldObject const* /*obj*/, ObjectGuid::LowType lowguid) : i_lowguid(lowguid) { } bool operator()(Creature* u) { - return u->GetDBTableGUIDLow() == i_lowguid; + return u->GetSpawnId() == i_lowguid; } private: ObjectGuid::LowType i_lowguid; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index d7d08508230..f359e1eff57 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -960,7 +960,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) //roll for over-threshold item if it's one-player loot if (item->GetQuality() >= uint32(m_lootThreshold)) { - ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>()->Generate()); + ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().Generate()); Roll* r = new Roll(newitemGUID, *i); //a vector is filled with only near party members @@ -1044,7 +1044,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) continue; } - ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>()->Generate()); + ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().Generate()); Roll* r = new Roll(newitemGUID, *i); //a vector is filled with only near party members @@ -1105,7 +1105,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) //roll for over-threshold item if it's one-player loot if (item->GetQuality() >= uint32(m_lootThreshold)) { - ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>()->Generate()); + ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().Generate()); Roll* r = new Roll(newitemGUID, *i); for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) @@ -1136,7 +1136,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) if (item->DisenchantID && m_maxEnchantingLevel >= item->RequiredDisenchantSkill) r->rollVoteMask |= ROLL_FLAG_TYPE_DISENCHANT; - if (item->GetFlags2() & ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED) + if (item->GetFlags2() & ITEM_FLAG2_NEED_ROLL_DISABLED) r->rollVoteMask &= ~ROLL_FLAG_TYPE_NEED; loot->items[itemSlot].is_blocked = true; @@ -1180,7 +1180,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) continue; item = sObjectMgr->GetItemTemplate(i->itemid); - ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>()->Generate()); + ObjectGuid newitemGUID = ObjectGuid::Create<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().Generate()); Roll* r = new Roll(newitemGUID, *i); for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index d838a01cee9..c5812999490 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -190,16 +190,16 @@ void Guild::BankEventLogEntry::WritePacket(WorldPackets::Guild:: GuildBankLogQue bankLogEntry.EntryType = int8(m_eventType); if (hasStack) - bankLogEntry.Count.Set(int32(m_itemStackCount)); + bankLogEntry.Count = int32(m_itemStackCount); if (IsMoneyEvent()) - bankLogEntry.Money.Set(uint64(m_itemOrMoney)); + bankLogEntry.Money = uint64(m_itemOrMoney); if (hasItem) - bankLogEntry.ItemID.Set(int32(m_itemOrMoney)); + bankLogEntry.ItemID = int32(m_itemOrMoney); if (itemMoved) - bankLogEntry.OtherTab.Set(int8(m_destTabId)); + bankLogEntry.OtherTab = int8(m_destTabId); packet.Entry.push_back(bankLogEntry); } @@ -236,7 +236,7 @@ void Guild::NewsLogEntry::WritePacket(WorldPackets::Guild::GuildNews& newsPacket { WorldPackets::Item::ItemInstance itemInstance; itemInstance.ItemID = GetValue(); - newsEvent.Item.Set(itemInstance); + newsEvent.Item = itemInstance; } newsPacket.NewsEvents.push_back(newsEvent); @@ -1313,25 +1313,25 @@ void Guild::SendQueryResponse(WorldSession* session) { WorldPackets::Guild::QueryGuildInfoResponse response; response.GuildGuid = GetGUID(); - response.Info.HasValue = true; + response.Info = boost::in_place(); - response.Info.Value.GuildGUID = GetGUID(); - response.Info.Value.VirtualRealmAddress = GetVirtualRealmAddress(); + response.Info->GuildGUID = GetGUID(); + response.Info->VirtualRealmAddress = GetVirtualRealmAddress(); - response.Info.Value.EmblemStyle = m_emblemInfo.GetStyle(); - response.Info.Value.EmblemColor = m_emblemInfo.GetColor(); - response.Info.Value.BorderStyle = m_emblemInfo.GetBorderStyle(); - response.Info.Value.BorderColor = m_emblemInfo.GetBorderColor(); - response.Info.Value.BackgroundColor = m_emblemInfo.GetBackgroundColor(); + response.Info->EmblemStyle = m_emblemInfo.GetStyle(); + response.Info->EmblemColor = m_emblemInfo.GetColor(); + response.Info->BorderStyle = m_emblemInfo.GetBorderStyle(); + response.Info->BorderColor = m_emblemInfo.GetBorderColor(); + response.Info->BackgroundColor = m_emblemInfo.GetBackgroundColor(); for (uint8 i = 0; i < _GetRanksSize(); ++i) { WorldPackets::Guild::QueryGuildInfoResponse::GuildInfo::GuildInfoRank info (m_ranks[i].GetId(), i, m_ranks[i].GetName()); - response.Info.Value.Ranks.insert(info); + response.Info->Ranks.insert(info); } - response.Info.Value.GuildName = m_name; + response.Info->GuildName = m_name; session->SendPacket(response.Write()); TC_LOG_DEBUG("guild", "SMSG_GUILD_QUERY_RESPONSE [%s]", session->GetPlayerInfo().c_str()); diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 0d9f292c4c2..88f45056187 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -174,7 +174,7 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell } if (sAuctionMgr->GetAItem(item->GetGUID().GetCounter()) || !item->CanBeTraded() || item->IsNotEmptyBag() || - item->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || + item->GetTemplate()->GetFlags() & ITEM_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || item->GetCount() < packetItem.UseCount) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp index e353279ad57..66a31ce0bf2 100644 --- a/src/server/game/Handlers/AuthHandler.cpp +++ b/src/server/game/Handlers/AuthHandler.cpp @@ -24,23 +24,33 @@ void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { WorldPackets::Auth::AuthResponse response; - response.SuccessInfo.HasValue = code == AUTH_OK; response.Result = code; - response.WaitInfo.HasValue = queued; - response.WaitInfo.Value.WaitCount = queuePos; + + if (queued) + { + response.WaitInfo = boost::in_place(); + response.WaitInfo->WaitCount = queuePos; + } + if (code == AUTH_OK) { - response.SuccessInfo.Value.AccountExpansionLevel = GetExpansion(); - response.SuccessInfo.Value.ActiveExpansionLevel = GetExpansion(); - response.SuccessInfo.Value.VirtualRealmAddress = GetVirtualRealmAddress(); + response.SuccessInfo = boost::in_place(); + + response.SuccessInfo->AccountExpansionLevel = GetExpansion(); + response.SuccessInfo->ActiveExpansionLevel = GetExpansion(); + response.SuccessInfo->VirtualRealmAddress = GetVirtualRealmAddress(); std::string realmName = sObjectMgr->GetRealmName(realmHandle.Index); // Send current home realm. Also there is no need to send it later in realm queries. - response.SuccessInfo.Value.VirtualRealms.emplace_back(GetVirtualRealmAddress(), true, false, realmName, realmName); + response.SuccessInfo->VirtualRealms.emplace_back(GetVirtualRealmAddress(), true, false, realmName, realmName); + + if (HasPermission(rbac::RBAC_PERM_USE_CHARACTER_TEMPLATES)) + for (auto& templ : sObjectMgr->GetCharacterTemplates()) + response.SuccessInfo->Templates.emplace_back(templ.second); - response.SuccessInfo.Value.AvailableClasses = &sObjectMgr->GetClassExpansionRequirements(); - response.SuccessInfo.Value.AvailableRaces = &sObjectMgr->GetRaceExpansionRequirements(); + response.SuccessInfo->AvailableClasses = &sObjectMgr->GetClassExpansionRequirements(); + response.SuccessInfo->AvailableRaces = &sObjectMgr->GetRaceExpansionRequirements(); } SendPacket(response.Write()); @@ -51,16 +61,11 @@ void WorldSession::SendAuthWaitQue(uint32 position) WorldPackets::Auth::AuthResponse response; if (position == 0) - { response.Result = AUTH_OK; - response.SuccessInfo.HasValue = false; - response.WaitInfo.HasValue = false; - } else { - response.WaitInfo.HasValue = true; - response.SuccessInfo.HasValue = false; - response.WaitInfo.Value.WaitCount = position; + response.WaitInfo = boost::in_place(); + response.WaitInfo->WaitCount = position; response.Result = AUTH_WAIT_QUEUE; } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index bcad74d50fd..56d865e5d06 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -236,6 +236,18 @@ bool LoginQueryHolder::Initialize() stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CURRENCY, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON, stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS, stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS, stmt); + return res; } @@ -671,7 +683,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac Player newChar(this); newChar.GetMotionMaster()->Initialize(); - if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>()->Generate(), createInfo)) + if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo)) { // Player not create (race/class/etc problem?) newChar.CleanupsBeforeDelete(); @@ -705,6 +717,25 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, WorldPac LoginDatabase.CommitTransaction(trans); + if (createInfo->TemplateSet) + { + if (HasPermission(rbac::RBAC_PERM_USE_CHARACTER_TEMPLATES)) + { + if (CharacterTemplate const* charTemplate = sObjectMgr->GetCharacterTemplate(*createInfo->TemplateSet)) + { + if (charTemplate->Level != 1) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_LEVEL); + stmt->setUInt8(0, uint8(charTemplate->Level)); + stmt->setUInt64(1, newChar.GetGUID().GetCounter()); + CharacterDatabase.Execute(stmt); + } + } + } + else + TC_LOG_WARN("cheat", "Account: %u (IP: %s) tried to use a character template without given permission. Possible cheating attempt.", GetAccountId(), GetRemoteAddress().c_str()); + } + SendCharCreate(CHAR_CREATE_SUCCESS); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Create Character: %s %s", GetAccountId(), GetRemoteAddress().c_str(), createInfo->Name.c_str(), newChar.GetGUID().ToString().c_str()); @@ -829,6 +860,8 @@ void WorldSession::HandleContinuePlayerLogin() return; } + SendPacket(WorldPackets::Auth::ResumeComms(CONNECTION_TYPE_INSTANCE).Write()); + _charLoginCallback = CharacterDatabase.DelayQueryHolder(holder); } @@ -1114,20 +1147,20 @@ void WorldSession::SendFeatureSystemStatus() features.VoiceEnabled = false; features.BrowserEnabled = false; // Has to be false, otherwise client will crash if "Customer Support" is opened - features.EuropaTicketSystemStatus.HasValue = true; - features.EuropaTicketSystemStatus.Value.ThrottleState.MaxTries = 10; - features.EuropaTicketSystemStatus.Value.ThrottleState.PerMilliseconds = 60000; - features.EuropaTicketSystemStatus.Value.ThrottleState.TryCount = 1; - features.EuropaTicketSystemStatus.Value.ThrottleState.LastResetTimeBeforeNow = 111111; + features.EuropaTicketSystemStatus = boost::in_place(); + features.EuropaTicketSystemStatus->ThrottleState.MaxTries = 10; + features.EuropaTicketSystemStatus->ThrottleState.PerMilliseconds = 60000; + features.EuropaTicketSystemStatus->ThrottleState.TryCount = 1; + features.EuropaTicketSystemStatus->ThrottleState.LastResetTimeBeforeNow = 111111; features.ComplaintStatus = 0; features.TutorialsEnabled = true; features.UnkBit90 = true; /// END OF DUMMY VALUES - features.EuropaTicketSystemStatus.Value.TicketsEnabled = sWorld->getBoolConfig(CONFIG_SUPPORT_TICKETS_ENABLED); - features.EuropaTicketSystemStatus.Value.BugsEnabled = sWorld->getBoolConfig(CONFIG_SUPPORT_BUGS_ENABLED); - features.EuropaTicketSystemStatus.Value.ComplaintsEnabled = sWorld->getBoolConfig(CONFIG_SUPPORT_COMPLAINTS_ENABLED); - features.EuropaTicketSystemStatus.Value.SuggestionsEnabled = sWorld->getBoolConfig(CONFIG_SUPPORT_SUGGESTIONS_ENABLED); + features.EuropaTicketSystemStatus->TicketsEnabled = sWorld->getBoolConfig(CONFIG_SUPPORT_TICKETS_ENABLED); + features.EuropaTicketSystemStatus->BugsEnabled = sWorld->getBoolConfig(CONFIG_SUPPORT_BUGS_ENABLED); + features.EuropaTicketSystemStatus->ComplaintsEnabled = sWorld->getBoolConfig(CONFIG_SUPPORT_COMPLAINTS_ENABLED); + features.EuropaTicketSystemStatus->SuggestionsEnabled = sWorld->getBoolConfig(CONFIG_SUPPORT_SUGGESTIONS_ENABLED); features.CharUndeleteEnabled = sWorld->getBoolConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_ENABLED); features.BpayStoreEnabled = sWorld->getBoolConfig(CONFIG_FEATURE_SYSTEM_BPAY_STORE_ENABLED); @@ -1135,15 +1168,14 @@ void WorldSession::SendFeatureSystemStatus() SendPacket(features.Write()); } -void WorldSession::HandleSetFactionAtWar(WorldPacket& recvData) +void WorldSession::HandleSetFactionAtWar(WorldPackets::Character::SetFactionAtWar& packet) { - uint32 repListID; - uint8 flag; - - recvData >> repListID; - recvData >> flag; + GetPlayer()->GetReputationMgr().SetAtWar(packet.FactionIndex, true); +} - GetPlayer()->GetReputationMgr().SetAtWar(repListID, flag != 0); +void WorldSession::HandleSetFactionNotAtWar(WorldPackets::Character::SetFactionNotAtWar& packet) +{ + GetPlayer()->GetReputationMgr().SetAtWar(packet.FactionIndex, false); } //I think this function is never used :/ I dunno, but i guess this opcode not exists @@ -1184,22 +1216,14 @@ void WorldSession::HandleTutorialFlag(WorldPackets::Misc::TutorialSetFlag& packe } } -void WorldSession::HandleSetWatchedFactionOpcode(WorldPacket& recvData) +void WorldSession::HandleSetWatchedFactionOpcode(WorldPackets::Character::SetWatchedFaction& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_SET_WATCHED_FACTION"); - uint32 fact; - recvData >> fact; - GetPlayer()->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fact); + GetPlayer()->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, packet.FactionIndex); } -void WorldSession::HandleSetFactionInactiveOpcode(WorldPacket& recvData) +void WorldSession::HandleSetFactionInactiveOpcode(WorldPackets::Character::SetFactionInactive& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_SET_FACTION_INACTIVE"); - uint32 replistid; - uint8 inactive; - recvData >> replistid >> inactive; - - _player->GetReputationMgr().SetInactive(replistid, inactive != 0); + _player->GetReputationMgr().SetInactive(packet.Index, packet.State); } void WorldSession::HandleRequestForcedReactionsOpcode(WorldPackets::Reputation::RequestForcedReactions& /*requestForcedReactions*/) @@ -1391,24 +1415,28 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recvData) void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance& packet) { - TC_LOG_DEBUG("network", "CMSG_ALTER_APPEARANCE"); - BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(packet.NewHairStyle); - if (!bs_hair || bs_hair->Type != 0 || bs_hair->Race != _player->getRace() || bs_hair->Sex != _player->getGender()) return; BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(packet.NewFacialHair); - if (!bs_facialHair || bs_facialHair->Type != 2 || bs_facialHair->Race != _player->getRace() || bs_facialHair->Sex != _player->getGender()) return; BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(packet.NewSkinColor); - if (bs_skinColor && (bs_skinColor->Type != 3 || bs_skinColor->Race != _player->getRace() || bs_skinColor->Sex != _player->getGender())) return; - if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->getGender(), bs_hair->ID, packet.NewHairColor, uint8(_player->GetUInt32Value(PLAYER_FLAGS) >> 8), bs_facialHair->ID, bs_skinColor ? bs_skinColor->ID : 0)) + BarberShopStyleEntry const* bs_face = sBarberShopStyleStore.LookupEntry(packet.NewFace); + if (bs_face && (bs_face->Type != 4 || bs_face->Race != _player->getRace() || bs_face->Sex != _player->getGender())) + return; + + if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->getGender(), + bs_hair->Data, + packet.NewHairColor, + bs_face ? bs_face->Data : _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID), + bs_facialHair->Data, + bs_skinColor ? bs_skinColor->Data : _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID))) return; GameObject* go = _player->FindNearestGameObjectOfType(GAMEOBJECT_TYPE_BARBER_CHAIR, 5.0f); @@ -1424,7 +1452,7 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance return; } - uint32 cost = _player->GetBarberShopCost(bs_hair->Data, packet.NewHairColor, bs_facialHair->Data, bs_skinColor); + uint32 cost = _player->GetBarberShopCost(bs_hair, packet.NewHairColor, bs_facialHair, bs_skinColor, bs_face); // 0 - ok // 1, 3 - not enough money @@ -1445,6 +1473,8 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance _player->SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE, uint8(bs_facialHair->Data)); if (bs_skinColor) _player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID, uint8(bs_skinColor->Data)); + if (bs_face) + _player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID, uint8(bs_face->Data)); _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); @@ -1603,8 +1633,6 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World void WorldSession::HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipmentSet& packet) { - TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_SAVE"); - if (packet.Set.SetID >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount return; @@ -1635,15 +1663,11 @@ void WorldSession::HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipm void WorldSession::HandleDeleteEquipmentSet(WorldPackets::EquipmentSet::DeleteEquipmentSet& packet) { - TC_LOG_DEBUG("network", "CMSG_DELETE_EQUIPMENT_SET"); - _player->DeleteEquipmentSet(packet.ID); } void WorldSession::HandleUseEquipmentSet(WorldPackets::EquipmentSet::UseEquipmentSet& packet) { - TC_LOG_DEBUG("network", "CMSG_USE_EQUIPMENT_SET"); - ObjectGuid ignoredItemGuid; ignoredItemGuid.SetRawValue(0, 1); @@ -1840,45 +1864,45 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res /// Customize { - if (factionChangeInfo->SkinID.HasValue) + if (factionChangeInfo->SkinID) { playerBytes &= ~uint32(0xFF); - playerBytes |= factionChangeInfo->SkinID.Value; + playerBytes |= *factionChangeInfo->SkinID; } else - factionChangeInfo->SkinID.Set(uint8(playerBytes & 0xFF)); + factionChangeInfo->SkinID = uint8(playerBytes & 0xFF); - if (factionChangeInfo->FaceID.HasValue) + if (factionChangeInfo->FaceID) { playerBytes &= ~(uint32(0xFF) << 8); - playerBytes |= uint32(factionChangeInfo->FaceID.Value) << 8; + playerBytes |= uint32(*factionChangeInfo->FaceID) << 8; } else - factionChangeInfo->FaceID.Set(uint8((playerBytes2 >> 8) & 0xFF)); + factionChangeInfo->FaceID = uint8((playerBytes2 >> 8) & 0xFF); - if (factionChangeInfo->HairStyleID.HasValue) + if (factionChangeInfo->HairStyleID) { playerBytes &= ~(uint32(0xFF) << 16); - playerBytes |= uint32(factionChangeInfo->HairStyleID.Value) << 16; + playerBytes |= uint32(*factionChangeInfo->HairStyleID) << 16; } else - factionChangeInfo->HairStyleID.Set(uint8((playerBytes2 >> 16) & 0xFF)); + factionChangeInfo->HairStyleID = uint8((playerBytes2 >> 16) & 0xFF); - if (factionChangeInfo->HairColorID.HasValue) + if (factionChangeInfo->HairColorID) { playerBytes &= ~(uint32(0xFF) << 24); - playerBytes |= uint32(factionChangeInfo->HairColorID.Value) << 24; + playerBytes |= uint32(*factionChangeInfo->HairColorID) << 24; } else - factionChangeInfo->HairColorID.Set(uint8((playerBytes2 >> 24) & 0xFF)); + factionChangeInfo->HairColorID = uint8((playerBytes2 >> 24) & 0xFF); - if (factionChangeInfo->FacialHairStyleID.HasValue) + if (factionChangeInfo->FacialHairStyleID) { playerBytes2 &= ~0xFF; - playerBytes2 |= factionChangeInfo->FacialHairStyleID.Value; + playerBytes2 |= *factionChangeInfo->FacialHairStyleID; } else - factionChangeInfo->FacialHairStyleID.Set(uint8(playerBytes2 & 0xFF)); + factionChangeInfo->FacialHairStyleID = int8(playerBytes2 & 0xFF); stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_PLAYERBYTES); stmt->setUInt8(0, factionChangeInfo->SexID); @@ -2535,7 +2559,7 @@ void WorldSession::SendCharRename(ResponseCodes result, WorldPackets::Character: packet.Result = result; packet.Name = renameInfo->NewName; if (result == RESPONSE_SUCCESS) - packet.Guid.Set(renameInfo->Guid); + packet.Guid = renameInfo->Guid; SendPacket(packet.Write()); } @@ -2571,15 +2595,15 @@ void WorldSession::SendCharFactionChange(ResponseCodes result, WorldPackets::Cha if (result == RESPONSE_SUCCESS) { - packet.Display.HasValue = true; - packet.Display.Value.Name = factionChangeInfo->Name; - packet.Display.Value.SexID = factionChangeInfo->SexID; - packet.Display.Value.SkinID = factionChangeInfo->SkinID.Value; - packet.Display.Value.HairColorID = factionChangeInfo->HairColorID.Value; - packet.Display.Value.HairStyleID = factionChangeInfo->HairStyleID.Value; - packet.Display.Value.FacialHairStyleID = factionChangeInfo->FacialHairStyleID.Value; - packet.Display.Value.FaceID = factionChangeInfo->FaceID.Value; - packet.Display.Value.RaceID = factionChangeInfo->RaceID; + packet.Display = boost::in_place(); + packet.Display->Name = factionChangeInfo->Name; + packet.Display->SexID = factionChangeInfo->SexID; + packet.Display->SkinID = *factionChangeInfo->SkinID; + packet.Display->HairColorID = *factionChangeInfo->HairColorID; + packet.Display->HairStyleID = *factionChangeInfo->HairStyleID; + packet.Display->FacialHairStyleID = *factionChangeInfo->FacialHairStyleID; + packet.Display->FaceID = *factionChangeInfo->FaceID; + packet.Display->RaceID = factionChangeInfo->RaceID; } SendPacket(packet.Write()); diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index 5507887625b..b5550c2c073 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -234,14 +234,14 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg, if (!normalizePlayerName(extName.Name)) { - SendPlayerNotFoundNotice(target); + SendChatPlayerNotfoundNotice(target); break; } Player* receiver = ObjectAccessor::FindConnectedPlayerByName(extName.Name); if (!receiver || (lang != LANG_ADDON && !receiver->isAcceptWhispers() && receiver->GetSession()->HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS) && !receiver->IsInWhisperWhiteList(sender->GetGUID()))) { - SendPlayerNotFoundNotice(target); + SendChatPlayerNotfoundNotice(target); return; } if (!sender->IsGameMaster() && sender->getLevel() < sWorld->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ) && !receiver->IsInWhisperWhiteList(sender->GetGUID())) @@ -252,7 +252,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg, if (GetPlayer()->GetTeam() != receiver->GetTeam() && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT) && !receiver->IsInWhisperWhiteList(sender->GetGUID())) { - SendPlayerNotFoundNotice(target); + SendChatPlayerNotfoundNotice(target); return; } @@ -641,7 +641,6 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData) { ObjectGuid guid; uint8 unk; - //TC_LOG_DEBUG("network", "WORLD: Received CMSG_CHAT_IGNORED"); recvData >> unk; // probably related to spam reporting guid[5] = recvData.ReadBit(); @@ -671,11 +670,9 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData) player->SendDirectMessage(packet.Write()); } -void WorldSession::SendPlayerNotFoundNotice(std::string const& name) +void WorldSession::SendChatPlayerNotfoundNotice(std::string const& name) { - WorldPacket data(SMSG_CHAT_PLAYER_NOTFOUND, name.size()+1); - data << name; - SendPacket(&data); + SendPacket(WorldPackets::Chat::ChatPlayerNotfound(name).Write()); } void WorldSession::SendPlayerAmbiguousNotice(std::string const& name) diff --git a/src/server/game/Handlers/GarrisonHandler.cpp b/src/server/game/Handlers/GarrisonHandler.cpp new file mode 100644 index 00000000000..54c7f4242fd --- /dev/null +++ b/src/server/game/Handlers/GarrisonHandler.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "WorldSession.h" +#include "Garrison.h" +#include "GarrisonPackets.h" + +void WorldSession::HandleGetGarrisonInfo(WorldPackets::Garrison::GetGarrisonInfo& /*getGarrisonInfo*/) +{ + if (Garrison* garrison = _player->GetGarrison()) + garrison->SendInfo(); +} + +void WorldSession::HandleGarrisonPurchaseBuilding(WorldPackets::Garrison::GarrisonPurchaseBuilding& garrisonPurchaseBuilding) +{ + if (!_player->GetNPCIfCanInteractWith(garrisonPurchaseBuilding.NpcGUID, UNIT_NPC_FLAG_GARRISON_ARCHITECT)) + return; + + if (Garrison* garrison = _player->GetGarrison()) + garrison->PlaceBuilding(garrisonPurchaseBuilding.PlotInstanceID, garrisonPurchaseBuilding.BuildingID); +} + +void WorldSession::HandleGarrisonCancelConstruction(WorldPackets::Garrison::GarrisonCancelConstruction& garrisonCancelConstruction) +{ + if (!_player->GetNPCIfCanInteractWith(garrisonCancelConstruction.NpcGUID, UNIT_NPC_FLAG_GARRISON_ARCHITECT)) + return; + + if (Garrison* garrison = _player->GetGarrison()) + garrison->CancelBuildingConstruction(garrisonCancelConstruction.PlotInstanceID); +} + +void WorldSession::HandleGarrisonRequestBlueprintAndSpecializationData(WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData& /*garrisonRequestBlueprintAndSpecializationData*/) +{ + if (Garrison* garrison = _player->GetGarrison()) + garrison->SendBlueprintAndSpecializationData(); +} + +void WorldSession::HandleGarrisonGetBuildingLandmarks(WorldPackets::Garrison::GarrisonGetBuildingLandmarks& /*garrisonGetBuildingLandmarks*/) +{ + if (Garrison* garrison = _player->GetGarrison()) + garrison->SendBuildingLandmarks(_player); +} diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index bf9b07413c1..9552c9a0655 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -63,8 +63,6 @@ void WorldSession::SendPartyResult(PartyOperation operation, const std::string& void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_INVITE"); - ObjectGuid crossRealmGuid; // unused recvData.read_skip<uint32>(); // Non-zero in cross realm invites @@ -326,8 +324,6 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData) void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_INVITE_RESPONSE"); - recvData.ReadBit(); // unk always 0 bool accept = recvData.ReadBit(); @@ -403,8 +399,6 @@ void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData) void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_PARTY_UNINVITE"); - ObjectGuid guid; std::string reason; recvData >> guid; @@ -446,8 +440,6 @@ void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData) void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_SET_ROLE"); - ObjectGuid guid; recvData >> guid; @@ -467,8 +459,6 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData) void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_SET_ROLES"); - uint32 newRole; ObjectGuid guid1; // Assigner GUID ObjectGuid guid2; // Target GUID @@ -545,8 +535,6 @@ void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData) void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LEAVE_GROUP"); - Group* grp = GetPlayer()->GetGroup(); if (!grp) return; @@ -568,8 +556,6 @@ void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/) void WorldSession::HandleLootMethodOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LOOT_METHOD"); - uint32 lootMethod; ObjectGuid lootMaster; uint32 lootThreshold; @@ -645,8 +631,6 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData) void WorldSession::HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_RANDOM_ROLL"); - uint32 minimum, maximum, roll; minimum = packet.Min; maximum = packet.Max; @@ -712,8 +696,6 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData) void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_CONVERT_RAID"); - Group* group = GetPlayer()->GetGroup(); if (!group) return; @@ -750,8 +732,6 @@ void WorldSession::HandleGroupRequestJoinUpdates(WorldPacket& /*recvData*/) void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_CHANGE_SUB_GROUP"); - // we will get correct pointer for group here, so we don't have to check if group is BG raid Group* group = GetPlayer()->GetGroup(); if (!group) @@ -788,7 +768,6 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData) void WorldSession::HandleGroupSwapSubGroupOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_SWAP_SUB_GROUPS"); std::string unk1; std::string unk2; @@ -798,8 +777,6 @@ void WorldSession::HandleGroupSwapSubGroupOpcode(WorldPacket& recvData) void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_SET_ASSISTANT_LEADER"); - Group* group = GetPlayer()->GetGroup(); if (!group) return; @@ -851,8 +828,6 @@ void WorldSession::HandlePartyAssignmentOpcode(WorldPacket& recvData) void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_DO_READY_CHECK"); - Group* group = GetPlayer()->GetGroup(); if (!group) return; @@ -1125,7 +1100,6 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke /*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid Guid; recvData >> Guid; @@ -1310,8 +1284,6 @@ void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket& /*recvData*/) void WorldSession::HandleOptOutOfLootOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_OPT_OUT_OF_LOOT"); - bool passOnLoot; recvData >> passOnLoot; // 1 always pass, 0 do not pass @@ -1328,8 +1300,6 @@ void WorldSession::HandleOptOutOfLootOpcode(WorldPacket& recvData) void WorldSession::HandleRolePollBeginOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_ROLE_POLL_BEGIN"); - Group* group = GetPlayer()->GetGroup(); if (!group) return; diff --git a/src/server/game/Handlers/GuildFinderHandler.cpp b/src/server/game/Handlers/GuildFinderHandler.cpp index 3959f659e85..714be0c51bc 100644 --- a/src/server/game/Handlers/GuildFinderHandler.cpp +++ b/src/server/game/Handlers/GuildFinderHandler.cpp @@ -24,8 +24,6 @@ void WorldSession::HandleGuildFinderAddRecruit(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_ADD_RECRUIT"); - if (sGuildFinderMgr->GetAllMembershipRequestsForPlayer(GetPlayer()->GetGUID()).size() == 10) return; @@ -73,7 +71,6 @@ void WorldSession::HandleGuildFinderAddRecruit(WorldPacket& recvPacket) void WorldSession::HandleGuildFinderBrowse(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_BROWSE"); uint32 classRoles = 0; uint32 availability = 0; uint32 guildInterests = 0; @@ -175,7 +172,6 @@ void WorldSession::HandleGuildFinderBrowse(WorldPacket& recvPacket) void WorldSession::HandleGuildFinderDeclineRecruit(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_DECLINE_RECRUIT"); if (!GetPlayer()->GetGuild()) { recvPacket.rfinish(); @@ -273,8 +269,6 @@ void WorldSession::HandleGuildFinderGetApplications(WorldPacket& /*recvPacket*/) // Lists all recruits for a guild - Misses times void WorldSession::HandleGuildFinderGetRecruits(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_GET_RECRUITS"); - uint32 unkTime = 0; recvPacket >> unkTime; @@ -343,8 +337,6 @@ void WorldSession::HandleGuildFinderGetRecruits(WorldPacket& recvPacket) void WorldSession::HandleGuildFinderPostRequest(WorldPacket& /*recvPacket*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_POST_REQUEST"); // Empty opcode - Player* player = GetPlayer(); Guild* guild = player->GetGuild(); @@ -376,8 +368,6 @@ void WorldSession::HandleGuildFinderPostRequest(WorldPacket& /*recvPacket*/) void WorldSession::HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_REMOVE_RECRUIT"); - ObjectGuid guildGuid; guildGuid[0] = recvPacket.ReadBit(); @@ -407,8 +397,6 @@ void WorldSession::HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket) // Sent any time a guild master sets an option in the interface and when listing / unlisting his guild void WorldSession::HandleGuildFinderSetGuildPost(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_LF_GUILD_SET_GUILD_POST"); - uint32 classRoles = 0; uint32 availability = 0; uint32 guildInterests = 0; diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp index 679f1f08dc9..ad3de84beb5 100644 --- a/src/server/game/Handlers/GuildHandler.cpp +++ b/src/server/game/Handlers/GuildHandler.cpp @@ -66,8 +66,6 @@ void WorldSession::HandleGuildOfficerRemoveMember(WorldPackets::Guild::GuildOffi void WorldSession::HandleGuildAcceptInvite(WorldPackets::Guild::AcceptGuildInvite& /*invite*/) { - TC_LOG_DEBUG("guild", "CMSG_ACCEPT_GUILD_INVITE [%s]", GetPlayerInfo().c_str()); - if (!GetPlayer()->GetGuildId()) if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildIdInvited())) guild->HandleAcceptMember(this); @@ -75,16 +73,12 @@ void WorldSession::HandleGuildAcceptInvite(WorldPackets::Guild::AcceptGuildInvit void WorldSession::HandleGuildDeclineInvitation(WorldPackets::Guild::GuildDeclineInvitation& /*decline*/) { - TC_LOG_DEBUG("guild", "CMSG_GUILD_DECLINE_INVITATION [%s]", GetPlayerInfo().c_str()); - GetPlayer()->SetGuildIdInvited(UI64LIT(0)); GetPlayer()->SetInGuild(UI64LIT(0)); } void WorldSession::HandleGuildGetRoster(WorldPackets::Guild::GuildGetRoster& /*packet*/) { - TC_LOG_DEBUG("guild", "CMSG_GUILD_ROSTER [%s]", GetPlayerInfo().c_str()); - if (Guild* guild = GetPlayer()->GetGuild()) guild->HandleRoster(this); else @@ -120,16 +114,12 @@ void WorldSession::HandleGuildAssignRank(WorldPackets::Guild::GuildAssignMemberR void WorldSession::HandleGuildLeave(WorldPackets::Guild::GuildLeave& /*leave*/) { - TC_LOG_DEBUG("guild", "CMSG_GUILD_LEAVE [%s]", GetPlayerInfo().c_str()); - if (Guild* guild = GetPlayer()->GetGuild()) guild->HandleLeaveMember(this); } void WorldSession::HandleGuildDelete(WorldPackets::Guild::GuildDelete& /*packet*/) { - TC_LOG_DEBUG("guild", "CMSG_GUILD_DELETE [%s]", GetPlayerInfo().c_str()); - if (Guild* guild = GetPlayer()->GetGuild()) guild->HandleDelete(this); } @@ -220,16 +210,12 @@ void WorldSession::HandleGuildEventLogQuery(WorldPackets::Guild::GuildEventLogQu void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPackets::Guild::GuildBankRemainingWithdrawMoneyQuery& /*packet*/) { - TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_MONEY_WITHDRAWN [%s]", GetPlayerInfo().c_str()); - if (Guild* guild = GetPlayer()->GetGuild()) guild->SendMoneyInfo(this); } void WorldSession::HandleGuildPermissionsQuery(WorldPackets::Guild::GuildPermissionsQuery& /* packet */) { - TC_LOG_DEBUG("guild", "CMSG_GUILD_PERMISSIONS_QUERY [%s]", GetPlayerInfo().c_str()); - if (Guild* guild = GetPlayer()->GetGuild()) guild->SendPermissions(this); } @@ -288,8 +274,6 @@ void WorldSession::HandleGuildBankWithdrawMoney(WorldPackets::Guild::GuildBankWi void WorldSession::HandleGuildBankSwapItems(WorldPackets::Guild::GuildBankSwapItems& packet) { - TC_LOG_DEBUG("guild", "CMSG_GUILD_BANK_SWAP_ITEMS [%s]", GetPlayerInfo().c_str()); - if (!GetPlayer()->GetGameObjectIfCanInteractWith(packet.Banker, GAMEOBJECT_TYPE_GUILD_BANK)) return; @@ -373,8 +357,6 @@ void WorldSession::HandleGuildSetRankPermissions(WorldPackets::Guild::GuildSetRa void WorldSession::HandleGuildRequestPartyState(WorldPackets::Guild::RequestGuildPartyState& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_GUILD_REQUEST_PARTY_STATE"); - if (Guild* guild = sGuildMgr->GetGuildByGuid(packet.GuildGUID)) guild->HandleGuildPartyRequest(this); } @@ -418,7 +400,6 @@ void WorldSession::HandleRequestGuildRewardsList(WorldPackets::Guild::RequestGui void WorldSession::HandleGuildQueryNews(WorldPackets::Guild::GuildQueryNews& newsQuery) { - TC_LOG_DEBUG("guild", "CMSG_GUILD_QUERY_NEWS [%s]", GetPlayerInfo().c_str()); if (Guild* guild = GetPlayer()->GetGuild()) if (guild->GetGUID() == newsQuery.GuildGUID) guild->SendNewsUpdate(this); @@ -436,18 +417,8 @@ void WorldSession::HandleGuildSetGuildMaster(WorldPackets::Guild::GuildSetGuildM guild->HandleSetNewGuildMaster(this, packet.NewMasterName); } -void WorldSession::HandleGuildSetAchievementTracking(WorldPacket& recvPacket) +void WorldSession::HandleGuildSetAchievementTracking(WorldPackets::Guild::GuildSetAchievementTracking& packet) { - uint32 count = recvPacket.ReadBits(24); - std::set<uint32> achievementIds; - - for (uint32 i = 0; i < count; ++i) - { - uint32 achievementId; - recvPacket >> achievementId; - achievementIds.insert(achievementId); - } - if (Guild* guild = GetPlayer()->GetGuild()) - guild->HandleSetAchievementTracking(this, achievementIds); + guild->HandleSetAchievementTracking(this, packet.AchievementIDs); } diff --git a/src/server/game/Handlers/InspectHandler.cpp b/src/server/game/Handlers/InspectHandler.cpp index 4057960bfc9..886234e720d 100644 --- a/src/server/game/Handlers/InspectHandler.cpp +++ b/src/server/game/Handlers/InspectHandler.cpp @@ -65,12 +65,10 @@ void WorldSession::HandleInspectOpcode(WorldPackets::Inspect::Inspect& inspect) if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId())) { - inspectResult.GuildData.HasValue = true; - - WorldPackets::Inspect::InspectGuildData& guildData = inspectResult.GuildData.Value; - guildData.GuildGUID = guild->GetGUID(); - guildData.NumGuildMembers = guild->GetMembersCount(); - guildData.AchievementPoints = guild->GetAchievementMgr().GetAchievementPoints(); + inspectResult.GuildData = boost::in_place(); + inspectResult.GuildData->GuildGUID = guild->GetGUID(); + inspectResult.GuildData->NumGuildMembers = guild->GetMembersCount(); + inspectResult.GuildData->AchievementPoints = guild->GetAchievementMgr().GetAchievementPoints(); } inspectResult.InspecteeGUID = inspect.Target; diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 335bb9ce48c..c938751e162 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -295,7 +295,7 @@ void WorldSession::HandleDestroyItemOpcode(WorldPackets::Item::DestroyItem& dest return; } - if (item->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_INDESTRUCTIBLE) + if (item->GetTemplate()->GetFlags() & ITEM_FLAG_INDESTRUCTIBLE) { _player->SendEquipError(EQUIP_ERR_DROP_BOUND_ITEM, NULL, NULL); return; @@ -388,7 +388,7 @@ void WorldSession::HandleSellItemOpcode(WorldPackets::Item::SellItem& packet) // prevent selling item for sellprice when the item is still refundable // this probably happens when right clicking a refundable item, the client sends both // CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified) - if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) + if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE)) return; // Therefore, no feedback to client // special case at auto sell (sell all) @@ -494,39 +494,6 @@ void WorldSession::HandleBuybackItem(WorldPackets::Item::BuyBackItem& packet) _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, 0, 0); } -void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket& recvData) -{ - TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUY_ITEM_IN_SLOT"); - ObjectGuid vendorguid, bagguid; - uint32 item, slot, count; - uint8 bagslot; - - recvData >> vendorguid >> item >> slot >> bagguid >> bagslot >> count; - - // client expects count starting at 1, and we send vendorslot+1 to client already - if (slot > 0) - --slot; - else - return; // cheating - - uint8 bag = NULL_BAG; // init for case invalid bagGUID - Item* bagItem = NULL; - // find bag slot by bag guid - if (bagguid == _player->GetGUID()) - bag = INVENTORY_SLOT_BAG_0; - else - bagItem = _player->GetItemByGuid(bagguid); - - if (bagItem && bagItem->IsBag()) - bag = bagItem->GetSlot(); - - // bag not found, cheating? - if (bag == NULL_BAG) - return; - - GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagslot); -} - void WorldSession::HandleBuyItemOpcode(WorldPackets::Item::BuyItem& packet) { // client expects count starting at 1, and we send vendorslot+1 to client already @@ -566,8 +533,6 @@ void WorldSession::HandleBuyItemOpcode(WorldPackets::Item::BuyItem& packet) void WorldSession::HandleListInventoryOpcode(WorldPackets::NPC::Hello& packet) { - TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_LIST_INVENTORY"); - if (!GetPlayer()->IsAlive()) return; @@ -626,8 +591,8 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid) continue; // Only display items in vendor lists for the team the player is on - if ((itemTemplate->GetFlags2() & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || - (itemTemplate->GetFlags2() & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE)) + if ((itemTemplate->GetFlags2() & ITEM_FLAG2_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || + (itemTemplate->GetFlags2() & ITEM_FLAG2_ALLIANCE_ONLY && _player->GetTeam() == HORDE)) continue; // Items sold out are not displayed in list @@ -760,39 +725,45 @@ void WorldSession::SendItemEnchantTimeUpdate(ObjectGuid Playerguid, ObjectGuid I SendPacket(&data); } -void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData) +void WorldSession::HandleWrapItem(WorldPackets::Item::WrapItem& packet) { - TC_LOG_DEBUG("network", "Received opcode CMSG_WRAP_ITEM"); - - uint8 gift_bag, gift_slot, item_bag, item_slot; + if (packet.Inv.Items.size() != 2) + { + TC_LOG_ERROR("network", "HandleWrapItem - Invalid itemCount (" SZFMTD ")", packet.Inv.Items.size()); + return; + } - recvData >> gift_bag >> gift_slot; // paper - recvData >> item_bag >> item_slot; // item + /// @todo: 6.x find better way for read + // Gift + uint8 giftContainerSlot = packet.Inv.Items[0].ContainerSlot; + uint8 giftSlot = packet.Inv.Items[0].Slot; + // Item + uint8 itemContainerSlot = packet.Inv.Items[1].ContainerSlot; + uint8 itemSlot = packet.Inv.Items[1].Slot; - TC_LOG_DEBUG("network", "WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot); + TC_LOG_DEBUG("network", "HandleWrapItem - Receive giftContainerSlot = %u, giftSlot = %u, itemContainerSlot = %u, itemSlot = %u", giftContainerSlot, giftSlot, itemContainerSlot, itemSlot); - Item* gift = _player->GetItemByPos(gift_bag, gift_slot); + Item* gift = _player->GetItemByPos(giftContainerSlot, giftSlot); if (!gift) { _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); return; } - if (!(gift->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_WRAPPER)) // cheating: non-wrapper wrapper + if (!(gift->GetTemplate()->GetFlags() & ITEM_FLAG_WRAPPER)) // cheating: non-wrapper wrapper { _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); return; } - Item* item = _player->GetItemByPos(item_bag, item_slot); - + Item* item = _player->GetItemByPos(itemContainerSlot, itemSlot); if (!item) { _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL); return; } - if (item == gift) // not possable with pacjket from real client + if (item == gift) // not possable with pacjket from real client { _player->SendEquipError(EQUIP_ERR_CANT_WRAP_WRAPPED, item, NULL); return; @@ -804,7 +775,7 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData) return; } - if (!item->GetGuidValue(ITEM_FIELD_GIFTCREATOR).IsEmpty()) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); + if (!item->GetGuidValue(ITEM_FIELD_GIFTCREATOR).IsEmpty()) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED); { _player->SendEquipError(EQUIP_ERR_CANT_WRAP_WRAPPED, item, NULL); return; @@ -848,22 +819,35 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData) switch (item->GetEntry()) { - case 5042: item->SetEntry(5043); break; - case 5048: item->SetEntry(5044); break; - case 17303: item->SetEntry(17302); break; - case 17304: item->SetEntry(17305); break; - case 17307: item->SetEntry(17308); break; - case 21830: item->SetEntry(21831); break; + case 5042: + item->SetEntry(5043); + break; + case 5048: + item->SetEntry(5044); + break; + case 17303: + item->SetEntry(17302); + break; + case 17304: + item->SetEntry(17305); + break; + case 17307: + item->SetEntry(17308); + break; + case 21830: + item->SetEntry(21831); + break; } + item->SetGuidValue(ITEM_FIELD_GIFTCREATOR, _player->GetGUID()); - item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED); + item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED); item->SetState(ITEM_CHANGED, _player); - if (item->GetState() == ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance` + if (item->GetState() == ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance` { // after save it will be impossible to remove the item from the queue item->RemoveFromUpdateQueueOf(_player); - item->SaveToDB(trans); // item gave inventory record unchanged and can be save standalone + item->SaveToDB(trans); // item gave inventory record unchanged and can be save standalone } CharacterDatabase.CommitTransaction(trans); @@ -873,8 +857,6 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData) void WorldSession::HandleSocketOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: CMSG_SOCKET_GEMS"); - ObjectGuid item_guid; ObjectGuid gem_guids[MAX_GEM_SOCKETS]; @@ -965,7 +947,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) ItemTemplate const* iGemProto = Gems[i]->GetTemplate(); // unique item (for new and already placed bit removed enchantments - if (iGemProto->GetFlags() & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED) + if (iGemProto->GetFlags() & ITEM_FLAG_UNIQUE_EQUIPPED) { for (int j = 0; j < MAX_GEM_SOCKETS; ++j) { @@ -1080,19 +1062,13 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) itemTarget->SendUpdateSockets(); } -void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recvData) +void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPackets::Item::CancelTempEnchantment& cancelTempEnchantment) { - TC_LOG_DEBUG("network", "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT"); - - uint32 slot; - - recvData >> slot; - // apply only to equipped item - if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot)) + if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, cancelTempEnchantment.Slot)) return; - Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, cancelTempEnchantment.Slot); if (!item) return; @@ -1120,7 +1096,6 @@ void WorldSession::HandleGetItemPurchaseData(WorldPackets::Item::GetItemPurchase void WorldSession::HandleItemRefund(WorldPacket &recvData) { - TC_LOG_DEBUG("network", "WORLD: CMSG_ITEM_PURCHASE_REFUND"); ObjectGuid guid; recvData >> guid; // item guid @@ -1138,37 +1113,8 @@ void WorldSession::HandleItemRefund(WorldPacket &recvData) GetPlayer()->RefundItem(item); } -/** - * Handles the packet sent by the client when requesting information about item text. - * - * This function is called when player clicks on item which has some flag set - */ -void WorldSession::HandleItemTextQuery(WorldPacket& recvData ) -{ - ObjectGuid itemGuid; - recvData >> itemGuid; - - TC_LOG_DEBUG("network", "CMSG_ITEM_TEXT_QUERY %s", itemGuid.ToString().c_str()); - - WorldPacket data(SMSG_QUERY_ITEM_TEXT_RESPONSE, 14); // guess size - - if (Item* item = _player->GetItemByGuid(itemGuid)) - { - data << uint8(0); // has text - data << itemGuid; // item guid - data << item->GetText(); - } - else - { - data << uint8(1); // no text - } - - SendPacket(&data); -} - void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRANSMOGRIFY_ITEMS"); Player* player = GetPlayer(); // Read data diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index 9a864a808cc..ddd084cbd9d 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -35,7 +35,6 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& packet) { - TC_LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); ObjectGuid lguid = player->GetLootGUID(); @@ -105,8 +104,6 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& p void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet*/) { - TC_LOG_DEBUG("network", "WORLD: CMSG_LOOT_MONEY"); - Player* player = GetPlayer(); ObjectGuid guid = player->GetLootGUID(); if (!guid) @@ -231,8 +228,6 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet void WorldSession::HandleLootOpcode(WorldPackets::Loot::LootUnit& packet) { - TC_LOG_DEBUG("network", "WORLD: CMSG_LOOT"); - // Check possible cheat if (!GetPlayer()->IsAlive() || !packet.Unit.IsCreatureOrVehicle()) return; @@ -246,8 +241,6 @@ void WorldSession::HandleLootOpcode(WorldPackets::Loot::LootUnit& packet) void WorldSession::HandleLootReleaseOpcode(WorldPackets::Loot::LootRelease& packet) { - TC_LOG_DEBUG("network", "WORLD: CMSG_LOOT_RELEASE"); - // cheaters can modify lguid to prevent correct apply loot release code and re-loot // use internal stored guid ObjectGuid lguid = GetPlayer()->GetLootGUID(); @@ -332,7 +325,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid) ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling - if (proto->GetFlags() & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) + if (proto->GetFlags() & (ITEM_FLAG_PROSPECTABLE | ITEM_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); @@ -348,7 +341,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid) else { // Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item - if (pItem->loot.isLooted() || !(proto->GetFlags() & ITEM_PROTO_FLAG_OPENABLE)) + if (pItem->loot.isLooted() || !(proto->GetFlags() & ITEM_FLAG_OPENABLE)) player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } return; // item can be looted only single player diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 10231167b01..dd55c6f2f06 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -196,7 +196,7 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet) if (Item* item = player->GetItemByGuid(att.ItemGUID)) { ItemTemplate const* itemProto = item->GetTemplate(); - if (!itemProto || !(itemProto->GetFlags() & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) + if (!itemProto || !(itemProto->GetFlags() & ITEM_FLAG_BIND_TO_ACCOUNT)) { accountBound = false; break; @@ -250,13 +250,13 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet) } } - if (item->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) + if (item->GetTemplate()->GetFlags() & ITEM_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } - if (packet.Info.Cod && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) + if (packet.Info.Cod && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; @@ -612,7 +612,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPackets::Mail::MailCreateTextIt } Item* bodyItem = new Item; // This is not bag and then can be used new Item. - if (!bodyItem->Create(sObjectMgr->GetGenerator<HighGuid::Item>()->Generate(), MAIL_BODY_ITEM_TEMPLATE, player)) + if (!bodyItem->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), MAIL_BODY_ITEM_TEMPLATE, player)) { delete bodyItem; return; @@ -636,7 +636,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPackets::Mail::MailCreateTextIt if (m->messageType == MAIL_NORMAL) bodyItem->SetGuidValue(ITEM_FIELD_CREATOR, ObjectGuid::Create<HighGuid::Player>(m->sender)); - bodyItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_MAIL_TEXT_MASK); + bodyItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_MAIL_TEXT_MASK); ItemPosCountVec dest; uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, bodyItem, false); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 8b1d91a89f3..025bb45b42b 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -47,7 +47,6 @@ #include "ScriptMgr.h" #include "MapManager.h" #include "InstanceScript.h" -#include "GameObjectAI.h" #include "Group.h" #include "AccountMgr.h" #include "Spell.h" @@ -57,14 +56,11 @@ #include "CharacterPackets.h" #include "ClientConfigPackets.h" #include "MiscPackets.h" -#include "NPCPackets.h" #include "AchievementPackets.h" #include "WhoPackets.h" void WorldSession::HandleRepopRequest(WorldPackets::Misc::RepopRequest& /*packet*/) { - TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_REPOP_REQUEST Message"); - if (GetPlayer()->IsAlive() || GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) return; @@ -89,91 +85,6 @@ void WorldSession::HandleRepopRequest(WorldPackets::Misc::RepopRequest& /*packet GetPlayer()->RepopAtGraveyard(); } -void WorldSession::HandleGossipSelectOptionOpcode(WorldPackets::NPC::GossipSelectOption& packet) -{ - if (!_player->PlayerTalkClass->GetGossipMenu().GetItem(packet.GossipIndex)) - return; - - // Prevent cheating on C++ scripted menus - if (_player->PlayerTalkClass->GetGossipMenu().GetSenderGUID() != packet.GossipUnit) - return; - - Creature* unit = nullptr; - GameObject* go = nullptr; - if (packet.GossipUnit.IsCreatureOrVehicle()) - { - unit = GetPlayer()->GetNPCIfCanInteractWith(packet.GossipUnit, UNIT_NPC_FLAG_NONE); - if (!unit) - { - - TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found or you can't interact with him.", packet.GossipUnit.ToString().c_str()); - return; - } - } - else if (packet.GossipUnit.IsGameObject()) - { - go = _player->GetMap()->GetGameObject(packet.GossipUnit); - if (!go) - { - TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found.", packet.GossipUnit.ToString().c_str()); - return; - } - } - else - { - - TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - unsupported %s.", packet.GossipUnit.ToString().c_str()); - return; - } - - // remove fake death - if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) - GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - - if ((unit && unit->GetCreatureTemplate()->ScriptID != unit->LastUsedScriptID) || (go && go->GetGOInfo()->ScriptId != go->LastUsedScriptID)) - { - TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - Script reloaded while in use, ignoring and set new scipt id"); - if (unit) - unit->LastUsedScriptID = unit->GetCreatureTemplate()->ScriptID; - - if (go) - go->LastUsedScriptID = go->GetGOInfo()->ScriptId; - _player->PlayerTalkClass->SendCloseGossip(); - return; - } - - if (!packet.PromotionCode.empty()) - { - if (unit) - { - unit->AI()->sGossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode.c_str()); - if (!sScriptMgr->OnGossipSelectCode(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex), packet.PromotionCode.c_str())) - _player->OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); - } - else - { - go->AI()->GossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode.c_str()); - if (!sScriptMgr->OnGossipSelectCode(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex), packet.PromotionCode.c_str())) - _player->OnGossipSelect(go, packet.GossipIndex, packet.GossipID); - } - } - else - { - if (unit) - { - unit->AI()->sGossipSelect(_player, packet.GossipID, packet.GossipIndex); - if (!sScriptMgr->OnGossipSelect(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex))) - _player->OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); - } - else - { - go->AI()->GossipSelect(_player, packet.GossipID, packet.GossipIndex); - if (!sScriptMgr->OnGossipSelect(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex))) - _player->OnGossipSelect(go, packet.GossipIndex, packet.GossipID); - } - } -} - void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest) { WorldPackets::Who::WhoRequest& request = whoRequest.Request; @@ -298,7 +209,7 @@ void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest) { std::string aName; if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(target->GetZoneId())) - aName = areaEntry->ZoneName; + aName = areaEntry->AreaName_lang; bool show = false; for (size_t i = 0; i < wWords.size(); ++i) @@ -346,8 +257,6 @@ void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest) void WorldSession::HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequest& /*logoutRequest*/) { - TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", GetSecurity()); - ObjectGuid lguid = GetPlayer()->GetLootGUID(); if (!lguid.IsEmpty()) DoLootRelease(lguid); @@ -398,8 +307,6 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequ void WorldSession::HandleLogoutCancelOpcode(WorldPackets::Character::LogoutCancel& /*logoutCancel*/) { - TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_LOGOUT_CANCEL Message"); - // Player have already logged out serverside, too late to cancel if (!GetPlayer()) return; @@ -503,37 +410,8 @@ void WorldSession::HandleStandStateChangeOpcode(WorldPackets::Misc::StandStateCh _player->SetStandState(packet.StandState); } -void WorldSession::HandleBugReportOpcode(WorldPacket& recvData) -{ - uint32 suggestion, contentlen, typelen; - std::string content, type; - - recvData >> suggestion >> contentlen; - content = recvData.ReadString(contentlen); - - recvData >> typelen; - type = recvData.ReadString(typelen); - - if (suggestion == 0) - TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUG_REPORT [Bug Report]"); - else - TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUG_REPORT [Suggestion]"); - - TC_LOG_DEBUG("network", "%s", type.c_str()); - TC_LOG_DEBUG("network", "%s", content.c_str()); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_BUG_REPORT); - - stmt->setString(0, type); - stmt->setString(1, content); - - CharacterDatabase.Execute(stmt); -} - void WorldSession::HandleReclaimCorpse(WorldPackets::Misc::ReclaimCorpse& /*packet*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_RECLAIM_CORPSE"); - if (_player->IsAlive()) return; @@ -566,12 +444,10 @@ void WorldSession::HandleReclaimCorpse(WorldPackets::Misc::ReclaimCorpse& /*pack void WorldSession::HandleResurrectResponse(WorldPackets::Misc::ResurrectResponse& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_RESURRECT_RESPONSE"); - if (GetPlayer()->IsAlive()) return; - if (packet.Response == 0) + if (packet.Response != 0) // Accept = 0 Decline = 1 Timeout = 2 { GetPlayer()->ClearResurrectRequestData(); // reject return; @@ -801,15 +677,14 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPackets::Spells::SetActionBu GetPlayer()->AddActionButton(packet.Index, action, type); } -void WorldSession::HandleCompleteCinematic(WorldPacket& /*recvData*/) +void WorldSession::HandleCompleteCinematic(WorldPackets::Misc::CompleteCinematic& /*packet*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_COMPLETE_CINEMATIC"); } -void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recvData*/) +void WorldSession::HandleNextCinematicCamera(WorldPackets::Misc::NextCinematicCamera& /*packet*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_NEXT_CINEMATIC_CAMERA"); } + void WorldSession::HandleSetActionBarToggles(WorldPackets::Character::SetActionBarToggles& packet) { if (!GetPlayer()) // ignore until not logged (check needed because STATUS_AUTHED) @@ -847,8 +722,6 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recvData) recvData >> PositionZ; recvData >> Orientation; // o (3.141593 = 180 degrees) - TC_LOG_DEBUG("network", "WORLD: Received CMSG_WORLD_TELEPORT"); - if (GetPlayer()->IsInFlight()) { TC_LOG_DEBUG("network", "Player '%s' (%s) in flight, ignore worldport command.", @@ -919,8 +792,6 @@ void WorldSession::HandleWhoIsOpcode(WorldPackets::Who::WhoIsRequest& packet) void WorldSession::HandleComplainOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: CMSG_COMPLAIN"); - uint8 spam_type; // 0 - mail, 1 - chat ObjectGuid spammer_guid; uint32 unk1 = 0; @@ -961,8 +832,6 @@ void WorldSession::HandleComplainOpcode(WorldPacket& recvData) void WorldSession::HandleRealmSplitOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "CMSG_REALM_SPLIT"); - uint32 unk; std::string split_date = "01/01/01"; recvData >> unk; @@ -979,14 +848,9 @@ void WorldSession::HandleRealmSplitOpcode(WorldPacket& recvData) //TC_LOG_DEBUG("response sent %u", unk); } -void WorldSession::HandleFarSightOpcode(WorldPacket& recvData) +void WorldSession::HandleFarSightOpcode(WorldPackets::Misc::FarSight& packet) { - TC_LOG_DEBUG("network", "WORLD: CMSG_FAR_SIGHT"); - - bool apply; - recvData >> apply; - - if (apply) + if (packet.Enable) { TC_LOG_DEBUG("network", "Added FarSight %s to %s", _player->GetGuidValue(PLAYER_FARSIGHT).ToString().c_str(), _player->GetGUID().ToString().c_str()); if (WorldObject* target = _player->GetViewpoint()) @@ -1005,8 +869,6 @@ void WorldSession::HandleFarSightOpcode(WorldPacket& recvData) void WorldSession::HandleSetTitleOpcode(WorldPackets::Character::SetTitle& packet) { - TC_LOG_DEBUG("network", "CMSG_SET_TITLE"); - // -1 at none if (packet.TitleID > 0 && packet.TitleID < MAX_TITLE_INDEX) { @@ -1021,8 +883,6 @@ void WorldSession::HandleSetTitleOpcode(WorldPackets::Character::SetTitle& packe void WorldSession::HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse& packet) { - TC_LOG_DEBUG("network", "CMSG_TIME_SYNC_RESPONSE"); - // Prevent crashing server if queue is empty if (_player->m_timeSyncQueue.empty()) { @@ -1046,8 +906,6 @@ void WorldSession::HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse& void WorldSession::HandleResetInstancesOpcode(WorldPacket& /*recvData*/) { - TC_LOG_DEBUG("network", "WORLD: CMSG_RESET_INSTANCES"); - if (Group* group = _player->GetGroup()) { if (group->IsLeader(_player->GetGUID())) @@ -1217,8 +1075,6 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPackets::Misc::SetRaidDiff void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& /*recvData*/) { // fly mode on/off - TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK"); - MovementInfo movementInfo; _player->ValidateMovementInfo(&movementInfo); @@ -1228,15 +1084,12 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& /*recvData*/) void WorldSession::HandleRequestPetInfoOpcode(WorldPacket& /*recvData */) { /* - TC_LOG_DEBUG("network", "WORLD: CMSG_REQUEST_PET_INFO"); recvData.hexlike(); */ } void WorldSession::HandleSetTaxiBenchmarkOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: CMSG_SET_TAXI_BENCHMARK_MODE"); - uint8 mode; recvData >> mode; @@ -1291,8 +1144,6 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket) void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY"); - ObjectGuid guid; uint32 spellId; float pitch, speed; @@ -1364,8 +1215,6 @@ void WorldSession::HandleObjectUpdateRescuedOpcode(WorldPackets::Misc::ObjectUpd void WorldSession::HandleSaveCUFProfiles(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: CMSG_SAVE_CUF_PROFILES"); - uint8 count = (uint8)recvPacket.ReadBits(20); if (count > MAX_CUF_PROFILES) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 3835a0642f9..240825faade 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -23,6 +23,7 @@ #include "Log.h" #include "Corpse.h" #include "Player.h" +#include "Garrison.h" #include "SpellAuras.h" #include "MapManager.h" #include "Transport.h" @@ -46,6 +47,7 @@ void WorldSession::HandleMoveWorldportAckOpcode() if (!GetPlayer()->IsBeingTeleportedFar()) return; + bool seamlessTeleport = GetPlayer()->IsBeingTeleportedSeamlessly(); GetPlayer()->SetSemaphoreTeleportFar(false); // get the teleport destination @@ -88,13 +90,16 @@ void WorldSession::HandleMoveWorldportAckOpcode() float z = loc.GetPositionZ(); if (GetPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_HOVER)) z += GetPlayer()->GetFloatValue(UNIT_FIELD_HOVERHEIGHT); + GetPlayer()->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation()); GetPlayer()->ResetMap(); GetPlayer()->SetMap(newMap); - GetPlayer()->SendInitialPacketsBeforeAddToMap(); - if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer())) + if (!seamlessTeleport) + GetPlayer()->SendInitialPacketsBeforeAddToMap(); + + if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer(), !seamlessTeleport)) { TC_LOG_ERROR("network", "WORLD: failed to teleport player %s (%s) to map %d (%s) because of unknown reason!", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().ToString().c_str(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown"); @@ -124,16 +129,26 @@ void WorldSession::HandleMoveWorldportAckOpcode() } } - GetPlayer()->SendInitialPacketsAfterAddToMap(); + if (!seamlessTeleport) + GetPlayer()->SendInitialPacketsAfterAddToMap(); + else + { + GetPlayer()->UpdateVisibilityForPlayer(); + if (Garrison* garrison = GetPlayer()->GetGarrison()) + garrison->SendRemoteInfo(); + } // flight fast teleport case if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { if (!_player->InBattleground()) { - // short preparations to continue flight - FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); - flight->Initialize(GetPlayer()); + if (!seamlessTeleport) + { + // short preparations to continue flight + FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); + flight->Initialize(GetPlayer()); + } return; } diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index b150663121e..2418bb84cac 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -36,8 +36,10 @@ #include "Battleground.h" #include "ScriptMgr.h" #include "CreatureAI.h" +#include "GameObjectAI.h" #include "SpellInfo.h" #include "NPCPackets.h" +#include "MailPackets.h" enum StableResultCode { @@ -75,9 +77,9 @@ void WorldSession::SendTabardVendorActivate(ObjectGuid guid) void WorldSession::SendShowMailBox(ObjectGuid guid) { - WorldPacket data(SMSG_SHOW_MAILBOX, 8); - data << guid; - SendPacket(&data); + WorldPackets::Mail::ShowMailbox packet; + packet.PostmasterGUID = guid; + SendPacket(packet.Write()); } void WorldSession::HandleTrainerListOpcode(WorldPackets::NPC::Hello& packet) @@ -128,7 +130,7 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) bool valid = true; bool primary_prof_first_rank = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i) { if (!tSpell->ReqAbility[i]) continue; @@ -171,7 +173,7 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) break; SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->ReqAbility[i]); - for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2) + for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < MAX_TRAINERSPELL_ABILITY_REQS; ++itr2) { spell.ReqAbility[maxReq] = itr2->second; ++maxReq; @@ -187,19 +189,14 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) SendPacket(packet.Write()); } -void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData) +void WorldSession::HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpell& packet) { - ObjectGuid guid; - uint32 spellId; - uint32 trainerId; - - recvData >> guid >> trainerId >> spellId; - TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRAINER_BUY_SPELL %s, learn spell id is: %u", guid.ToString().c_str(), spellId); + TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRAINER_BUY_SPELL %s, learn spell id is: %i", packet.TrainerGUID.ToString().c_str(), packet.SpellID); - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); + Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(packet.TrainerGUID, UNIT_NPC_FLAG_TRAINER); if (!unit) { - TC_LOG_DEBUG("network", "WORLD: HandleTrainerBuySpellOpcode - %s not found or you can not interact with him.", guid.ToString().c_str()); + TC_LOG_DEBUG("network", "WORLD: HandleTrainerBuySpellOpcode - %s not found or you can not interact with him.", packet.TrainerGUID.ToString().c_str()); return; } @@ -211,32 +208,32 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData) TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) { - SendTrainerBuyFailed(guid, spellId, 0); + SendTrainerBuyFailed(packet.TrainerGUID, packet.SpellID, 0); return; } // not found, cheat? - TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); - if (!trainer_spell) + TrainerSpell const* trainerSpell = trainer_spells->Find(packet.SpellID); + if (!trainerSpell) { - SendTrainerBuyFailed(guid, spellId, 0); + SendTrainerBuyFailed(packet.TrainerGUID, packet.SpellID, 0); return; } // can't be learn, cheat? Or double learn with lags... - if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN) + if (_player->GetTrainerSpellState(trainerSpell) != TRAINER_SPELL_GREEN) { - SendTrainerBuyFailed(guid, spellId, 0); + SendTrainerBuyFailed(packet.TrainerGUID, packet.SpellID, 0); return; } // apply reputation discount - uint32 nSpellCost = uint32(floor(trainer_spell->MoneyCost * _player->GetReputationPriceDiscount(unit))); + uint32 nSpellCost = uint32(floor(trainerSpell->MoneyCost * _player->GetReputationPriceDiscount(unit))); // check money requirement if (!_player->HasEnoughMoney(uint64(nSpellCost))) { - SendTrainerBuyFailed(guid, spellId, 1); + SendTrainerBuyFailed(packet.TrainerGUID, packet.SpellID, 1); return; } @@ -246,25 +243,23 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData) _player->SendPlaySpellVisualKit(362, 1); // 113 EmoteSalute // learn explicitly or cast explicitly - if (trainer_spell->IsCastable()) - _player->CastSpell(_player, trainer_spell->SpellID, true); + if (trainerSpell->IsCastable()) + _player->CastSpell(_player, trainerSpell->SpellID, true); else - _player->LearnSpell(spellId, false); + _player->LearnSpell(packet.SpellID, false); } -void WorldSession::SendTrainerBuyFailed(ObjectGuid guid, uint32 spellId, uint32 reason) +void WorldSession::SendTrainerBuyFailed(ObjectGuid trainerGUID, uint32 spellID, int32 trainerFailedReason) { - WorldPacket data(SMSG_TRAINER_BUY_FAILED, 16); - data << guid; - data << uint32(spellId); // should be same as in packet from client - data << uint32(reason); // 1 == "Not enough money for trainer service." 0 == "Trainer service %d unavailable." - SendPacket(&data); + WorldPackets::NPC::TrainerBuyFailed trainerBuyFailed; + trainerBuyFailed.TrainerGUID = trainerGUID; + trainerBuyFailed.SpellID = spellID; // should be same as in packet from client + trainerBuyFailed.TrainerFailedReason = trainerFailedReason; // 1 == "Not enough money for trainer service." 0 == "Trainer service %d unavailable." + SendPacket(trainerBuyFailed.Write()); } void WorldSession::HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_GOSSIP_HELLO"); - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(packet.Unit, UNIT_NPC_FLAG_NONE); if (!unit) { @@ -305,28 +300,41 @@ void WorldSession::HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet) unit->AI()->sGossipHello(_player); } -/*void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recvData) + +void WorldSession::HandleGossipSelectOptionOpcode(WorldPackets::NPC::GossipSelectOption& packet) { - TC_LOG_DEBUG("network", "WORLD: CMSG_GOSSIP_SELECT_OPTION"); + if (!_player->PlayerTalkClass->GetGossipMenu().GetItem(packet.GossipIndex)) + return; - uint32 option; - uint32 unk; - uint64 guid; - std::string code = ""; + // Prevent cheating on C++ scripted menus + if (_player->PlayerTalkClass->GetGossipMenu().GetSenderGUID() != packet.GossipUnit) + return; - recvData >> guid >> unk >> option; + Creature* unit = nullptr; + GameObject* go = nullptr; + if (packet.GossipUnit.IsCreatureOrVehicle()) + { + unit = GetPlayer()->GetNPCIfCanInteractWith(packet.GossipUnit, UNIT_NPC_FLAG_NONE); + if (!unit) + { - if (_player->PlayerTalkClass->GossipOptionCoded(option)) + TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found or you can't interact with him.", packet.GossipUnit.ToString().c_str()); + return; + } + } + else if (packet.GossipUnit.IsGameObject()) { - TC_LOG_DEBUG("network", "reading string"); - recvData >> code; - TC_LOG_DEBUG("network", "string read: %s", code.c_str()); + go = _player->GetMap()->GetGameObject(packet.GossipUnit); + if (!go) + { + TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found.", packet.GossipUnit.ToString().c_str()); + return; + } } - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) + else { - TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + + TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - unsupported %s.", packet.GossipUnit.ToString().c_str()); return; } @@ -334,29 +342,56 @@ void WorldSession::HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet) if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - if (!code.empty()) + if ((unit && unit->GetCreatureTemplate()->ScriptID != unit->LastUsedScriptID) || (go && go->GetGOInfo()->ScriptId != go->LastUsedScriptID)) { - if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str())) - unit->OnGossipSelect (_player, option); + TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - Script reloaded while in use, ignoring and set new scipt id"); + if (unit) + unit->LastUsedScriptID = unit->GetCreatureTemplate()->ScriptID; + + if (go) + go->LastUsedScriptID = go->GetGOInfo()->ScriptId; + _player->PlayerTalkClass->SendCloseGossip(); + return; + } + + if (!packet.PromotionCode.empty()) + { + if (unit) + { + unit->AI()->sGossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode.c_str()); + if (!sScriptMgr->OnGossipSelectCode(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex), packet.PromotionCode.c_str())) + _player->OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); + } + else + { + go->AI()->GossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode.c_str()); + if (!sScriptMgr->OnGossipSelectCode(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex), packet.PromotionCode.c_str())) + _player->OnGossipSelect(go, packet.GossipIndex, packet.GossipID); + } } else { - if (!Script->OnGossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option))) - unit->OnGossipSelect (_player, option); + if (unit) + { + unit->AI()->sGossipSelect(_player, packet.GossipID, packet.GossipIndex); + if (!sScriptMgr->OnGossipSelect(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex))) + _player->OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); + } + else + { + go->AI()->GossipSelect(_player, packet.GossipID, packet.GossipIndex); + if (!sScriptMgr->OnGossipSelect(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex))) + _player->OnGossipSelect(go, packet.GossipIndex, packet.GossipID); + } } -}*/ +} -void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket& recvData) +void WorldSession::HandleSpiritHealerActivate(WorldPackets::NPC::SpiritHealerActivate& packet) { - TC_LOG_DEBUG("network", "WORLD: CMSG_SPIRIT_HEALER_ACTIVATE"); - - ObjectGuid guid; - recvData >> guid; - - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_SPIRITHEALER); + Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(packet.Healer, UNIT_NPC_FLAG_SPIRITHEALER); if (!unit) { - TC_LOG_DEBUG("network", "WORLD: HandleSpiritHealerActivateOpcode - %s not found or you can not interact with him.", guid.ToString().c_str()); + TC_LOG_DEBUG("network", "WORLD: HandleSpiritHealerActivateOpcode - %s not found or you can not interact with him.", packet.Healer.ToString().c_str()); return; } @@ -470,8 +505,6 @@ void WorldSession::SendStablePetCallback(PreparedQueryResult result, ObjectGuid if (!GetPlayer()) return; - TC_LOG_DEBUG("network", "WORLD: Recv CMSG_REQUEST_STABLED_PETS Send."); - WorldPacket data(SMSG_PET_STABLE_LIST, 200); // guess size data << guid; @@ -529,7 +562,6 @@ void WorldSession::SendPetStableResult(uint8 res) void WorldSession::HandleStablePet(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Recv CMSG_STABLE_PET"); ObjectGuid npcGUID; recvData >> npcGUID; @@ -603,7 +635,6 @@ void WorldSession::HandleStablePetCallback(PreparedQueryResult result) void WorldSession::HandleUnstablePet(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Recv CMSG_UNSTABLE_PET."); ObjectGuid npcGUID; uint32 petnumber; @@ -684,7 +715,6 @@ void WorldSession::HandleUnstablePetCallback(PreparedQueryResult result, uint32 void WorldSession::HandleBuyStableSlot(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Recv CMSG_BUY_STABLE_SLOT."); ObjectGuid npcGUID; recvData >> npcGUID; @@ -722,7 +752,6 @@ void WorldSession::HandleStableRevivePet(WorldPacket &/* recvData */) void WorldSession::HandleStableSwapPet(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Recv CMSG_STABLE_SWAP_PET."); ObjectGuid npcGUID; uint32 petId; diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index c9cc6d547f1..7f1782ea1f0 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -34,6 +34,7 @@ #include "SpellInfo.h" #include "Player.h" #include "SpellPackets.h" +#include "QueryPackets.h" void WorldSession::HandleDismissCritter(WorldPacket& recvData) { @@ -413,48 +414,34 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe } } -void WorldSession::HandlePetNameQuery(WorldPacket& recvData) +void WorldSession::HandleQueryPetName(WorldPackets::Query::QueryPetName& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_NAME_QUERY"); - - uint32 petnumber; - ObjectGuid petguid; - - recvData >> petnumber; - recvData >> petguid; - - SendPetNameQuery(petguid, petnumber); + SendQueryPetNameResponse(packet.UnitGUID); } -void WorldSession::SendPetNameQuery(ObjectGuid petguid, uint32 petnumber) +void WorldSession::SendQueryPetNameResponse(ObjectGuid guid) { - Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); - if (!pet) - { - WorldPacket data(SMSG_QUERY_PET_NAME_RESPONSE, (4 + 1 + 4 + 1)); - data << uint32(petnumber); - data << uint8(0); - data << uint32(0); - data << uint8(0); - _player->GetSession()->SendPacket(&data); - return; - } + WorldPackets::Query::QueryPetNameResponse response; - WorldPacket data(SMSG_QUERY_PET_NAME_RESPONSE, (4 + 4 + pet->GetName().size() + 1)); - data << uint32(petnumber); - data << pet->GetName(); - data << uint32(pet->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP)); + response.UnitGUID = guid; - if (pet->IsPet() && ((Pet*)pet)->GetDeclinedNames()) + if (Creature* unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid)) { - data << uint8(1); - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - data << ((Pet*)pet)->GetDeclinedNames()->name[i]; + response.Allow = true; + response.Timestamp = unit->GetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP); + response.Name = unit->GetName(); + + if (Pet* pet = unit->ToPet()) + { + if (DeclinedName const* names = pet->GetDeclinedNames()) + { + response.HasDeclined = true; + response.DeclinedNames = *names; + } + } } - else - data << uint8(0); - _player->GetSession()->SendPacket(&data); + _player->GetSession()->SendPacket(response.Write()); } bool WorldSession::CheckStableMaster(ObjectGuid guid) @@ -482,8 +469,6 @@ bool WorldSession::CheckStableMaster(ObjectGuid guid) void WorldSession::HandlePetSetAction(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_SET_ACTION"); - ObjectGuid petguid; uint8 count; @@ -599,8 +584,6 @@ void WorldSession::HandlePetSetAction(WorldPacket& recvData) void WorldSession::HandlePetRename(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_RENAME"); - ObjectGuid petguid; uint8 isdeclined; @@ -611,7 +594,7 @@ void WorldSession::HandlePetRename(WorldPacket& recvData) recvData >> name; recvData >> isdeclined; - Pet* pet = ObjectAccessor::FindPet(petguid); + Pet* pet = ObjectAccessor::GetPet(*_player, petguid); // check it! if (!pet || !pet->IsPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || @@ -706,7 +689,6 @@ void WorldSession::HandlePetAbandon(WorldPacket& recvData) void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_SPELL_AUTOCAST"); ObjectGuid guid; uint32 spellid; uint8 state; //1 for on, 0 for off diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index 97935d5837e..2e5c4c14424 100644 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -35,8 +35,6 @@ void WorldSession::HandlePetitionBuy(WorldPackets::Petition::PetitionBuy& packet) { - TC_LOG_DEBUG("network", "Received CMSG_PETITION_BUY"); - TC_LOG_DEBUG("network", "Petitioner %s tried sell petition: title %s", packet.Unit.ToString().c_str(), packet.Title.c_str()); // prevent cheating @@ -140,8 +138,6 @@ void WorldSession::HandlePetitionBuy(WorldPackets::Petition::PetitionBuy& packet void WorldSession::HandlePetitionShowSignatures(WorldPackets::Petition::PetitionShowSignatures& packet) { - TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_SHOW_SIGNATURES"); - uint8 signs = 0; // if has guild => error, return; @@ -238,9 +234,6 @@ void WorldSession::SendPetitionQueryOpcode(ObjectGuid petitionGUID) void WorldSession::HandlePetitionRenameGuild(WorldPackets::Petition::PetitionRenameGuild& packet) { - TC_LOG_DEBUG("network", "Received CMSG_PETITION_RENAME_GUILD"); - TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_RENAME_GUILD"); - Item* item = _player->GetItemByGuid(packet.PetitionGuid); if (!item) return; @@ -274,8 +267,6 @@ void WorldSession::HandlePetitionRenameGuild(WorldPackets::Petition::PetitionRen void WorldSession::HandleSignPetition(WorldPackets::Petition::SignPetition& packet) { - TC_LOG_DEBUG("network", "Received CMSG_SIGN_PETITION"); - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURES); stmt->setUInt64(0, packet.PetitionGUID.GetCounter()); @@ -368,8 +359,6 @@ void WorldSession::HandleSignPetition(WorldPackets::Petition::SignPetition& pack void WorldSession::HandleDeclinePetition(WorldPackets::Petition::DeclinePetition& packet) { - TC_LOG_DEBUG("network", "Received CMSG_DECLINE_PETITION"); - TC_LOG_DEBUG("network", "Petition %s declined by %s", packet.PetitionGUID.ToString().c_str(), _player->GetGUID().ToString().c_str()); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_OWNER_BY_GUID); @@ -396,8 +385,6 @@ void WorldSession::HandleDeclinePetition(WorldPackets::Petition::DeclinePetition void WorldSession::HandleOfferPetition(WorldPackets::Petition::OfferPetition& packet) { - TC_LOG_DEBUG("network", "Received opcode CMSG_OFFER_PETITION"); - Player* player = ObjectAccessor::FindConnectedPlayer(packet.TargetPlayer); if (!player) return; @@ -458,8 +445,6 @@ void WorldSession::HandleOfferPetition(WorldPackets::Petition::OfferPetition& pa void WorldSession::HandleTurnInPetition(WorldPackets::Petition::TurnInPetition& packet) { - TC_LOG_DEBUG("network", "Received CMSG_TURN_IN_PETITION"); - // Check if player really has the required petition charter Item* item = _player->GetItemByGuid(packet.Item); if (!item) @@ -582,8 +567,6 @@ void WorldSession::HandleTurnInPetition(WorldPackets::Petition::TurnInPetition& void WorldSession::HandlePetitionShowList(WorldPackets::Petition::PetitionShowList& packet) { - TC_LOG_DEBUG("network", "Received CMSG_PETITION_SHOW_LIST"); - SendPetitionShowList(packet.PetitionUnit); } diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 55a364b811e..eec80888559 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -152,8 +152,6 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPackets::Query::QueryGameObj void WorldSession::HandleQueryCorpseLocation(WorldPackets::Query::QueryCorpseLocationFromClient& /*packet*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUERY_CORPSE_LOCATION_FROM_CLIENT"); - Corpse* corpse = GetPlayer()->GetCorpse(); if (!corpse) @@ -230,8 +228,6 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPackets::Query::QueryNPCText& p /// Only _static_ data is sent in this packet !!! void WorldSession::HandleQueryPageText(WorldPackets::Query::QueryPageText& packet) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUERY_PAGE_TEXT"); - uint32 pageID = packet.PageTextID; while (pageID) @@ -269,8 +265,6 @@ void WorldSession::HandleQueryPageText(WorldPackets::Query::QueryPageText& packe void WorldSession::HandleQueryCorpseTransport(WorldPackets::Query::QueryCorpseTransport& packet) { - TC_LOG_DEBUG("network", "WORLD: Recv CMSG_QUERY_CORPSE_TRANSPORT"); - Corpse* corpse = _player->GetCorpse(); WorldPackets::Query::CorpseTransportQuery response; @@ -420,3 +414,22 @@ void WorldSession::HandleDBQueryBulk(WorldPackets::Query::DBQueryBulk& packet) SendPacket(response.Write()); } } + +/** +* Handles the packet sent by the client when requesting information about item text. +* +* This function is called when player clicks on item which has some flag set +*/ +void WorldSession::HandleItemTextQuery(WorldPackets::Query::ItemTextQuery& itemTextQuery) +{ + WorldPackets::Query::QueryItemTextResponse queryItemTextResponse; + queryItemTextResponse.Id = itemTextQuery.Id; + + if (Item* item = _player->GetItemByGuid(itemTextQuery.Id)) + { + queryItemTextResponse.Valid = true; + queryItemTextResponse.Item.Text = item->GetText(); + } + + SendPacket(queryItemTextResponse.Write()); +} diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index ed6faf4cca9..c1d61ca49f4 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -256,7 +256,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest bool itemValid = false; for (uint32 i = 0; i < quest->GetRewChoiceItemsCount(); ++i) { - if (quest->RewardChoiceItemId[i] && quest->RewardChoiceItemId[i] == packet.ItemChoiceID) + if (quest->RewardChoiceItemId[i] && quest->RewardChoiceItemId[i] == uint32(packet.ItemChoiceID)) { itemValid = true; break; @@ -269,7 +269,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest { for (QuestPackageItemEntry const* questPackageItem : *questPackageItems) { - if (questPackageItem->ItemID != packet.ItemChoiceID) + if (questPackageItem->ItemID != uint32(packet.ItemChoiceID)) continue; if (ItemTemplate const* rewardProto = sObjectMgr->GetItemTemplate(questPackageItem->ItemID)) @@ -397,8 +397,6 @@ void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPackets::Quest::Ques void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recvData*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_CANCEL"); - _player->PlayerTalkClass->SendCloseGossip(); } @@ -557,7 +555,6 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPackets::Quest::QuestGiver void WorldSession::HandleQuestgiverQuestAutoLaunch(WorldPacket& /*recvPacket*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_QUEST_AUTOLAUNCH"); } void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) @@ -639,8 +636,6 @@ void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) uint8 msg; recvPacket >> guid >> questId >> msg; - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_PUSH_RESULT"); - if (!_player->GetDivider().IsEmpty() && _player->GetDivider() == guid) { Player* player = ObjectAccessor::FindPlayer(_player->GetDivider()); @@ -654,8 +649,6 @@ void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPackets::Quest::QuestGiverStatusMultipleQuery& /*packet*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY"); - WorldPackets::Quest::QuestGiverStatusMultiple response; for (auto itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr) @@ -666,7 +659,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPackets::Quest::Ques Creature* questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(), *itr); if (!questgiver || questgiver->IsHostileTo(_player)) continue; - if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) + if (!questgiver->HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) continue; response.QuestGiver.emplace_back(questgiver->GetGUID(), _player->GetQuestDialogStatus(questgiver)); diff --git a/src/server/game/Handlers/ReferAFriendHandler.cpp b/src/server/game/Handlers/ReferAFriendHandler.cpp index a7cee1e25b9..b4c9513a238 100644 --- a/src/server/game/Handlers/ReferAFriendHandler.cpp +++ b/src/server/game/Handlers/ReferAFriendHandler.cpp @@ -24,7 +24,7 @@ void WorldSession::HandleGrantLevel(WorldPackets::RaF::GrantLevel& grantLevel) { - Player* target = ObjectAccessor::GetObjectInWorld(grantLevel.Target, _player); + Player* target = ObjectAccessor::GetPlayer(*_player, grantLevel.Target); // check cheating uint8 levels = _player->GetGrantableLevels(); @@ -64,7 +64,7 @@ void WorldSession::HandleGrantLevel(WorldPackets::RaF::GrantLevel& grantLevel) void WorldSession::HandleAcceptGrantLevel(WorldPackets::RaF::AcceptLevelGrant& acceptLevelGrant) { - Player* other = ObjectAccessor::GetObjectInWorld(acceptLevelGrant.Granter, _player); + Player* other = ObjectAccessor::GetPlayer(*_player, acceptLevelGrant.Granter); if (!(other && other->GetSession())) return; diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index a83ce9f996d..870fdea69ac 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -27,6 +27,7 @@ #include "WorldPacket.h" #include "WorldSession.h" #include "TalentPackets.h" +#include "SpellPackets.h" void WorldSession::HandleLearnTalentsOpcode(WorldPackets::Talent::LearnTalents& packet) { @@ -69,16 +70,13 @@ void WorldSession::HandleConfirmRespecWipeOpcode(WorldPacket& recvData) unit->CastSpell(_player, 14867, true); //spell: "Untalent Visual Effect" } -void WorldSession::HandleUnlearnSkillOpcode(WorldPacket& recvData) +void WorldSession::HandleUnlearnSkillOpcode(WorldPackets::Spells::UnlearnSkill& packet) { - uint32 skillId; - recvData >> skillId; - - SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skillId, GetPlayer()->getRace(), GetPlayer()->getClass()); + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(packet.SkillLine, GetPlayer()->getRace(), GetPlayer()->getClass()); if (!rcEntry || !(rcEntry->Flags & SKILL_FLAG_UNLEARNABLE)) return; - GetPlayer()->SetSkill(skillId, 0, 0, 0); + GetPlayer()->SetSkill(packet.SkillLine, 0, 0, 0); } void WorldSession::HandleSetSpecializationOpcode(WorldPackets::Talent::SetSpecialization& packet) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 824b747b9f8..3d2f60929fb 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -81,14 +81,14 @@ void WorldSession::HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet) } // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) - if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && !(proto->GetFlags() & ITEM_PROTO_FLAG_USEABLE_IN_ARENA) && user->InArena()) + if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && !(proto->GetFlags() & ITEM_FLAG_USEABLE_IN_ARENA) && user->InArena()) { user->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, item, NULL); return; } // don't allow items banned in arena - if (proto->GetFlags() & ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA && user->InArena()) + if (proto->GetFlags() & ITEM_FLAG_NOT_USEABLE_IN_ARENA && user->InArena()) { user->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, item, NULL); return; @@ -153,7 +153,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet) } // Verify that the bag is an actual bag or wrapped item that can be used "normally" - if (!(proto->GetFlags() & ITEM_PROTO_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) + if (!(proto->GetFlags() & ITEM_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) { player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL); TC_LOG_ERROR("network", "Possible hacking attempt: Player %s [%s] tried to open item [%s, entry: %u] which is not openable!", @@ -182,7 +182,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet) } } - if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))// wrapped? + if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))// wrapped? { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM); @@ -468,10 +468,8 @@ void WorldSession::HandleTotemDestroyed(WorldPacket& recvPacket) totem->ToTotem()->UnSummon(); } -void WorldSession::HandleSelfResOpcode(WorldPacket& /*recvData*/) +void WorldSession::HandleSelfResOpcode(WorldPackets::Spells::SelfRes& /*packet*/) { - TC_LOG_DEBUG("network", "WORLD: CMSG_SELF_RES"); // empty opcode - if (_player->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) return; // silent return, client should display error by itself and not send this opcode @@ -510,7 +508,7 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData) recvData.read_skip<uint32>(); // DisplayId ? // Get unit for which data is needed by client - Unit* unit = ObjectAccessor::GetObjectInWorld(guid, (Unit*)NULL); + Unit* unit = ObjectAccessor::GetUnit(*_player, guid); if (!unit) return; @@ -597,8 +595,6 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData) void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: CMSG_MISSILE_TRAJECTORY_COLLISION"); - ObjectGuid casterGuid; uint32 spellId; uint8 castCount; @@ -634,28 +630,5 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) void WorldSession::HandleRequestCategoryCooldowns(WorldPackets::Spells::RequestCategoryCooldowns& /*requestCategoryCooldowns*/) { - SendSpellCategoryCooldowns(); -} - -void WorldSession::SendSpellCategoryCooldowns() -{ - WorldPackets::Spells::CategoryCooldown cooldowns; - - Unit::AuraEffectList const& categoryCooldownAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN); - for (AuraEffect* aurEff : categoryCooldownAuras) - { - uint32 categoryId = aurEff->GetMiscValue(); - auto cItr = std::find_if(cooldowns.CategoryCooldowns.begin(), cooldowns.CategoryCooldowns.end(), - [categoryId](WorldPackets::Spells::CategoryCooldown::CategoryCooldownInfo const& cooldown) - { - return cooldown.Category == categoryId; - }); - - if (cItr == cooldowns.CategoryCooldowns.end()) - cooldowns.CategoryCooldowns.emplace_back(aurEff->GetMiscValue(), -aurEff->GetAmount()); - else - cItr->ModCooldown -= aurEff->GetAmount(); - } - - SendPacket(cooldowns.Write()); + _player->SendSpellCategoryCooldowns(); } diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp index 74d18eadfe7..0fde16f1be9 100644 --- a/src/server/game/Handlers/TaxiHandler.cpp +++ b/src/server/game/Handlers/TaxiHandler.cpp @@ -30,8 +30,6 @@ void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_TAXINODE_STATUS_QUERY"); - ObjectGuid guid; recvData >> guid; @@ -65,8 +63,6 @@ void WorldSession::SendTaxiStatus(ObjectGuid guid) void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_TAXIQUERYAVAILABLENODES"); - ObjectGuid guid; recvData >> guid; @@ -165,8 +161,6 @@ void WorldSession::SendDiscoverNewTaxiNode(uint32 nodeid) void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_ACTIVATETAXIEXPRESS"); - ObjectGuid guid; uint32 node_count; @@ -205,8 +199,6 @@ void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket& recvData) void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_MOVE_SPLINE_DONE"); - recvData.read_skip<uint32>(); // unk MovementInfo movementInfo; // used only for proper packet read @@ -280,8 +272,6 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData) void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_ACTIVATETAXI"); - ObjectGuid guid; std::vector<uint32> nodes; nodes.resize(2); diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp index 55bbe96f15c..1ff239035a4 100644 --- a/src/server/game/Handlers/TicketHandler.cpp +++ b/src/server/game/Handlers/TicketHandler.cpp @@ -203,6 +203,9 @@ void WorldSession::HandleGMResponseResolve(WorldPackets::Ticket::GMTicketRespons void WorldSession::HandleSupportTicketSubmitBug(WorldPackets::Ticket::SupportTicketSubmitBug& packet) { + if (!sSupportMgr->GetBugSystemStatus()) + return; + BugTicket* ticket = new BugTicket(GetPlayer()); ticket->SetPosition(packet.Header.MapID, packet.Header.Position); ticket->SetFacing(packet.Header.Facing); @@ -213,6 +216,9 @@ void WorldSession::HandleSupportTicketSubmitBug(WorldPackets::Ticket::SupportTic void WorldSession::HandleSupportTicketSubmitSuggestion(WorldPackets::Ticket::SupportTicketSubmitSuggestion& packet) { + if (!sSupportMgr->GetSuggestionSystemStatus()) + return; + SuggestionTicket* ticket = new SuggestionTicket(GetPlayer()); ticket->SetPosition(packet.Header.MapID, packet.Header.Position); ticket->SetFacing(packet.Header.Facing); @@ -223,6 +229,9 @@ void WorldSession::HandleSupportTicketSubmitSuggestion(WorldPackets::Ticket::Sup void WorldSession::HandleSupportTicketSubmitComplaint(WorldPackets::Ticket::SupportTicketSubmitComplaint& packet) { + if (!sSupportMgr->GetComplaintSystemStatus()) + return; + ComplaintTicket* comp = new ComplaintTicket(GetPlayer()); comp->SetPosition(packet.Header.MapID, packet.Header.Position); comp->SetFacing(packet.Header.Facing); @@ -232,5 +241,16 @@ void WorldSession::HandleSupportTicketSubmitComplaint(WorldPackets::Ticket::Supp comp->SetNote(packet.Note); sSupportMgr->AddTicket(comp); +} + +void WorldSession::HandleBugReportOpcode(WorldPackets::Ticket::BugReport& bugReport) +{ + // Note: There is no way to trigger this with standard UI except /script ReportBug("text") + if (!sSupportMgr->GetBugSystemStatus()) + return; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_BUG_REPORT); + stmt->setString(0, bugReport.Text); + stmt->setString(1, bugReport.DiagInfo); + CharacterDatabase.Execute(stmt); } diff --git a/src/server/game/Handlers/TokenHandler.cpp b/src/server/game/Handlers/TokenHandler.cpp index 6b2dd06a44b..a71d9b6e3a7 100644 --- a/src/server/game/Handlers/TokenHandler.cpp +++ b/src/server/game/Handlers/TokenHandler.cpp @@ -23,9 +23,22 @@ void WorldSession::HandleUpdateListedAuctionableTokens(WorldPackets::Token::Upda { WorldPackets::Token::UpdateListedAuctionableTokensResponse response; - /// @todo: fix 6.x implementation + /// @todo: 6.x fix implementation response.UnkInt = updateListedAuctionableTokens.UnkInt; - response.Result = TOKEN_RESULT_ERROR_DISABLED; + response.Result = TOKEN_RESULT_SUCCESS; + + SendPacket(response.Write()); +} + +void WorldSession::HandleRequestWowTokenMarketPrice(WorldPackets::Token::RequestWowTokenMarketPrice& requestWowTokenMarketPrice) +{ + WorldPackets::Token::RequestWowTokenMarketPriceResponse response; + + /// @todo: 6.x fix implementation + response.CurrentMarketPrice = 300000000; + response.UnkInt = requestWowTokenMarketPrice.UnkInt; + response.Result = TOKEN_RESULT_SUCCESS; + //packet.ReadUInt32("UnkInt32"); SendPacket(response.Write()); } diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index c5258e63e40..ddfc0cef55c 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -67,21 +67,21 @@ void WorldSession::SendUpdateTrade(bool trader_data /*= true*/) tradeItem.EntryID = item->GetEntry(); tradeItem.StackCount = item->GetCount(); tradeItem.GiftCreator = item->GetGuidValue(ITEM_FIELD_GIFTCREATOR); - if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) + if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) { - WorldPackets::Trade::TradeUpdated::UnwrappedTradeItem* unwrappedItem = &tradeItem.Unwrapped.Value; - unwrappedItem->Item.Initialize(item); - unwrappedItem->EnchantID = item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT); - unwrappedItem->OnUseEnchantmentID = item->GetEnchantmentId(USE_ENCHANTMENT_SLOT); - unwrappedItem->Creator = item->GetGuidValue(ITEM_FIELD_CREATOR); - unwrappedItem->Charges = item->GetSpellCharges(); - unwrappedItem->Lock = item->GetTemplate()->GetLockID() && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED); - unwrappedItem->MaxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); - unwrappedItem->Durability = item->GetUInt32Value(ITEM_FIELD_DURABILITY); - for (uint32 s = SOCK_ENCHANTMENT_SLOT; s < MAX_GEM_SOCKETS; ++s) - unwrappedItem->SocketEnchant[s] = item->GetEnchantmentId(EnchantmentSlot(s + SOCK_ENCHANTMENT_SLOT)); + tradeItem.Unwrapped = boost::in_place(); + + tradeItem.Unwrapped->Item.Initialize(item); + tradeItem.Unwrapped->EnchantID = item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT); + tradeItem.Unwrapped->OnUseEnchantmentID = item->GetEnchantmentId(USE_ENCHANTMENT_SLOT); + tradeItem.Unwrapped->Creator = item->GetGuidValue(ITEM_FIELD_CREATOR); + tradeItem.Unwrapped->Charges = item->GetSpellCharges(); + tradeItem.Unwrapped->Lock = item->GetTemplate()->GetLockID() && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_UNLOCKED); + tradeItem.Unwrapped->MaxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); + tradeItem.Unwrapped->Durability = item->GetUInt32Value(ITEM_FIELD_DURABILITY); - tradeItem.Unwrapped.HasValue = true; + for (uint32 s = SOCK_ENCHANTMENT_SLOT; s < MAX_GEM_SOCKETS; ++s) + tradeItem.Unwrapped->SocketEnchant[s] = item->GetEnchantmentId(EnchantmentSlot(s + SOCK_ENCHANTMENT_SLOT)); } tradeUpdated.Items.push_back(tradeItem); @@ -124,7 +124,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[]) } // adjust time (depends on /played) - if (myItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE)) + if (myItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE)) myItems[i]->SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, trader->GetTotalPlayedTime()-(_player->GetTotalPlayedTime()-myItems[i]->GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME))); // store trader->MoveItemToInventory(traderDst, myItems[i], true, true); @@ -142,7 +142,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[]) } // adjust time (depends on /played) - if (hisItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE)) + if (hisItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE)) hisItems[i]->SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, _player->GetTotalPlayedTime()-(trader->GetTotalPlayedTime()-hisItems[i]->GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME))); // store _player->MoveItemToInventory(playerDst, hisItems[i], true, true); diff --git a/src/server/game/Handlers/VoiceChatHandler.cpp b/src/server/game/Handlers/VoiceChatHandler.cpp index e20c79337fa..b84f91373da 100644 --- a/src/server/game/Handlers/VoiceChatHandler.cpp +++ b/src/server/game/Handlers/VoiceChatHandler.cpp @@ -24,7 +24,6 @@ void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: CMSG_VOICE_SESSION_ENABLE"); // uint8 isVoiceEnabled, uint8 isMicrophoneEnabled recvData.read_skip<uint8>(); recvData.read_skip<uint8>(); @@ -32,7 +31,6 @@ void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket& recvData) void WorldSession::HandleSetActiveVoiceChannel(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: CMSG_SET_ACTIVE_VOICE_CHANNEL"); recvData.read_skip<uint32>(); recvData.read_skip<char*>(); } diff --git a/src/server/game/Handlers/VoidStorageHandler.cpp b/src/server/game/Handlers/VoidStorageHandler.cpp index dcca2f81711..46e2f1270c1 100644 --- a/src/server/game/Handlers/VoidStorageHandler.cpp +++ b/src/server/game/Handlers/VoidStorageHandler.cpp @@ -158,7 +158,7 @@ void WorldSession::HandleVoidStorageTransfer(WorldPackets::VoidStorage::VoidStor Item* item = _player->GetItemByGuid(voidStorageTransfer.Deposits[i]); if (!item) { - TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s wants to deposit an invalid item (%s).", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), item->GetGUID().ToString().c_str()); + TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s wants to deposit an invalid item (%s).", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.Deposits[i].ToString().c_str()); continue; } diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index c45358efa11..c729057468b 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -558,7 +558,10 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId) ((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY); if (iMap) + { iMap->DeleteRespawnTimes(); + iMap->DeleteCorpseData(); + } else Map::DeleteRespawnTimesInDB(mapid, instanceId); diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 8c34e37976c..be1956efc79 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -178,11 +178,11 @@ class InstanceScript : public ZoneScript inline Creature* GetCreature(uint32 type) { - return ObjectAccessor::GetObjectInMap<Creature>(GetObjectGuid(type), instance, nullptr); + return instance->GetCreature(GetObjectGuid(type)); } inline GameObject* GetGameObject(uint32 type) { - return ObjectAccessor::GetObjectInMap<GameObject>(GetObjectGuid(type), instance, nullptr); + return instance->GetGameObject(GetObjectGuid(type)); } // Called when a player successfully enters the instance. diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index efb3810d00c..a63ed66446e 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -365,7 +365,7 @@ LootItem::LootItem(LootStoreItem const& li) conditions = li.conditions; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemid); - freeforall = proto && (proto->GetFlags() & ITEM_PROTO_FLAG_PARTY_LOOT); + freeforall = proto && (proto->GetFlags() & ITEM_FLAG_PARTY_LOOT); follow_loot_rules = proto && (proto->FlagsCu & ITEM_FLAGS_CU_FOLLOW_LOOT_RULES); needs_quest = li.needs_quest; @@ -392,14 +392,14 @@ bool LootItem::AllowedForPlayer(Player const* player) const return false; // not show loot for players without profession or those who already know the recipe - if ((pProto->GetFlags() & ITEM_PROTO_FLAG_SMART_LOOT) && (!player->HasSkill(pProto->GetRequiredSkill()) || player->HasSpell(pProto->Effects[1]->SpellID))) + if ((pProto->GetFlags() & ITEM_FLAG_SMART_LOOT) && (!player->HasSkill(pProto->GetRequiredSkill()) || player->HasSpell(pProto->Effects[1]->SpellID))) return false; // not show loot for not own team - if ((pProto->GetFlags2() & ITEM_FLAGS_EXTRA_HORDE_ONLY) && player->GetTeam() != HORDE) + if ((pProto->GetFlags2() & ITEM_FLAG2_HORDE_ONLY) && player->GetTeam() != HORDE) return false; - if ((pProto->GetFlags2() & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE) + if ((pProto->GetFlags2() & ITEM_FLAG2_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE) return false; // check quest requirements @@ -447,7 +447,7 @@ void Loot::AddItem(LootStoreItem const& item) // non-conditional one-player only items are counted here, // free for all items are counted in FillFFALoot(), // non-ffa conditionals are counted in FillNonQuestNonFFAConditionalLoot() - if (!item.needs_quest && item.conditions.empty() && !(proto->GetFlags() & ITEM_PROTO_FLAG_PARTY_LOOT)) + if (!item.needs_quest && item.conditions.empty() && !(proto->GetFlags() & ITEM_FLAG_PARTY_LOOT)) ++unlootedCount; } } @@ -1651,7 +1651,7 @@ void LoadLootTemplates_Item() // remove real entries and check existence loot ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) - if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end() && itr->second.GetFlags() & ITEM_PROTO_FLAG_OPENABLE) + if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end() && itr->second.GetFlags() & ITEM_FLAG_OPENABLE) lootIdSet.erase(itr->second.GetId()); // output error for any still listed (not referenced from appropriate table) ids @@ -1676,7 +1676,7 @@ void LoadLootTemplates_Milling() ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { - if (!(itr->second.GetFlags() & ITEM_PROTO_FLAG_MILLABLE)) + if (!(itr->second.GetFlags() & ITEM_FLAG_MILLABLE)) continue; if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end()) @@ -1739,7 +1739,7 @@ void LoadLootTemplates_Prospecting() ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { - if (!(itr->second.GetFlags() & ITEM_PROTO_FLAG_PROSPECTABLE)) + if (!(itr->second.GetFlags() & ITEM_FLAG_PROSPECTABLE)) continue; if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end()) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index c2bec063223..108b7cadfe1 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -40,7 +40,7 @@ #include "Weather.h" u_map_magic MapMagic = { {'M','A','P','S'} }; -u_map_magic MapVersionMagic = { {'v','1','.','4'} }; +u_map_magic MapVersionMagic = { {'v','1','.','5'} }; u_map_magic MapAreaMagic = { {'A','R','E','A'} }; u_map_magic MapHeightMagic = { {'M','H','G','T'} }; u_map_magic MapLiquidMagic = { {'M','L','I','Q'} }; @@ -78,33 +78,29 @@ Map::~Map() bool Map::ExistMap(uint32 mapid, int gx, int gy) { - int len = sWorld->GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1; - char* fileName = new char[len]; - snprintf(fileName, len, (char *)(sWorld->GetDataPath() + "maps/%03u%02u%02u.map").c_str(), mapid, gx, gy); + std::string fileName = Trinity::StringFormat("%smaps/%04u_%02u_%02u.map", sWorld->GetDataPath().c_str(), mapid, gx, gy); bool ret = false; - FILE* pf = fopen(fileName, "rb"); - - if (!pf) + FILE* file = fopen(fileName.c_str(), "rb"); + if (!file) { - TC_LOG_ERROR("maps", "Map file '%s' does not exist!", fileName); + TC_LOG_ERROR("maps", "Map file '%s' does not exist!", fileName.c_str()); TC_LOG_ERROR("maps", "Please place MAP-files (*.map) in the appropriate directory (%s), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath()+"maps/").c_str()); } else { map_fileheader header; - if (fread(&header, sizeof(header), 1, pf) == 1) + if (fread(&header, sizeof(header), 1, file) == 1) { if (header.mapMagic.asUInt != MapMagic.asUInt || header.versionMagic.asUInt != MapVersionMagic.asUInt) TC_LOG_ERROR("maps", "Map file '%s' is from an incompatible map version (%.*s %.*s), %.*s %.*s is expected. Please recreate using the mapextractor.", - fileName, 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar); + fileName.c_str(), 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar); else ret = true; } - fclose(pf); + fclose(file); } - delete[] fileName; return ret; } @@ -191,16 +187,12 @@ void Map::LoadMap(int gx, int gy, bool reload) } // map file name - char* tmp = NULL; - int len = sWorld->GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1; - tmp = new char[len]; - snprintf(tmp, len, (char *)(sWorld->GetDataPath() + "maps/%03u%02u%02u.map").c_str(), GetId(), gx, gy); - TC_LOG_DEBUG("maps", "Loading map %s", tmp); + std::string fileName = Trinity::StringFormat("%smaps/%04u_%02u_%02u.map", sWorld->GetDataPath().c_str(), GetId(), gx, gy); + TC_LOG_DEBUG("maps", "Loading map %s", fileName.c_str()); // loading data GridMaps[gx][gy] = new GridMap(); - if (!GridMaps[gx][gy]->loadData(tmp)) - TC_LOG_ERROR("maps", "Error loading map file: \n %s\n", tmp); - delete[] tmp; + if (!GridMaps[gx][gy]->loadData(fileName.c_str())) + TC_LOG_ERROR("maps", "Error loading map file: %s", fileName.c_str()); sScriptMgr->OnLoadGridMap(this, GridMaps[gx][gy], gx, gy); } @@ -392,7 +384,7 @@ template<> void Map::DeleteFromWorld(Player* player) { sObjectAccessor->RemoveObject(player); - sObjectAccessor->RemoveUpdateObject(player); /// @todo I do not know why we need this, it should be removed in ~Object anyway + RemoveUpdateObject(player); /// @todo I do not know why we need this, it should be removed in ~Object anyway delete player; } @@ -456,8 +448,7 @@ bool Map::EnsureGridLoaded(const Cell &cell) setGridObjectDataLoaded(true, cell.GridX(), cell.GridY()); - ObjectGridLoader loader(*grid, this, cell); - loader.LoadN(); + LoadGridObjects(grid, cell); // Add resurrectable corpses to world object list in grid sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this); @@ -468,12 +459,18 @@ bool Map::EnsureGridLoaded(const Cell &cell) return false; } +void Map::LoadGridObjects(NGridType* grid, Cell const& cell) +{ + ObjectGridLoader loader(*grid, this, cell); + loader.LoadN(); +} + void Map::LoadGrid(float x, float y) { EnsureGridLoaded(Cell(x, y)); } -bool Map::AddPlayerToMap(Player* player) +bool Map::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) { CellCoord cellCoord = Trinity::ComputeCellCoord(player->GetPositionX(), player->GetPositionY()); if (!cellCoord.IsCoordValid()) @@ -491,13 +488,16 @@ bool Map::AddPlayerToMap(Player* player) player->SetMap(this); player->AddToWorld(); - SendInitSelf(player); + if (initPlayer) + SendInitSelf(player); + SendInitTransports(player); SendZoneDynamicInfo(player); - player->m_clientGUIDs.clear(); - player->UpdateObjectVisibility(false); + if (initPlayer) + player->m_clientGUIDs.clear(); + player->UpdateObjectVisibility(false); player->SendUpdatePhasing(); sScriptMgr->OnPlayerEnterMap(this, player); @@ -698,6 +698,8 @@ void Map::Update(const uint32 t_diff) obj->Update(t_diff); } + SendObjectUpdates(); + ///- Process necessary scripts if (!m_scriptSchedule.empty()) { @@ -2591,8 +2593,40 @@ inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y) i_grids[x][y] = grid; } +void Map::SendObjectUpdates() +{ + UpdateDataMapType update_players; + + while (!_updateObjects.empty()) + { + Object* obj = *_updateObjects.begin(); + ASSERT(obj && obj->IsInWorld()); + _updateObjects.erase(_updateObjects.begin()); + obj->BuildUpdate(update_players); + } + + WorldPacket packet; // here we allocate a std::vector with a size of 0x10000 + for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) + { + iter->second.BuildPacket(&packet); + iter->first->GetSession()->SendPacket(&packet); + packet.clear(); // clean the string + } +} + void Map::DelayedUpdate(const uint32 t_diff) { + for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();) + { + Transport* transport = *_transportsUpdateIter; + ++_transportsUpdateIter; + + if (!transport->IsInWorld()) + continue; + + transport->DelayedUpdate(t_diff); + } + RemoveAllObjectsInRemoveList(); // Don't unload grids if it's battleground, since we may have manually added GOs, creatures, those doesn't load from DB at grid re-load ! @@ -2775,7 +2809,7 @@ void Map::AddToActive(Creature* c) AddToActiveHelper(c); // also not allow unloading spawn grid to prevent creating creature clone at load - if (!c->IsPet() && c->GetDBTableGUIDLow()) + if (!c->IsPet() && c->GetSpawnId()) { float x, y, z; c->GetRespawnPosition(x, y, z); @@ -2806,7 +2840,7 @@ void Map::RemoveFromActive(Creature* c) RemoveFromActiveHelper(c); // also allow unloading spawn grid - if (!c->IsPet() && c->GetDBTableGUIDLow()) + if (!c->IsPet() && c->GetSpawnId()) { float x, y, z; c->GetRespawnPosition(x, y, z); @@ -2932,7 +2966,7 @@ bool InstanceMap::CanEnter(Player* player) /* Do map specific checks and add the player to the map if successful. */ -bool InstanceMap::AddPlayerToMap(Player* player) +bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) { /// @todo Not sure about checking player level: already done in HandleAreaTriggerOpcode // GMs still can teleport player in instance. @@ -3042,7 +3076,7 @@ bool InstanceMap::AddPlayerToMap(Player* player) } // this will acquire the same mutex so it cannot be in the previous block - Map::AddPlayerToMap(player); + Map::AddPlayerToMap(player, initPlayer); if (i_data) i_data->OnPlayerEnter(player); @@ -3188,8 +3222,11 @@ void InstanceMap::UnloadAll() { ASSERT(!HavePlayers()); - if (m_resetAfterUnload == true) + if (m_resetAfterUnload) + { DeleteRespawnTimes(); + DeleteCorpseData(); + } Map::UnloadAll(); } @@ -3297,7 +3334,7 @@ bool BattlegroundMap::CanEnter(Player* player) return Map::CanEnter(player); } -bool BattlegroundMap::AddPlayerToMap(Player* player) +bool BattlegroundMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) { { std::lock_guard<std::mutex> lock(_mapLock); @@ -3307,7 +3344,7 @@ bool BattlegroundMap::AddPlayerToMap(Player* player) // reset instance validity, battleground maps do not homebind player->m_InstanceValid = true; } - return Map::AddPlayerToMap(player); + return Map::AddPlayerToMap(player, initPlayer); } void BattlegroundMap::RemovePlayerFromMap(Player* player, bool remove) @@ -3330,17 +3367,37 @@ void BattlegroundMap::RemoveAllPlayers() player->TeleportTo(player->GetBattlegroundEntryPoint()); } -Creature* Map::GetCreature(ObjectGuid guid) +AreaTrigger* Map::GetAreaTrigger(ObjectGuid const& guid) +{ + return _objectsStore.Find<AreaTrigger>(guid); +} + +Corpse* Map::GetCorpse(ObjectGuid const& guid) +{ + return _objectsStore.Find<Corpse>(guid); +} + +Creature* Map::GetCreature(ObjectGuid const& guid) +{ + return _objectsStore.Find<Creature>(guid); +} + +DynamicObject* Map::GetDynamicObject(ObjectGuid const& guid) { - return ObjectAccessor::GetObjectInMap(guid, this, (Creature*)NULL); + return _objectsStore.Find<DynamicObject>(guid); } -GameObject* Map::GetGameObject(ObjectGuid guid) +GameObject* Map::GetGameObject(ObjectGuid const& guid) { - return ObjectAccessor::GetObjectInMap(guid, this, (GameObject*)NULL); + return _objectsStore.Find<GameObject>(guid); } -Transport* Map::GetTransport(ObjectGuid guid) +Pet* Map::GetPet(ObjectGuid const& guid) +{ + return _objectsStore.Find<Pet>(guid); +} + +Transport* Map::GetTransport(ObjectGuid const& guid) { if (!guid.IsMOTransport()) return NULL; @@ -3349,11 +3406,6 @@ Transport* Map::GetTransport(ObjectGuid guid) return go ? go->ToTransport() : NULL; } -DynamicObject* Map::GetDynamicObject(ObjectGuid guid) -{ - return ObjectAccessor::GetObjectInMap(guid, this, (DynamicObject*)NULL); -} - void Map::UpdateIteratorBack(Player* player) { if (m_mapRefIter == player->GetMapRef()) @@ -3490,6 +3542,72 @@ time_t Map::GetLinkedRespawnTime(ObjectGuid guid) const return time_t(0); } +void Map::LoadCorpseData() +{ + std::unordered_map<uint64, std::unordered_set<uint32>> phases; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_PHASES); + stmt->setUInt32(0, GetId()); + + // 0 1 + // SELECT OwnerGuid, PhaseId FROM corpse_phases cp LEFT JOIN corpse c ON cp.OwnerGuid = c.guid WHERE c.mapId = ? + PreparedQueryResult phaseResult = CharacterDatabase.Query(stmt); + if (phaseResult) + { + do + { + Field* fields = phaseResult->Fetch(); + uint64 guid = fields[0].GetUInt64(); + uint32 phaseId = fields[1].GetUInt32(); + + phases[guid].insert(phaseId); + + } while (phaseResult->NextRow()); + } + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES); + stmt->setUInt32(0, GetId()); + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? + PreparedQueryResult result = CharacterDatabase.Query(stmt); + if (!result) + return; + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + CorpseType type = CorpseType(fields[12].GetUInt8()); + ObjectGuid::LowType guid = fields[14].GetUInt64(); + if (type >= MAX_CORPSE_TYPE || type == CORPSE_BONES) + { + TC_LOG_ERROR("misc", "Corpse (guid: " UI64FMTD ") have wrong corpse type (%u), not loading.", guid, type); + continue; + } + + Corpse* corpse = new Corpse(type); + if (!corpse->LoadCorpseFromDB(GenerateLowGuid<HighGuid::Corpse>(), fields)) + { + delete corpse; + continue; + } + + for (auto phaseId : phases[guid]) + corpse->SetInPhase(phaseId, false, true); + + sObjectAccessor->AddCorpse(corpse); + ++count; + } while (result->NextRow()); +} + +void Map::DeleteCorpseData() +{ + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSES_FROM_MAP); + stmt->setUInt32(0, GetId()); + CharacterDatabase.Execute(stmt); +} + void Map::SendZoneDynamicInfo(Player* player) { uint32 zoneId = GetZoneId(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 752953091f8..a2faa8cc0a0 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -34,6 +34,7 @@ #include <bitset> #include <list> +#include <memory> class Unit; class WorldPacket; @@ -212,12 +213,7 @@ public: ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0); }; -// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif struct InstanceTemplate { @@ -242,11 +238,7 @@ struct ZoneDynamicInfo uint32 LightFadeInTime; }; -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif #define MAX_HEIGHT 100000.0f // can be use for find ground height at surface #define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE @@ -258,6 +250,8 @@ typedef std::map<ObjectGuid::LowType/*leaderDBGUID*/, CreatureGroup*> CreatureGr typedef std::unordered_map<uint32 /*zoneId*/, ZoneDynamicInfo> ZoneDynamicInfoMap; +typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer; + class Map : public GridRefManager<NGridType> { friend class MapReference; @@ -280,7 +274,7 @@ class Map : public GridRefManager<NGridType> return false; } - virtual bool AddPlayerToMap(Player*); + virtual bool AddPlayerToMap(Player* player, bool initPlayer = true); virtual void RemovePlayerFromMap(Player*, bool); template<class T> bool AddToMap(T *); template<class T> void RemoveFromMap(T *, bool); @@ -400,6 +394,7 @@ class Map : public GridRefManager<NGridType> bool IsBattleground() const { return i_mapEntry && i_mapEntry->IsBattleground(); } bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } bool IsBattlegroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattlegroundOrArena(); } + bool IsGarrison() const { return i_mapEntry && i_mapEntry->IsGarrison(); } bool GetEntrancePos(int32 &mapid, float &x, float &y) { if (!i_mapEntry) @@ -453,10 +448,21 @@ class Map : public GridRefManager<NGridType> TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = NULL, uint32 duration = 0, Unit* summoner = NULL, uint32 spellId = 0, uint32 vehId = 0); void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = NULL); - Creature* GetCreature(ObjectGuid guid); - GameObject* GetGameObject(ObjectGuid guid); - Transport* GetTransport(ObjectGuid guid); - DynamicObject* GetDynamicObject(ObjectGuid guid); + AreaTrigger* GetAreaTrigger(ObjectGuid const& guid); + Corpse* GetCorpse(ObjectGuid const& guid); + Creature* GetCreature(ObjectGuid const& guid); + DynamicObject* GetDynamicObject(ObjectGuid const& guid); + GameObject* GetGameObject(ObjectGuid const& guid); + Pet* GetPet(ObjectGuid const& guid); + Transport* GetTransport(ObjectGuid const& guid); + + MapStoredObjectTypesContainer& GetObjectsStore() { return _objectsStore; } + + typedef std::unordered_multimap<ObjectGuid::LowType, Creature*> CreatureBySpawnIdContainer; + CreatureBySpawnIdContainer& GetCreatureBySpawnIdStore() { return _creatureBySpawnIdStore; } + + typedef std::unordered_multimap<ObjectGuid::LowType, GameObject*> GameObjectBySpawnIdContainer; + GameObjectBySpawnIdContainer& GetGameObjectBySpawnIdStore() { return _gameobjectBySpawnIdStore; } MapInstanced* ToMapInstanced() { if (Instanceable()) return reinterpret_cast<MapInstanced*>(this); return NULL; } MapInstanced const* ToMapInstanced() const { if (Instanceable()) return reinterpret_cast<MapInstanced const*>(this); return NULL; } @@ -505,6 +511,8 @@ class Map : public GridRefManager<NGridType> void RemoveGORespawnTime(ObjectGuid::LowType dbGuid); void LoadRespawnTimes(); void DeleteRespawnTimes(); + void LoadCorpseData(); + void DeleteCorpseData(); static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId); @@ -519,6 +527,23 @@ class Map : public GridRefManager<NGridType> void UpdateAreaDependentAuras(); + template<HighGuid high> + inline ObjectGuid::LowType GenerateLowGuid() + { + static_assert(ObjectGuidTraits<high>::MapSpecific, "Only map specific guid can be generated in Map context"); + return GetGuidSequenceGenerator<high>().Generate(); + } + + void AddUpdateObject(Object* obj) + { + _updateObjects.insert(obj); + } + + void RemoveUpdateObject(Object* obj) + { + _updateObjects.erase(obj); + } + private: void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); @@ -573,8 +598,11 @@ class Map : public GridRefManager<NGridType> void UpdateActiveCells(const float &x, const float &y, const uint32 t_diff); + void SendObjectUpdates(); + protected: void SetUnloadReferenceLock(const GridCoord &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); } + virtual void LoadGridObjects(NGridType* grid, Cell const& cell); std::mutex _mapLock; std::mutex _gridLock; @@ -665,6 +693,23 @@ class Map : public GridRefManager<NGridType> ZoneDynamicInfoMap _zoneDynamicInfo; uint32 _defaultLight; + + template<HighGuid high> + inline ObjectGuidGeneratorBase& GetGuidSequenceGenerator() + { + auto itr = _guidGenerators.find(high); + if (itr == _guidGenerators.end()) + itr = _guidGenerators.insert(std::make_pair(high, std::unique_ptr<ObjectGuidGenerator<high>>(new ObjectGuidGenerator<high>()))).first; + + return *itr->second; + } + + std::map<HighGuid, std::unique_ptr<ObjectGuidGeneratorBase>> _guidGenerators; + MapStoredObjectTypesContainer _objectsStore; + CreatureBySpawnIdContainer _creatureBySpawnIdStore; + GameObjectBySpawnIdContainer _gameobjectBySpawnIdStore; + + std::unordered_set<Object*> _updateObjects; }; enum InstanceResetMethod @@ -682,7 +727,7 @@ class InstanceMap : public Map public: InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent); ~InstanceMap(); - bool AddPlayerToMap(Player*) override; + bool AddPlayerToMap(Player* player, bool initPlayer = true) override; void RemovePlayerFromMap(Player*, bool) override; void Update(const uint32) override; void CreateInstanceData(bool load); @@ -712,7 +757,7 @@ class BattlegroundMap : public Map BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode); ~BattlegroundMap(); - bool AddPlayerToMap(Player*) override; + bool AddPlayerToMap(Player* player, bool initPlayer = true) override; void RemovePlayerFromMap(Player*, bool) override; bool CanEnter(Player* player) override; void SetUnload(); diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index cc0c99adc99..473e3163216 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -26,6 +26,7 @@ #include "World.h" #include "Group.h" #include "Player.h" +#include "GarrisonMap.h" MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DIFFICULTY_NORMAL) { @@ -138,7 +139,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) } } } - else + else if (!IsGarrison()) { InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficultyID(GetEntry())); InstanceSave* pSave = pBind ? pBind->save : NULL; @@ -180,6 +181,13 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) map = CreateInstance(newInstanceId, NULL, diff); } } + else + { + newInstanceId = player->GetGUID().GetCounter(); + map = FindInstanceMap(newInstanceId); + if (!map) + map = CreateGarrison(newInstanceId, player); + } return map; } @@ -212,6 +220,7 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, ASSERT(map->IsDungeon()); map->LoadRespawnTimes(); + map->LoadCorpseData(); bool load_data = save != NULL; map->CreateInstanceData(load_data); @@ -236,6 +245,17 @@ BattlegroundMap* MapInstanced::CreateBattleground(uint32 InstanceId, Battlegroun return map; } +GarrisonMap* MapInstanced::CreateGarrison(uint32 instanceId, Player* owner) +{ + std::lock_guard<std::mutex> lock(_mapLock); + + GarrisonMap* map = new GarrisonMap(GetId(), GetGridExpiry(), instanceId, this, owner->GetGUID()); + ASSERT(map->IsGarrison()); + + m_InstancedMaps[instanceId] = map; + return map; +} + // increments the iterator after erase bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) { diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h index c385215ba76..e487957ed6e 100644 --- a/src/server/game/Maps/MapInstanced.h +++ b/src/server/game/Maps/MapInstanced.h @@ -23,6 +23,8 @@ #include "InstanceSaveMgr.h" #include "DBCEnums.h" +class GarrisonMap; + class MapInstanced : public Map { friend class MapManager; @@ -66,6 +68,7 @@ class MapInstanced : public Map private: InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty); BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg); + GarrisonMap* CreateGarrison(uint32 instanceId, Player* owner); InstancedMaps m_InstancedMaps; diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index d49bde4415d..e18a98e8429 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -81,6 +81,7 @@ Map* MapManager::CreateBaseMap(uint32 id) { map = new Map(id, i_gridCleanUpDelay, 0, DIFFICULTY_NONE); map->LoadRespawnTimes(); + map->LoadCorpseData(); } i_maps[id] = map; @@ -253,8 +254,6 @@ void MapManager::Update(uint32 diff) for (iter = i_maps.begin(); iter != i_maps.end(); ++iter) iter->second->DelayedUpdate(uint32(i_timer.GetCurrent())); - sObjectAccessor->Update(uint32(i_timer.GetCurrent())); - i_timer.SetCurrent(0); } diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index dc6c0bb642f..98bc1e0ad22 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -21,6 +21,7 @@ #include "Object.h" #include "Map.h" +#include "MapInstanced.h" #include "GridStates.h" #include "MapUpdater.h" @@ -125,7 +126,13 @@ class MapManager MapUpdater * GetMapUpdater() { return &m_updater; } - private: + template<typename Worker> + void DoForAllMaps(Worker&& worker); + + template<typename Worker> + void DoForAllMapsWithMapId(uint32 mapId, Worker&& worker); + +private: typedef std::unordered_map<uint32, Map*> MapMapType; typedef std::vector<bool> InstanceIds; @@ -150,5 +157,45 @@ class MapManager uint32 _nextInstanceId; MapUpdater m_updater; }; + +template<typename Worker> +void MapManager::DoForAllMaps(Worker&& worker) +{ + std::lock_guard<std::mutex> lock(_mapsLock); + + for (auto& mapPair : i_maps) + { + Map* map = mapPair.second; + if (MapInstanced* mapInstanced = map->ToMapInstanced()) + { + MapInstanced::InstancedMaps& instances = mapInstanced->GetInstancedMaps(); + for (auto& instancePair : instances) + worker(instancePair.second); + } + else + worker(map); + } +} + +template<typename Worker> +inline void MapManager::DoForAllMapsWithMapId(uint32 mapId, Worker&& worker) +{ + std::lock_guard<std::mutex> lock(_mapsLock); + + auto itr = i_maps.find(mapId); + if (itr != i_maps.end()) + { + Map* map = itr->second; + if (MapInstanced* mapInstanced = map->ToMapInstanced()) + { + MapInstanced::InstancedMaps& instances = mapInstanced->GetInstancedMaps(); + for (auto& p : instances) + worker(p.second); + } + else + worker(map); + } +} + #define sMapMgr MapManager::instance() #endif diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp index 015665d6430..8f9d65e749b 100644 --- a/src/server/game/Maps/TransportMgr.cpp +++ b/src/server/game/Maps/TransportMgr.cpp @@ -384,7 +384,7 @@ Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid float o = tInfo->keyFrames.begin()->InitialOrientation; // initialize the gameobject base - ObjectGuid::LowType guidLow = guid ? guid : sObjectMgr->GetGenerator<HighGuid::Transport>()->Generate(); + ObjectGuid::LowType guidLow = guid ? guid : sObjectMgr->GetGenerator<HighGuid::Transport>().Generate(); if (!trans->Create(guidLow, entry, mapId, x, y, z, o, 255)) { delete trans; @@ -414,7 +414,7 @@ Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid trans->m_zoneScript = map->ToInstanceMap()->GetInstanceScript(); // Passengers will be loaded once a player is near - + HashMapHolder<Transport>::Insert(trans); trans->GetMap()->AddToMap<Transport>(trans); return trans; } diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 28705b36c65..ed004c6174d 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -1199,8 +1199,8 @@ enum SpellEffectName SPELL_EFFECT_LOOT = 189, // NYI, lootid in MiscValue ? SPELL_EFFECT_190 = 190, SPELL_EFFECT_TELEPORT_TO_DIGSITE = 191, // NYI - SPELL_EFFECT_192 = 192, - SPELL_EFFECT_193 = 193, + SPELL_EFFECT_UNCAGE_BATTLEPET = 192, + SPELL_EFFECT_START_PET_BATTLE = 193, SPELL_EFFECT_194 = 194, SPELL_EFFECT_195 = 195, SPELL_EFFECT_196 = 196, @@ -1211,53 +1211,53 @@ enum SpellEffectName SPELL_EFFECT_ENABLE_BATTLE_PETS = 201, // NYI SPELL_EFFECT_202 = 202, SPELL_EFFECT_203 = 203, - SPELL_EFFECT_204 = 204, - SPELL_EFFECT_205 = 205, + SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY = 204, + SPELL_EFFECT_LAUNCH_QUEST_CHOICE = 205, SPELL_EFFECT_206 = 206, - SPELL_EFFECT_207 = 207, + SPELL_EFFECT_LAUNCH_QUEST_TASK = 207, // Starts one of the "progress bar" quests SPELL_EFFECT_208 = 208, SPELL_EFFECT_209 = 209, - SPELL_EFFECT_210 = 210, - SPELL_EFFECT_211 = 211, + SPELL_EFFECT_LEARN_GARRISON_BUILDING = 210, + SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION = 211, SPELL_EFFECT_212 = 212, SPELL_EFFECT_213 = 213, - SPELL_EFFECT_214 = 214, - SPELL_EFFECT_215 = 215, - SPELL_EFFECT_216 = 216, - SPELL_EFFECT_217 = 217, + SPELL_EFFECT_CREATE_GARRISON = 214, + SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS = 215, // Unlocks boosted players' spells (ChrUpgrade*.db2) + SPELL_EFFECT_CREATE_SHIPMENT = 216, + SPELL_EFFECT_UPGRADE_GARRISON = 217, SPELL_EFFECT_218 = 218, SPELL_EFFECT_219 = 219, - SPELL_EFFECT_220 = 220, + SPELL_EFFECT_ADD_GARRISON_FOLLOWER = 220, SPELL_EFFECT_221 = 221, - SPELL_EFFECT_222 = 222, - SPELL_EFFECT_223 = 223, - SPELL_EFFECT_224 = 224, - SPELL_EFFECT_225 = 225, + SPELL_EFFECT_CREATE_HEIRLOOM_ITEM = 222, + SPELL_EFFECT_CHANGE_ITEM_BONUSES = 223, + SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING = 224, + SPELL_EFFECT_GRANT_BATTLEPET_LEVEL = 225, SPELL_EFFECT_226 = 226, SPELL_EFFECT_227 = 227, SPELL_EFFECT_228 = 228, - SPELL_EFFECT_229 = 229, - SPELL_EFFECT_230 = 230, - SPELL_EFFECT_231 = 231, - SPELL_EFFECT_232 = 232, - SPELL_EFFECT_233 = 233, + SPELL_EFFECT_SET_FOLLOWER_QUALITY = 229, + SPELL_EFFECT_INCREASE_FOLLOWER_ITEM_LEVEL = 230, + SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE = 231, + SPELL_EFFECT_REMOVE_PHASE = 232, + SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES = 233, SPELL_EFFECT_234 = 234, SPELL_EFFECT_235 = 235, - SPELL_EFFECT_236 = 236, - SPELL_EFFECT_237 = 237, - SPELL_EFFECT_238 = 238, - SPELL_EFFECT_239 = 239, + SPELL_EFFECT_GIVE_EXPERIENCE = 236, // Increases players XP + SPELL_EFFECT_GIVE_RESTED_EXPERIENCE_BONUS = 237, + SPELL_EFFECT_INCREASE_SKILL = 238, + SPELL_EFFECT_END_GARRISON_BUILDING_CONSTRUCTION = 239, // Instantly finishes building construction SPELL_EFFECT_240 = 240, SPELL_EFFECT_241 = 241, SPELL_EFFECT_242 = 242, - SPELL_EFFECT_243 = 243, - SPELL_EFFECT_244 = 244, - SPELL_EFFECT_245 = 245, - SPELL_EFFECT_246 = 246, - SPELL_EFFECT_247 = 247, - SPELL_EFFECT_248 = 248, + SPELL_EFFECT_APPLY_ENCHANT_ILLUSION = 243, + SPELL_EFFECT_LEARN_FOLLOWER_ABILITY = 244, + SPELL_EFFECT_UPGRADE_HEIRLOOM = 245, + SPELL_EFFECT_FINISH_GARRISON_MISSION = 246, + SPELL_EFFECT_ADD_GARRISON_MISSION = 247, + SPELL_EFFECT_FINISH_SHIPMENT = 248, SPELL_EFFECT_249 = 249, - SPELL_EFFECT_250 = 250, + SPELL_EFFECT_TAKE_SCREENSHOT = 250, // Serverside marker for selfie screenshot - achievement check TOTAL_SPELL_EFFECTS = 251, }; @@ -2124,11 +2124,12 @@ enum GameObjectFlags enum GameObjectDynamicLowFlags { - GO_DYNFLAG_LO_ACTIVATE = 0x01, // enables interaction with GO - GO_DYNFLAG_LO_ANIMATE = 0x02, // possibly more distinct animation of GO - GO_DYNFLAG_LO_NO_INTERACT = 0x04, // appears to disable interaction (not fully verified) - GO_DYNFLAG_LO_SPARKLE = 0x08, // makes GO sparkle - GO_DYNFLAG_LO_STOPPED = 0x10 // Transport is stopped + GO_DYNFLAG_LO_HIDE_MODEL = 0x01, // Object model is not shown with this flag + GO_DYNFLAG_LO_ACTIVATE = 0x02, // enables interaction with GO + GO_DYNFLAG_LO_ANIMATE = 0x04, // possibly more distinct animation of GO + GO_DYNFLAG_LO_NO_INTERACT = 0x08, // appears to disable interaction (not fully verified) + GO_DYNFLAG_LO_SPARKLE = 0x10, // makes GO sparkle + GO_DYNFLAG_LO_STOPPED = 0x20 // Transport is stopped }; enum GameObjectDestructibleState @@ -4881,7 +4882,7 @@ enum PartyResult }; const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP' -#define MMAP_VERSION 6 +#define MMAP_VERSION 7 struct MmapTileHeader { @@ -4921,15 +4922,15 @@ enum DiminishingLevels enum TokenResult { - TOKEN_RESULT_SUCCESS = 1, - TOKEN_RESULT_ERROR_DISABLED = 2, - TOKEN_RESULT_ERROR_OTHER = 3, - TOKEN_RESULT_ERROR_NONE_FOR_SALE = 4, - TOKEN_RESULT_ERROR_TOO_MANY_TOKENS = 5, - TOKEN_RESULT_SUCCESS_NO = 6, - TOKEN_RESULT_ERROR_TRANSACTION_IN_PROGRESS = 7, - TOKEN_RESULT_ERROR_AUCTIONABLE_TOKEN_OWNED = 8, - TOKEN_RESULT_ERROR_TRIAL_RESTRICTED = 9 + TOKEN_RESULT_SUCCESS = 0, + TOKEN_RESULT_ERROR_DISABLED = 1, + TOKEN_RESULT_ERROR_OTHER = 2, + TOKEN_RESULT_ERROR_NONE_FOR_SALE = 3, + TOKEN_RESULT_ERROR_TOO_MANY_TOKENS = 4, + TOKEN_RESULT_SUCCESS_NO = 5, + TOKEN_RESULT_ERROR_TRANSACTION_IN_PROGRESS = 6, + TOKEN_RESULT_ERROR_AUCTIONABLE_TOKEN_OWNED = 7, + TOKEN_RESULT_ERROR_TRIAL_RESTRICTED = 8 }; #endif diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 0222087c168..47e8f18810c 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -42,7 +42,7 @@ void WaypointMovementGenerator<Creature>::LoadPath(Creature* creature) if (!i_path) { // No path id found for entry - TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::LoadPath: creature %s (%s DB GUID: " UI64FMTD ") doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), creature->GetDBTableGUIDLow(), path_id); + TC_LOG_ERROR("sql.sql", "WaypointMovementGenerator::LoadPath: creature %s (%s DB GUID: " UI64FMTD ") doesn't have waypoint path id: %u", creature->GetName().c_str(), creature->GetGUID().ToString().c_str(), creature->GetSpawnId(), path_id); return; } diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h index d93c19ff869..acd0c94bbf1 100644 --- a/src/server/game/Movement/Spline/MoveSplineFlag.h +++ b/src/server/game/Movement/Spline/MoveSplineFlag.h @@ -23,11 +23,7 @@ namespace Movement { -#if defined( __GNUC__ ) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif class MoveSplineFlag { @@ -36,12 +32,12 @@ namespace Movement { None = 0x00000000, // x00-x07 used as animation Ids storage in pair with Animation flag - Unknown0 = 0x00000008, // NOT VERIFIED + Unknown0 = 0x00000008, // NOT VERIFIED - does someting related to falling/fixed orientation FallingSlow = 0x00000010, Done = 0x00000020, Falling = 0x00000040, // Affects elevation computation, can't be combined with Parabolic flag No_Spline = 0x00000080, - Unknown2 = 0x00000100, // NOT VERIFIED + Unknown1 = 0x00000100, // NOT VERIFIED Flying = 0x00000200, // Smooth movement(Catmullrom interpolation mode), flying animation OrientationFixed = 0x00000400, // Model orientation fixed Catmullrom = 0x00000800, // Used Catmullrom interpolation mode @@ -50,21 +46,21 @@ namespace Movement Frozen = 0x00004000, // Will never arrive TransportEnter = 0x00008000, TransportExit = 0x00010000, - Unknown3 = 0x00020000, // NOT VERIFIED - Unknown4 = 0x00040000, // NOT VERIFIED + Unknown2 = 0x00020000, // NOT VERIFIED + Unknown3 = 0x00040000, // NOT VERIFIED OrientationInversed = 0x00080000, SmoothGroundPath = 0x00100000, Walkmode = 0x00200000, UncompressedPath = 0x00400000, - Unknown6 = 0x00800000, // NOT VERIFIED - Animation = 0x01000000, // Plays animation after some time passed - Parabolic = 0x02000000, // Affects elevation computation, can't be combined with Falling flag - Final_Point = 0x04000000, - Final_Target = 0x08000000, - Final_Angle = 0x10000000, - Unknown7 = 0x20000000, // NOT VERIFIED - Unknown8 = 0x40000000, // NOT VERIFIED - Unknown9 = 0x80000000, // NOT VERIFIED + Unknown4 = 0x00800000, // NOT VERIFIED + Unknown5 = 0x01000000, // NOT VERIFIED + Animation = 0x02000000, // Plays animation after some time passed + Parabolic = 0x04000000, // Affects elevation computation, can't be combined with Falling flag + Final_Point = 0x08000000, + Final_Target = 0x10000000, + Final_Angle = 0x20000000, + Unknown6 = 0x40000000, // NOT VERIFIED + Unknown7 = 0x80000000, // NOT VERIFIED // Masks Mask_Final_Facing = Final_Point | Final_Target | Final_Angle, @@ -73,7 +69,7 @@ namespace Movement // flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done, // Unused, not suported flags - Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown0|Unknown2|Unknown3|Unknown4|Unknown6|Unknown7|Unknown8|Unknown9 + Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown0|Unknown1|Unknown2|Unknown3|Unknown4|Unknown5|Unknown6|Unknown7 }; inline uint32& raw() { return (uint32&)*this; } @@ -118,7 +114,7 @@ namespace Movement bool done : 1; bool falling : 1; bool no_spline : 1; - bool unknown2 : 1; + bool unknown1 : 1; bool flying : 1; bool orientationFixed : 1; bool catmullrom : 1; @@ -127,27 +123,23 @@ namespace Movement bool frozen : 1; bool transportEnter : 1; bool transportExit : 1; + bool unknown2 : 1; bool unknown3 : 1; - bool unknown4 : 1; bool orientationInversed : 1; bool smoothGroundPath : 1; bool walkmode : 1; bool uncompressedPath : 1; - bool unknown6 : 1; + bool unknown4 : 1; + bool unknown5 : 1; bool animation : 1; bool parabolic : 1; bool final_point : 1; bool final_target : 1; bool final_angle : 1; + bool unknown6 : 1; bool unknown7 : 1; - bool unknown8 : 1; - bool unknown9 : 1; }; -#if defined( __GNUC__ ) -#pragma pack() -#else #pragma pack(pop) -#endif } #endif // TRINITYSERVER_MOVESPLINEFLAG_H diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp index 6667672aee0..117891140da 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp @@ -49,7 +49,7 @@ class DefenseMessageBuilder }; OPvPCapturePoint::OPvPCapturePoint(OutdoorPvP* pvp): - m_capturePointGUID(), m_capturePoint(NULL), m_maxValue(0.0f), m_minValue(0.0f), m_maxSpeed(0), + m_capturePointSpawnId(), m_capturePoint(NULL), m_maxValue(0.0f), m_minValue(0.0f), m_maxSpeed(0), m_value(0), m_team(TEAM_NEUTRAL), m_OldState(OBJECTIVESTATE_NEUTRAL), m_State(OBJECTIVESTATE_NEUTRAL), m_neutralValuePct(0), m_PvP(pvp) { } @@ -85,31 +85,23 @@ void OPvPCapturePoint::SendChangePhase() SendUpdateWorldState(m_capturePoint->GetGOInfo()->controlZone.worldstate3, m_neutralValuePct); } -void OPvPCapturePoint::AddGO(uint32 type, uint32 mapId, ObjectGuid::LowType guid, uint32 entry /*= 0*/) +void OPvPCapturePoint::AddGO(uint32 type, ObjectGuid::LowType guid) { - if (!entry) - { - GameObjectData const* data = sObjectMgr->GetGOData(guid); - if (!data) - return; - entry = data->id; - } + GameObjectData const* data = sObjectMgr->GetGOData(guid); + if (!data) + return; - m_Objects[type] = ObjectGuid::Create<HighGuid::GameObject>(mapId, entry, guid); + m_Objects[type] = guid; m_ObjectTypes[m_Objects[type]] = type; } -void OPvPCapturePoint::AddCre(uint32 type, uint32 mapId, ObjectGuid::LowType guid, uint32 entry /*= 0*/) +void OPvPCapturePoint::AddCre(uint32 type, ObjectGuid::LowType guid) { - if (!entry) - { - CreatureData const* data = sObjectMgr->GetCreatureData(guid); - if (!data) - return; - entry = data->id; - } + CreatureData const* data = sObjectMgr->GetCreatureData(guid); + if (!data) + return; - m_Creatures[type] = ObjectGuid::Create<HighGuid::Creature>(mapId, entry, guid); + m_Creatures[type] = guid; m_CreatureTypes[m_Creatures[type]] = type; } @@ -117,7 +109,7 @@ bool OPvPCapturePoint::AddObject(uint32 type, uint32 entry, uint32 map, float x, { if (ObjectGuid::LowType guid = sObjectMgr->AddGOData(entry, map, x, y, z, o, 0, rotation0, rotation1, rotation2, rotation3)) { - AddGO(type, map, guid, entry); + AddGO(type, guid); return true; } @@ -128,7 +120,7 @@ bool OPvPCapturePoint::AddCreature(uint32 type, uint32 entry, uint32 map, float { if (ObjectGuid::LowType guid = sObjectMgr->AddCreData(entry, map, x, y, z, o, spawntimedelay)) { - AddCre(type, map, guid, entry); + AddCre(type, guid); return true; } @@ -147,8 +139,8 @@ bool OPvPCapturePoint::SetCapturePointData(uint32 entry, uint32 map, float x, fl return false; } - m_capturePointGUID = ObjectGuid::Create<HighGuid::GameObject>(map, entry, sObjectMgr->AddGOData(entry, map, x, y, z, o, 0, rotation0, rotation1, rotation2, rotation3)); - if (!m_capturePointGUID) + m_capturePointSpawnId = sObjectMgr->AddGOData(entry, map, x, y, z, o, 0, rotation0, rotation1, rotation2, rotation3); + if (!m_capturePointSpawnId) return false; // get the needed values from goinfo @@ -162,24 +154,25 @@ bool OPvPCapturePoint::SetCapturePointData(uint32 entry, uint32 map, float x, fl bool OPvPCapturePoint::DelCreature(uint32 type) { - if (!m_Creatures[type]) + ObjectGuid::LowType spawnId = m_Creatures[type]; + if (!spawnId) { TC_LOG_DEBUG("outdoorpvp", "opvp creature type %u was already deleted", type); return false; } - Creature* cr = HashMapHolder<Creature>::Find(m_Creatures[type]); - if (!cr) + auto bounds = m_PvP->GetMap()->GetCreatureBySpawnIdStore().equal_range(spawnId); + for (auto itr = bounds.first; itr != bounds.second;) { - // can happen when closing the core - m_Creatures[type].Clear(); - return false; + Creature* c = itr->second; + ++itr; + // Don't save respawn time + c->SetRespawnTime(0); + c->RemoveCorpse(); + c->AddObjectToRemoveList(); } + TC_LOG_DEBUG("outdoorpvp", "deleting opvp creature type %u", type); - ObjectGuid::LowType guid = cr->GetDBTableGUIDLow(); - // Don't save respawn time - cr->SetRespawnTime(0); - cr->RemoveCorpse(); // explicit removal from map // beats me why this is needed, but with the recent removal "cleanup" some creatures stay in the map if "properly" deleted // so this is a big fat workaround, if AddObjectToRemoveList and DoDelayedMovesAndRemoves worked correctly, this wouldn't be needed @@ -187,15 +180,14 @@ bool OPvPCapturePoint::DelCreature(uint32 type) // map->Remove(cr, false); // delete respawn time for this creature PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); - stmt->setUInt64(0, guid); - stmt->setUInt16(1, cr->GetMapId()); + stmt->setUInt64(0, spawnId); + stmt->setUInt16(1, m_PvP->GetMap()->GetId()); stmt->setUInt32(2, 0); // instance id, always 0 for world maps CharacterDatabase.Execute(stmt); - cr->AddObjectToRemoveList(); - sObjectMgr->DeleteCreatureData(guid); + sObjectMgr->DeleteCreatureData(spawnId); m_CreatureTypes[m_Creatures[type]] = 0; - m_Creatures[type].Clear(); + m_Creatures[type] = 0; return true; } @@ -204,25 +196,27 @@ bool OPvPCapturePoint::DelObject(uint32 type) if (!m_Objects[type]) return false; - GameObject* obj = HashMapHolder<GameObject>::Find(m_Objects[type]); - if (!obj) + ObjectGuid::LowType spawnId = m_Objects[type]; + auto bounds = m_PvP->GetMap()->GetGameObjectBySpawnIdStore().equal_range(spawnId); + for (auto itr = bounds.first; itr != bounds.second;) { - m_Objects[type].Clear(); - return false; + GameObject* go = itr->second; + ++itr; + // Don't save respawn time + go->SetRespawnTime(0); + go->Delete(); } - ObjectGuid::LowType guid = obj->GetDBTableGUIDLow(); - obj->SetRespawnTime(0); // not save respawn time - obj->Delete(); - sObjectMgr->DeleteGOData(guid); + + sObjectMgr->DeleteGOData(spawnId); m_ObjectTypes[m_Objects[type]] = 0; - m_Objects[type].Clear(); + m_Objects[type] = 0; return true; } bool OPvPCapturePoint::DelCapturePoint() { - sObjectMgr->DeleteGOData(m_capturePointGUID.GetCounter()); - m_capturePointGUID.Clear(); + sObjectMgr->DeleteGOData(m_capturePointSpawnId); + m_capturePointSpawnId = 0; if (m_capturePoint) { @@ -235,9 +229,9 @@ bool OPvPCapturePoint::DelCapturePoint() void OPvPCapturePoint::DeleteSpawns() { - for (std::map<uint32, ObjectGuid>::iterator i = m_Objects.begin(); i != m_Objects.end(); ++i) + for (std::map<uint32, ObjectGuid::LowType>::iterator i = m_Objects.begin(); i != m_Objects.end(); ++i) DelObject(i->first); - for (std::map<uint32, ObjectGuid>::iterator i = m_Creatures.begin(); i != m_Creatures.end(); ++i) + for (std::map<uint32, ObjectGuid::LowType>::iterator i = m_Creatures.begin(); i != m_Creatures.end(); ++i) DelCreature(i->first); DelCapturePoint(); } @@ -252,7 +246,7 @@ void OutdoorPvP::DeleteSpawns() m_capturePoints.clear(); } -OutdoorPvP::OutdoorPvP() : m_TypeId(0), m_sendUpdate(true) { } +OutdoorPvP::OutdoorPvP() : m_TypeId(0), m_sendUpdate(true), m_map(nullptr) { } OutdoorPvP::~OutdoorPvP() { @@ -512,19 +506,19 @@ bool OPvPCapturePoint::HandleCustomSpell(Player* player, uint32 /*spellId*/, Gam return true; } -bool OutdoorPvP::HandleOpenGo(Player* player, ObjectGuid guid) +bool OutdoorPvP::HandleOpenGo(Player* player, GameObject* go) { for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) - if (itr->second->HandleOpenGo(player, guid) >= 0) + if (itr->second->HandleOpenGo(player, go) >= 0) return true; return false; } -bool OutdoorPvP::HandleGossipOption(Player* player, ObjectGuid guid, uint32 id) +bool OutdoorPvP::HandleGossipOption(Player* player, Creature* creature, uint32 id) { for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) - if (itr->second->HandleGossipOption(player, guid, id)) + if (itr->second->HandleGossipOption(player, creature, id)) return true; return false; @@ -548,13 +542,12 @@ bool OutdoorPvP::HandleDropFlag(Player* player, uint32 id) return false; } -int32 OPvPCapturePoint::HandleOpenGo(Player* /*player*/, ObjectGuid guid) +int32 OPvPCapturePoint::HandleOpenGo(Player* /*player*/, GameObject* go) { - std::map<ObjectGuid, uint32>::iterator itr = m_ObjectTypes.find(guid); + std::map<ObjectGuid::LowType, uint32>::iterator itr = m_ObjectTypes.find(go->GetSpawnId()); if (itr != m_ObjectTypes.end()) - { return itr->second; - } + return -1; } @@ -569,16 +562,16 @@ void OutdoorPvP::BroadcastPacket(WorldPacket const* data) const void OutdoorPvP::AddCapturePoint(OPvPCapturePoint* cp) { - OPvPCapturePointMap::iterator i = m_capturePoints.find(cp->m_capturePointGUID); + OPvPCapturePointMap::iterator i = m_capturePoints.find(cp->m_capturePointSpawnId); if (i != m_capturePoints.end()) { - TC_LOG_ERROR("outdoorpvp", "OutdoorPvP::AddCapturePoint: CapturePoint %s already exists!", cp->m_capturePointGUID.ToString().c_str()); + TC_LOG_ERROR("outdoorpvp", "OutdoorPvP::AddCapturePoint: CapturePoint " UI64FMTD " already exists!", cp->m_capturePointSpawnId); delete i->second; } - m_capturePoints[cp->m_capturePointGUID] = cp; + m_capturePoints[cp->m_capturePointSpawnId] = cp; } -OPvPCapturePoint* OutdoorPvP::GetCapturePoint(ObjectGuid guid) const +OPvPCapturePoint* OutdoorPvP::GetCapturePoint(ObjectGuid::LowType guid) const { OutdoorPvP::OPvPCapturePointMap::const_iterator itr = m_capturePoints.find(guid); if (itr != m_capturePoints.end()) @@ -624,7 +617,7 @@ void OutdoorPvP::OnGameObjectCreate(GameObject* go) if (go->GetGoType() != GAMEOBJECT_TYPE_CONTROL_ZONE) return; - if (OPvPCapturePoint *cp = GetCapturePoint(go->GetGUID())) + if (OPvPCapturePoint *cp = GetCapturePoint(go->GetSpawnId())) cp->m_capturePoint = go; } @@ -633,7 +626,7 @@ void OutdoorPvP::OnGameObjectRemove(GameObject* go) if (go->GetGoType() != GAMEOBJECT_TYPE_CONTROL_ZONE) return; - if (OPvPCapturePoint *cp = GetCapturePoint(go->GetGUID())) + if (OPvPCapturePoint *cp = GetCapturePoint(go->GetSpawnId())) cp->m_capturePoint = NULL; } @@ -653,3 +646,12 @@ void OutdoorPvP::BroadcastWorker(Worker& _worker, uint32 zoneId) if (player->GetZoneId() == zoneId) _worker(player); } + +void OutdoorPvP::SetMapFromZone(uint32 zone) +{ + AreaTableEntry const* areaTable = GetAreaEntryByAreaID(zone); + ASSERT(areaTable); + Map* map = sMapMgr->CreateBaseMap(areaTable->MapID); + ASSERT(!map->Instanceable()); + m_map = map; +} diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h index 1b7b086fd29..cb86f1e9056 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvP.h +++ b/src/server/game/OutdoorPvP/OutdoorPvP.h @@ -109,7 +109,7 @@ class OPvPCapturePoint virtual bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go); - virtual int32 HandleOpenGo(Player* player, ObjectGuid guid); + virtual int32 HandleOpenGo(Player* player, GameObject* go); // returns true if the state of the objective has changed, in this case, the OutdoorPvP must send a world state ui update. virtual bool Update(uint32 diff); @@ -120,7 +120,7 @@ class OPvPCapturePoint virtual void SendChangePhase(); - virtual bool HandleGossipOption(Player* /*player*/, ObjectGuid /*guid*/, uint32 /*gossipId*/) { return false; } + virtual bool HandleGossipOption(Player* /*player*/, Creature* /*guid*/, uint32 /*gossipId*/) { return false; } virtual bool CanTalkTo(Player* /*player*/, Creature* /*creature*/, GossipMenuItems const& /*gso*/) { return false; } @@ -128,12 +128,12 @@ class OPvPCapturePoint virtual void DeleteSpawns(); - ObjectGuid m_capturePointGUID; + ObjectGuid::LowType m_capturePointSpawnId; GameObject* m_capturePoint; - void AddGO(uint32 type, uint32 mapId, ObjectGuid::LowType guid, uint32 entry = 0); - void AddCre(uint32 type, uint32 mapId, ObjectGuid::LowType guid, uint32 entry = 0); + void AddGO(uint32 type, ObjectGuid::LowType guid); + void AddCre(uint32 type, ObjectGuid::LowType guid); bool SetCapturePointData(uint32 entry, uint32 map, float x, float y, float z, float o = 0, float rotation0 = 0, float rotation1 = 0, float rotation2 = 0, float rotation3 = 0); @@ -178,10 +178,10 @@ class OPvPCapturePoint // map to store the various gameobjects and creatures spawned by the objective // type, guid - std::map<uint32, ObjectGuid> m_Objects; - std::map<uint32, ObjectGuid> m_Creatures; - std::map<ObjectGuid, uint32> m_ObjectTypes; - std::map<ObjectGuid, uint32> m_CreatureTypes; + std::map<uint32, ObjectGuid::LowType> m_Objects; + std::map<uint32, ObjectGuid::LowType> m_Creatures; + std::map<ObjectGuid::LowType, uint32> m_ObjectTypes; + std::map<ObjectGuid::LowType, uint32> m_CreatureTypes; }; // base class for specific outdoor pvp handlers @@ -200,7 +200,7 @@ class OutdoorPvP : public ZoneScript // deletes all gos/creatures spawned by the pvp void DeleteSpawns(); - typedef std::map<ObjectGuid/*guid*/, OPvPCapturePoint*> OPvPCapturePointMap; + typedef std::map<ObjectGuid::LowType/*spawnId*/, OPvPCapturePoint*> OPvPCapturePointMap; virtual void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates & /*packet*/) { } @@ -211,7 +211,7 @@ class OutdoorPvP : public ZoneScript virtual bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go); // called on go use - virtual bool HandleOpenGo(Player* player, ObjectGuid guid); + virtual bool HandleOpenGo(Player* player, GameObject* go); // setup stuff virtual bool SetupOutdoorPvP() {return true;} @@ -240,7 +240,7 @@ class OutdoorPvP : public ZoneScript virtual bool HandleDropFlag(Player* player, uint32 spellId); - virtual bool HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid); + virtual bool HandleGossipOption(Player* player, Creature* creature, uint32 gossipid); virtual bool CanTalkTo(Player* player, Creature* c, GossipMenuItems const& gso); @@ -261,6 +261,8 @@ class OutdoorPvP : public ZoneScript void SendDefenseMessage(uint32 zoneId, uint32 id); + Map* GetMap() const { return m_map; } + protected: // the map of the objectives belonging to this outdoorpvp @@ -284,7 +286,7 @@ class OutdoorPvP : public ZoneScript void AddCapturePoint(OPvPCapturePoint* cp); - OPvPCapturePoint * GetCapturePoint(ObjectGuid guid) const; + OPvPCapturePoint* GetCapturePoint(ObjectGuid::LowType guid) const; void RegisterZone(uint32 zoneid); @@ -294,6 +296,11 @@ class OutdoorPvP : public ZoneScript template<class Worker> void BroadcastWorker(Worker& _worker, uint32 zoneId); + + // Hack to store map because this code is just shit + void SetMapFromZone(uint32 zone); + + Map* m_map; }; #endif /*OUTDOOR_PVP_H_*/ diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp index 62440eab44e..b07d21436b2 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp @@ -181,21 +181,21 @@ ZoneScript* OutdoorPvPMgr::GetZoneScript(uint32 zoneId) return NULL; } -bool OutdoorPvPMgr::HandleOpenGo(Player* player, ObjectGuid guid) +bool OutdoorPvPMgr::HandleOpenGo(Player* player, GameObject* go) { for (OutdoorPvPSet::iterator itr = m_OutdoorPvPSet.begin(); itr != m_OutdoorPvPSet.end(); ++itr) { - if ((*itr)->HandleOpenGo(player, guid)) + if ((*itr)->HandleOpenGo(player, go)) return true; } return false; } -void OutdoorPvPMgr::HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid) +void OutdoorPvPMgr::HandleGossipOption(Player* player, Creature* creature, uint32 gossipid) { for (OutdoorPvPSet::iterator itr = m_OutdoorPvPSet.begin(); itr != m_OutdoorPvPSet.end(); ++itr) { - if ((*itr)->HandleGossipOption(player, guid, gossipid)) + if ((*itr)->HandleGossipOption(player, creature, gossipid)) return; } } diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.h b/src/server/game/OutdoorPvP/OutdoorPvPMgr.h index 4f03dd37fac..542aad0ef0d 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.h +++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.h @@ -70,7 +70,7 @@ class OutdoorPvPMgr bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go); // handle custom go if registered - bool HandleOpenGo(Player* player, ObjectGuid guid); + bool HandleOpenGo(Player* player, GameObject* go); ZoneScript* GetZoneScript(uint32 zoneId); @@ -78,7 +78,7 @@ class OutdoorPvPMgr void Update(uint32 diff); - void HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid); + void HandleGossipOption(Player* player, Creature* creature, uint32 gossipid); bool CanTalkTo(Player* player, Creature* creature, GossipMenuItems const& gso); diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index 9f8a9f8686b..a82652d2f03 100644 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -221,8 +221,17 @@ void PoolGroup<Creature>::Despawn1Object(uint64 guid) { sObjectMgr->RemoveCreatureFromGrid(guid, data); - if (Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid::Create<HighGuid::Creature>(data->mapid, data->id, guid), (Creature*)NULL)) - creature->AddObjectToRemoveList(); + Map* map = sMapMgr->CreateBaseMap(data->mapid); + if (!map->Instanceable()) + { + auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(guid); + for (auto itr = creatureBounds.first; itr != creatureBounds.second;) + { + Creature* creature = itr->second; + ++itr; + creature->AddObjectToRemoveList(); + } + } } } @@ -234,8 +243,17 @@ void PoolGroup<GameObject>::Despawn1Object(uint64 guid) { sObjectMgr->RemoveGameobjectFromGrid(guid, data); - if (GameObject* pGameobject = ObjectAccessor::GetObjectInWorld(ObjectGuid::Create<HighGuid::GameObject>(data->mapid, data->id, guid), (GameObject*)NULL)) - pGameobject->AddObjectToRemoveList(); + Map* map = sMapMgr->CreateBaseMap(data->mapid); + if (!map->Instanceable()) + { + auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(guid); + for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second;) + { + GameObject* go = itr->second; + ++itr; + go->AddObjectToRemoveList(); + } + } } } @@ -507,20 +525,16 @@ void PoolGroup<Quest>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint64 // Method that does the respawn job on the specified creature template <> -void PoolGroup<Creature>::ReSpawn1Object(PoolObject* obj) +void PoolGroup<Creature>::ReSpawn1Object(PoolObject* /*obj*/) { - if (CreatureData const* data = sObjectMgr->GetCreatureData(obj->guid)) - if (Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid::Create<HighGuid::Creature>(data->mapid, data->id, obj->guid), (Creature*)NULL)) - creature->GetMap()->AddToMap(creature); + // Creature is still on map, nothing to do } // Method that does the respawn job on the specified gameobject template <> -void PoolGroup<GameObject>::ReSpawn1Object(PoolObject* obj) +void PoolGroup<GameObject>::ReSpawn1Object(PoolObject* /*obj*/) { - if (GameObjectData const* data = sObjectMgr->GetGOData(obj->guid)) - if (GameObject* pGameobject = ObjectAccessor::GetObjectInWorld(ObjectGuid::Create<HighGuid::GameObject>(data->mapid, data->id, obj->guid), (GameObject*)NULL)) - pGameobject->GetMap()->AddToMap(pGameobject); + // GameObject is still on map, nothing to do } // Nothing to do for a child Pool diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp index 48f3bf79088..5fea62655b3 100644 --- a/src/server/game/Reputation/ReputationMgr.cpp +++ b/src/server/game/Reputation/ReputationMgr.cpp @@ -27,6 +27,7 @@ #include "ScriptMgr.h" #include "Opcodes.h" #include "WorldSession.h" +#include "CharacterPackets.h" const int32 ReputationMgr::PointsInRank[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000}; @@ -225,15 +226,15 @@ void ReputationMgr::SendStates() SendState(&(itr->second)); } -void ReputationMgr::SendVisible(FactionState const* faction, bool visible /* = true*/) const +void ReputationMgr::SendVisible(FactionState const* faction, bool visible) const { if (_player->GetSession()->PlayerLoading()) return; // make faction visible/not visible in reputation list at client - WorldPacket data(visible ? SMSG_SET_FACTION_VISIBLE : SMSG_SET_FACTION_NOT_VISIBLE, 4); - data << faction->ReputationListID; - _player->SendDirectMessage(&data); + WorldPackets::Character::SetFactionVisible packet(visible); + packet.FactionIndex = faction->ReputationListID; + _player->SendDirectMessage(packet.Write()); } void ReputationMgr::Initialize() diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp index 8797caf2cf7..deae263e5f8 100644 --- a/src/server/game/Scripting/MapScripts.cpp +++ b/src/server/game/Scripting/MapScripts.cpp @@ -321,26 +321,23 @@ void Map::ScriptsProcess() break; case HighGuid::Creature: case HighGuid::Vehicle: - source = HashMapHolder<Creature>::Find(step.sourceGUID); + source = GetCreature(step.sourceGUID); break; case HighGuid::Pet: - source = HashMapHolder<Pet>::Find(step.sourceGUID); + source = GetPet(step.sourceGUID); break; case HighGuid::Player: source = HashMapHolder<Player>::Find(step.sourceGUID); break; case HighGuid::GameObject: - source = HashMapHolder<GameObject>::Find(step.sourceGUID); + source = GetGameObject(step.sourceGUID); break; case HighGuid::Corpse: - source = HashMapHolder<Corpse>::Find(step.sourceGUID); + source = GetCorpse(step.sourceGUID); break; case HighGuid::Transport: - { - GameObject* go = HashMapHolder<GameObject>::Find(step.sourceGUID); - source = go ? go->ToTransport() : NULL; + source = GetTransport(step.sourceGUID); break; - } default: TC_LOG_ERROR("scripts", "%s source with unsupported high guid %s.", step.script->GetDebugInfo().c_str(), step.sourceGUID.ToString().c_str()); @@ -355,26 +352,23 @@ void Map::ScriptsProcess() { case HighGuid::Creature: case HighGuid::Vehicle: - target = HashMapHolder<Creature>::Find(step.targetGUID); + target = GetCreature(step.targetGUID); break; case HighGuid::Pet: - target = HashMapHolder<Pet>::Find(step.targetGUID); + target = GetPet(step.targetGUID); break; case HighGuid::Player: target = HashMapHolder<Player>::Find(step.targetGUID); break; case HighGuid::GameObject: - target = HashMapHolder<GameObject>::Find(step.targetGUID); + target = GetGameObject(step.targetGUID); break; case HighGuid::Corpse: - target = HashMapHolder<Corpse>::Find(step.targetGUID); + target = GetCorpse(step.targetGUID); break; case HighGuid::Transport: - { - GameObject* go = HashMapHolder<GameObject>::Find(step.targetGUID); - target = go ? go->ToTransport() : NULL; + target = GetTransport(step.targetGUID); break; - } default: TC_LOG_ERROR("scripts", "%s target with unsupported high guid %s.", step.script->GetDebugInfo().c_str(), step.targetGUID.ToString().c_str()); @@ -826,8 +820,12 @@ void Map::ScriptsProcess() } else //check hashmap holders { - if (CreatureData const* data = sObjectMgr->GetCreatureData(step.script->CallScript.CreatureEntry)) - cTarget = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, ObjectGuid::Create<HighGuid::Creature>(data->mapid, data->id, uint64(step.script->CallScript.CreatureEntry)), cTarget); + if (sObjectMgr->GetCreatureData(step.script->CallScript.CreatureEntry)) + { + auto creatureBounds = _creatureBySpawnIdStore.equal_range(step.script->CallScript.CreatureEntry); + if (creatureBounds.first != creatureBounds.second) + cTarget = creatureBounds.first->second; + } } if (!cTarget) diff --git a/src/server/game/Server/Packet.h b/src/server/game/Server/Packet.h index bf538803ad6..85d65e967be 100644 --- a/src/server/game/Server/Packet.h +++ b/src/server/game/Server/Packet.h @@ -45,7 +45,7 @@ namespace WorldPackets class ServerPacket : public Packet { public: - ServerPacket(OpcodeServer opcode, size_t initialSize = 200) : Packet(WorldPacket(opcode, initialSize)) { } + ServerPacket(OpcodeServer opcode, size_t initialSize = 200, ConnectionType connection = CONNECTION_TYPE_DEFAULT) : Packet(WorldPacket(opcode, initialSize, connection)) { } void Read() override final { ASSERT(!"Read not implemented for server packets."); } diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index b6d2ff21630..40af397e110 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -53,90 +53,94 @@ void WorldPackets::Auth::AuthSession::Read() WorldPackets::Auth::AuthResponse::AuthResponse() : ServerPacket(SMSG_AUTH_RESPONSE, 132) { - WaitInfo.HasValue = false; - SuccessInfo.HasValue = false; } WorldPacket const* WorldPackets::Auth::AuthResponse::Write() { _worldPacket << uint8(Result); - _worldPacket.WriteBit(SuccessInfo.HasValue); - _worldPacket.WriteBit(WaitInfo.HasValue); + _worldPacket.WriteBit(SuccessInfo.is_initialized()); + _worldPacket.WriteBit(WaitInfo.is_initialized()); + _worldPacket.FlushBits(); - if (SuccessInfo.HasValue) + if (SuccessInfo) { - _worldPacket << uint32(SuccessInfo.Value.VirtualRealmAddress); - _worldPacket << uint32(SuccessInfo.Value.VirtualRealms.size()); - _worldPacket << uint32(SuccessInfo.Value.TimeRemain); - _worldPacket << uint32(SuccessInfo.Value.TimeOptions); - _worldPacket << uint32(SuccessInfo.Value.TimeRested); - _worldPacket << uint8(SuccessInfo.Value.ActiveExpansionLevel); - _worldPacket << uint8(SuccessInfo.Value.AccountExpansionLevel); - _worldPacket << uint32(SuccessInfo.Value.TimeSecondsUntilPCKick); - _worldPacket << uint32(SuccessInfo.Value.AvailableRaces->size()); - _worldPacket << uint32(SuccessInfo.Value.AvailableClasses->size()); - _worldPacket << uint32(SuccessInfo.Value.Templates.size()); - _worldPacket << uint32(SuccessInfo.Value.CurrencyID); - - for (auto& realm : SuccessInfo.Value.VirtualRealms) + _worldPacket << uint32(SuccessInfo->VirtualRealmAddress); + _worldPacket << uint32(SuccessInfo->VirtualRealms.size()); + _worldPacket << uint32(SuccessInfo->TimeRemain); + _worldPacket << uint32(SuccessInfo->TimeOptions); + _worldPacket << uint32(SuccessInfo->TimeRested); + _worldPacket << uint8(SuccessInfo->ActiveExpansionLevel); + _worldPacket << uint8(SuccessInfo->AccountExpansionLevel); + _worldPacket << uint32(SuccessInfo->TimeSecondsUntilPCKick); + _worldPacket << uint32(SuccessInfo->AvailableRaces->size()); + _worldPacket << uint32(SuccessInfo->AvailableClasses->size()); + _worldPacket << uint32(SuccessInfo->Templates.size()); + _worldPacket << uint32(SuccessInfo->CurrencyID); + + for (auto& realm : SuccessInfo->VirtualRealms) { _worldPacket << uint32(realm.RealmAddress); _worldPacket.WriteBit(realm.IsLocal); _worldPacket.WriteBit(realm.IsInternalRealm); _worldPacket.WriteBits(realm.RealmNameActual.length(), 8); _worldPacket.WriteBits(realm.RealmNameNormalized.length(), 8); + _worldPacket.FlushBits(); + _worldPacket.WriteString(realm.RealmNameActual); _worldPacket.WriteString(realm.RealmNameNormalized); } - for (auto& race : *SuccessInfo.Value.AvailableRaces) + for (auto& race : *SuccessInfo->AvailableRaces) { _worldPacket << uint8(race.first); /// the current race _worldPacket << uint8(race.second); /// the required Expansion } - for (auto& klass : *SuccessInfo.Value.AvailableClasses) + for (auto& klass : *SuccessInfo->AvailableClasses) { _worldPacket << uint8(klass.first); /// the current class _worldPacket << uint8(klass.second); /// the required Expansion } - for (auto& templat : SuccessInfo.Value.Templates) + for (auto& templat : SuccessInfo->Templates) { _worldPacket << uint32(templat.TemplateSetId); - _worldPacket << uint32(templat.TemplateClasses.size()); - for (auto& templatClass : templat.TemplateClasses) + _worldPacket << uint32(templat.Classes.size()); + for (auto& templateClass : templat.Classes) { - _worldPacket << uint8(templatClass.Class); - _worldPacket << uint8(templatClass.FactionGroup); + _worldPacket << uint8(templateClass.ClassID); + _worldPacket << uint8(templateClass.FactionGroup); } _worldPacket.WriteBits(templat.Name.length(), 7); _worldPacket.WriteBits(templat.Description.length(), 10); + _worldPacket.FlushBits(); + _worldPacket.WriteString(templat.Name); _worldPacket.WriteString(templat.Description); } - _worldPacket.WriteBit(SuccessInfo.Value.IsExpansionTrial); - _worldPacket.WriteBit(SuccessInfo.Value.ForceCharacterTemplate); - _worldPacket.WriteBit(SuccessInfo.Value.NumPlayersHorde.HasValue); - _worldPacket.WriteBit(SuccessInfo.Value.NumPlayersAlliance.HasValue); - _worldPacket.WriteBit(SuccessInfo.Value.IsVeteranTrial); + _worldPacket.WriteBit(SuccessInfo->IsExpansionTrial); + _worldPacket.WriteBit(SuccessInfo->ForceCharacterTemplate); + _worldPacket.WriteBit(SuccessInfo->NumPlayersHorde.is_initialized()); + _worldPacket.WriteBit(SuccessInfo->NumPlayersAlliance.is_initialized()); + _worldPacket.WriteBit(SuccessInfo->IsVeteranTrial); + _worldPacket.FlushBits(); - if (SuccessInfo.Value.NumPlayersHorde.HasValue) - _worldPacket << uint16(SuccessInfo.Value.NumPlayersHorde.Value); + if (SuccessInfo->NumPlayersHorde) + _worldPacket << uint16(*SuccessInfo->NumPlayersHorde); - if (SuccessInfo.Value.NumPlayersAlliance.HasValue) - _worldPacket << uint16(SuccessInfo.Value.NumPlayersAlliance.Value); + if (SuccessInfo->NumPlayersAlliance) + _worldPacket << uint16(*SuccessInfo->NumPlayersAlliance); } - if (WaitInfo.HasValue) + if (WaitInfo) { - _worldPacket << uint32(WaitInfo.Value.WaitCount); - _worldPacket.WriteBit(WaitInfo.Value.HasFCM); + _worldPacket << uint32(WaitInfo->WaitCount); + _worldPacket.WriteBit(WaitInfo->HasFCM); + _worldPacket.FlushBits(); } - _worldPacket.FlushBits(); return &_worldPacket; } diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h index eae0cae34f1..f75dd9c040b 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.h +++ b/src/server/game/Server/Packets/AuthenticationPackets.h @@ -20,7 +20,7 @@ #include "Packet.h" #include "ObjectMgr.h" -#include "Util.h" +#include "Common.h" #include "BigNumber.h" #include "SHA1.h" #include <boost/asio/ip/tcp.hpp> @@ -83,20 +83,6 @@ namespace WorldPackets std::string RealmNameNormalized; ///< the name of the realm without spaces }; - struct CharacterTemplate - { - struct TemplateClass - { - uint8 Class; - uint8 FactionGroup; ///< @todo research - }; - - uint32 TemplateSetId; ///< @todo research - std::list<TemplateClass> TemplateClasses; - std::string Name; - std::string Description; - }; - struct AuthSuccessInfo { uint32 TimeRemain = 0; ///< the remaining game time that the account has in seconds. It is not currently implemented and probably won't ever be. @@ -110,8 +96,8 @@ namespace WorldPackets uint32 TimeSecondsUntilPCKick = 0; ///< @todo research uint32 CurrencyID = 0; ///< this is probably used for the ingame shop. @todo implement - std::list<RealmInfo> VirtualRealms; ///< list of realms connected to this one (inclusive) @todo implement - std::list<CharacterTemplate> Templates; ///< list of pre-made character templates. @todo implement + std::vector<RealmInfo> VirtualRealms; ///< list of realms connected to this one (inclusive) @todo implement + std::vector<CharacterTemplate> Templates; ///< list of pre-made character templates. ExpansionRequirementContainer const* AvailableClasses = nullptr; ///< the minimum AccountExpansion required to select the classes ExpansionRequirementContainer const* AvailableRaces = nullptr; ///< the minimum AccountExpansion required to select the races @@ -198,7 +184,7 @@ namespace WorldPackets class ResumeComms final : public ServerPacket { public: - ResumeComms() : ServerPacket(SMSG_RESUME_COMMS, 0) { } + ResumeComms(ConnectionType connection) : ServerPacket(SMSG_RESUME_COMMS, 0, connection) { } WorldPacket const* Write() override { return &_worldPacket; } }; diff --git a/src/server/game/Server/Packets/BattlegroundPackets.cpp b/src/server/game/Server/Packets/BattlegroundPackets.cpp index 1124a3b9d6e..142d53c481a 100644 --- a/src/server/game/Server/Packets/BattlegroundPackets.cpp +++ b/src/server/game/Server/Packets/BattlegroundPackets.cpp @@ -65,27 +65,27 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Battleground::PVPLogData: data.WriteBit(playerData.Faction); data.WriteBit(playerData.IsInWorld); - data.WriteBit(playerData.Honor.HasValue); - data.WriteBit(playerData.PreMatchRating.HasValue); - data.WriteBit(playerData.RatingChange.HasValue); - data.WriteBit(playerData.PreMatchMMR.HasValue); - data.WriteBit(playerData.MmrChange.HasValue); + data.WriteBit(playerData.Honor.is_initialized()); + data.WriteBit(playerData.PreMatchRating.is_initialized()); + data.WriteBit(playerData.RatingChange.is_initialized()); + data.WriteBit(playerData.PreMatchMMR.is_initialized()); + data.WriteBit(playerData.MmrChange.is_initialized()); data.FlushBits(); - if (playerData.Honor.HasValue) - data << playerData.Honor.Value; + if (playerData.Honor) + data << *playerData.Honor; - if (playerData.PreMatchRating.HasValue) - data << uint32(playerData.PreMatchRating.Value); + if (playerData.PreMatchRating) + data << uint32(*playerData.PreMatchRating); - if (playerData.RatingChange.HasValue) - data << uint32(playerData.RatingChange.Value); + if (playerData.RatingChange) + data << uint32(*playerData.RatingChange); - if (playerData.PreMatchMMR.HasValue) - data << uint32(playerData.PreMatchMMR.Value); + if (playerData.PreMatchMMR) + data << uint32(*playerData.PreMatchMMR); - if (playerData.MmrChange.HasValue) - data << uint32(playerData.MmrChange.Value); + if (playerData.MmrChange) + data << uint32(*playerData.MmrChange); return data; } @@ -94,16 +94,16 @@ WorldPacket const* WorldPackets::Battleground::PVPLogData::Write() { _worldPacket.reserve(Players.size() * sizeof(PlayerData) + sizeof(PVPLogData)); - _worldPacket.WriteBit(Ratings.HasValue); - _worldPacket.WriteBit(Winner.HasValue); + _worldPacket.WriteBit(Ratings.is_initialized()); + _worldPacket.WriteBit(Winner.is_initialized()); _worldPacket << uint32(Players.size()); _worldPacket.append(PlayerCount, 2); - if (Ratings.HasValue) - _worldPacket << Ratings.Value; + if (Ratings.is_initialized()) + _worldPacket << *Ratings; - if (Winner.HasValue) - _worldPacket << uint8(Winner.Value); + if (Winner) + _worldPacket << uint8(*Winner); for (PlayerData const& player : Players) _worldPacket << player; diff --git a/src/server/game/Server/Packets/BattlegroundPackets.h b/src/server/game/Server/Packets/BattlegroundPackets.h index d532ec949b8..2b534826436 100644 --- a/src/server/game/Server/Packets/BattlegroundPackets.h +++ b/src/server/game/Server/Packets/BattlegroundPackets.h @@ -18,6 +18,7 @@ #ifndef BattlegroundPackets_h__ #define BattlegroundPackets_h__ +#include "Common.h" #include "ObjectGuid.h" #include "LFGPackets.h" #include "PacketUtilities.h" diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp index 257c8065fa2..a48639f1b03 100644 --- a/src/server/game/Server/Packets/CharacterPackets.cpp +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -154,6 +154,8 @@ WorldPacket const* WorldPackets::Character::EnumCharactersResult::Write() _worldPacket.WriteBit(charInfo.FirstLogin); _worldPacket.WriteBit(charInfo.BoostInProgress); _worldPacket.WriteBits(charInfo.unkWod61x, 5); + _worldPacket.FlushBits(); + _worldPacket.WriteString(charInfo.Name); } @@ -170,7 +172,8 @@ void WorldPackets::Character::CreateCharacter::Read() { CreateInfo.reset(new CharacterCreateInfo()); uint32 nameLength = _worldPacket.ReadBits(6); - CreateInfo->TemplateSet.HasValue = _worldPacket.ReadBit(); + bool const hasTemplateSet = _worldPacket.ReadBit(); + _worldPacket >> CreateInfo->Race; _worldPacket >> CreateInfo->Class; _worldPacket >> CreateInfo->Sex; @@ -181,8 +184,8 @@ void WorldPackets::Character::CreateCharacter::Read() _worldPacket >> CreateInfo->FacialHairStyle; _worldPacket >> CreateInfo->OutfitId; CreateInfo->Name = _worldPacket.ReadString(nameLength); - if (CreateInfo->TemplateSet.HasValue) - _worldPacket >> CreateInfo->TemplateSet.Value; + if (hasTemplateSet) + CreateInfo->TemplateSet = _worldPacket.read<int32>(); } WorldPacket const* WorldPackets::Character::CreateChar::Write() @@ -212,13 +215,15 @@ void WorldPackets::Character::CharacterRenameRequest::Read() WorldPacket const* WorldPackets::Character::CharacterRenameResult::Write() { _worldPacket << uint8(Result); - _worldPacket.WriteBit(Guid.HasValue); + _worldPacket.WriteBit(Guid.is_initialized()); _worldPacket.WriteBits(Name.length(), 6); + _worldPacket.FlushBits(); - if (Guid.HasValue) - _worldPacket << Guid.Value; + if (Guid) + _worldPacket << *Guid; _worldPacket.WriteString(Name); + return &_worldPacket; } @@ -243,11 +248,11 @@ void WorldPackets::Character::CharRaceOrFactionChange::Read() uint32 nameLength = _worldPacket.ReadBits(6); - RaceOrFactionChangeInfo->SkinID.HasValue = _worldPacket.ReadBit(); - RaceOrFactionChangeInfo->HairColorID.HasValue = _worldPacket.ReadBit(); - RaceOrFactionChangeInfo->HairStyleID.HasValue = _worldPacket.ReadBit(); - RaceOrFactionChangeInfo->FacialHairStyleID.HasValue = _worldPacket.ReadBit(); - RaceOrFactionChangeInfo->FaceID.HasValue = _worldPacket.ReadBit(); + bool const hasSkinID = _worldPacket.ReadBit(); + bool const hasHairColorID = _worldPacket.ReadBit(); + bool const hasHairStyleID = _worldPacket.ReadBit(); + bool const hasFacialHairStyleID = _worldPacket.ReadBit(); + bool const hasFaceID = _worldPacket.ReadBit(); _worldPacket >> RaceOrFactionChangeInfo->Guid; _worldPacket >> RaceOrFactionChangeInfo->SexID; @@ -255,40 +260,40 @@ void WorldPackets::Character::CharRaceOrFactionChange::Read() RaceOrFactionChangeInfo->Name = _worldPacket.ReadString(nameLength); - if (RaceOrFactionChangeInfo->SkinID.HasValue) - _worldPacket >> RaceOrFactionChangeInfo->SkinID.Value; + if (hasSkinID) + RaceOrFactionChangeInfo->SkinID = _worldPacket.read<uint8>(); - if (RaceOrFactionChangeInfo->HairColorID.HasValue) - _worldPacket >> RaceOrFactionChangeInfo->HairColorID.Value; + if (hasHairColorID) + RaceOrFactionChangeInfo->HairColorID = _worldPacket.read<uint8>(); - if (RaceOrFactionChangeInfo->HairStyleID.HasValue) - _worldPacket >> RaceOrFactionChangeInfo->HairStyleID.Value; + if (hasHairStyleID) + RaceOrFactionChangeInfo->HairStyleID = _worldPacket.read<uint8>(); - if (RaceOrFactionChangeInfo->FacialHairStyleID.HasValue) - _worldPacket >> RaceOrFactionChangeInfo->FacialHairStyleID.Value; + if (hasFacialHairStyleID) + RaceOrFactionChangeInfo->FacialHairStyleID = _worldPacket.read<uint8>(); - if (RaceOrFactionChangeInfo->FaceID.HasValue) - _worldPacket >> RaceOrFactionChangeInfo->FaceID.Value; + if (hasFaceID) + RaceOrFactionChangeInfo->FaceID = _worldPacket.read<uint8>(); } WorldPacket const* WorldPackets::Character::CharFactionChangeResult::Write() { _worldPacket << uint8(Result); _worldPacket << Guid; - _worldPacket.WriteBit(Display.HasValue); + _worldPacket.WriteBit(Display.is_initialized()); _worldPacket.FlushBits(); - if (Display.HasValue) + if (Display) { - _worldPacket.WriteBits(Display.Value.Name.length(), 6); - _worldPacket << uint8(Display.Value.SexID); - _worldPacket << uint8(Display.Value.SkinID); - _worldPacket << uint8(Display.Value.HairColorID); - _worldPacket << uint8(Display.Value.HairStyleID); - _worldPacket << uint8(Display.Value.FacialHairStyleID); - _worldPacket << uint8(Display.Value.FaceID); - _worldPacket << uint8(Display.Value.RaceID); - _worldPacket.WriteString(Display.Value.Name); + _worldPacket.WriteBits(Display->Name.length(), 6); + _worldPacket << uint8(Display->SexID); + _worldPacket << uint8(Display->SkinID); + _worldPacket << uint8(Display->HairColorID); + _worldPacket << uint8(Display->HairStyleID); + _worldPacket << uint8(Display->FacialHairStyleID); + _worldPacket << uint8(Display->FaceID); + _worldPacket << uint8(Display->RaceID); + _worldPacket.WriteString(Display->Name); } return &_worldPacket; @@ -304,19 +309,21 @@ WorldPacket const* WorldPackets::Character::GenerateRandomCharacterNameResult::W { _worldPacket.WriteBit(Success); _worldPacket.WriteBits(Name.length(), 6); + _worldPacket.FlushBits(); + _worldPacket.WriteString(Name); + return &_worldPacket; } void WorldPackets::Character::ReorderCharacters::Read() { uint32 count = std::min<uint32>(_worldPacket.ReadBits(9), sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)); - while (count--) + Entries.resize(count); + for (ReorderInfo& reorderInfo : Entries) { - ReorderInfo reorderInfo; _worldPacket >> reorderInfo.PlayerGUID; _worldPacket >> reorderInfo.NewPosition; - Entries.emplace_back(reorderInfo); } } @@ -435,7 +442,7 @@ void WorldPackets::Character::AlterApperance::Read() _worldPacket >> NewHairColor; _worldPacket >> NewFacialHair; _worldPacket >> NewSkinColor; - _worldPacket >> Unk; + _worldPacket >> NewFace; } WorldPacket const* WorldPackets::Character::BarberShopResultServer::Write() @@ -457,3 +464,37 @@ WorldPacket const* WorldPackets::Character::LogXPGain::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Character::TitleEarned::Write() +{ + _worldPacket << uint32(Index); + + return &_worldPacket; +} + +void WorldPackets::Character::SetFactionAtWar::Read() +{ + _worldPacket >> FactionIndex; +} + +void WorldPackets::Character::SetFactionNotAtWar::Read() +{ + _worldPacket >> FactionIndex; +} + +void WorldPackets::Character::SetFactionInactive::Read() +{ + _worldPacket >> Index; + State = _worldPacket.ReadBit(); +} + +void WorldPackets::Character::SetWatchedFaction::Read() +{ + _worldPacket >> FactionIndex; +} + +WorldPacket const* WorldPackets::Character::SetFactionVisible::Write() +{ + _worldPacket << FactionIndex; + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h index 8541f00a402..cee4f5edb5c 100644 --- a/src/server/game/Server/Packets/CharacterPackets.h +++ b/src/server/game/Server/Packets/CharacterPackets.h @@ -598,7 +598,7 @@ namespace WorldPackets uint32 NewHairColor = 0; uint32 NewFacialHair = 0; uint32 NewSkinColor = 0; - uint32 Unk = 0; + uint32 NewFace = 0; }; class BarberShopResultServer final : public ServerPacket @@ -625,6 +625,67 @@ namespace WorldPackets float GroupBonus = 0; bool ReferAFriend = false; }; + + class TitleEarned final : public ServerPacket + { + public: + TitleEarned(OpcodeServer opcode) : ServerPacket(opcode, 4) { } + + WorldPacket const* Write() override; + + uint32 Index = 0; + }; + + class SetFactionAtWar final : public ClientPacket + { + public: + SetFactionAtWar(WorldPacket&& packet) : ClientPacket(CMSG_SET_FACTION_AT_WAR, std::move(packet)) { } + + void Read() override; + + uint8 FactionIndex = 0; + }; + + class SetFactionNotAtWar final : public ClientPacket + { + public: + SetFactionNotAtWar(WorldPacket&& packet) : ClientPacket(CMSG_SET_FACTION_NOT_AT_WAR, std::move(packet)) { } + + void Read() override; + + uint8 FactionIndex = 0; + }; + + class SetFactionInactive final : public ClientPacket + { + public: + SetFactionInactive(WorldPacket&& packet) : ClientPacket(CMSG_SET_FACTION_INACTIVE, std::move(packet)) { } + + void Read() override; + + uint32 Index = 0; + bool State = false; + }; + + class SetWatchedFaction final : public ClientPacket + { + public: + SetWatchedFaction(WorldPacket&& packet) : ClientPacket(CMSG_SET_WATCHED_FACTION, std::move(packet)) { } + + void Read() override; + + uint32 FactionIndex = 0; + }; + + class SetFactionVisible : public ServerPacket + { + public: + SetFactionVisible(bool visible) : ServerPacket(visible ? SMSG_SET_FACTION_VISIBLE : SMSG_SET_FACTION_NOT_VISIBLE, 4) { } + + WorldPacket const* Write() override; + + uint32 FactionIndex = 0; + }; } } diff --git a/src/server/game/Server/Packets/ChatPackets.cpp b/src/server/game/Server/Packets/ChatPackets.cpp index 8179ee427c8..260770e65fe 100644 --- a/src/server/game/Server/Packets/ChatPackets.cpp +++ b/src/server/game/Server/Packets/ChatPackets.cpp @@ -165,6 +165,8 @@ WorldPacket const* WorldPackets::Chat::Chat::Write() _worldPacket.WriteBits(_ChatFlags, 11); _worldPacket.WriteBit(HideChatLog); _worldPacket.WriteBit(FakeSenderName); + _worldPacket.FlushBits(); + _worldPacket.WriteString(SenderName); _worldPacket.WriteString(TargetName); _worldPacket.WriteString(Prefix); @@ -203,6 +205,31 @@ WorldPacket const* WorldPackets::Chat::STextEmote::Write() WorldPacket const* WorldPackets::Chat::PrintNotification::Write() { _worldPacket.WriteBits(NotifyText.size(), 12); + _worldPacket.FlushBits(); + _worldPacket.WriteString(NotifyText); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Chat::ChatPlayerNotfound::Write() +{ + _worldPacket.WriteBits(Name.length(), 9); + _worldPacket.FlushBits(); + + _worldPacket.WriteString(Name); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Chat::ChatServerMessage::Write() +{ + _worldPacket << MessageID; + + _worldPacket.WriteBits(StringParam.length(), 11); + _worldPacket.FlushBits(); + + _worldPacket.WriteString(StringParam); + return &_worldPacket; } diff --git a/src/server/game/Server/Packets/ChatPackets.h b/src/server/game/Server/Packets/ChatPackets.h index 8cadb88b584..5bc55952168 100644 --- a/src/server/game/Server/Packets/ChatPackets.h +++ b/src/server/game/Server/Packets/ChatPackets.h @@ -229,6 +229,27 @@ namespace WorldPackets void Read() override { } }; + + class ChatPlayerNotfound final : public ServerPacket + { + public: + ChatPlayerNotfound(std::string const& name) : ServerPacket(SMSG_CHAT_PLAYER_NOTFOUND, 2 + name.size()), Name(name) { } + + WorldPacket const* Write() override; + + std::string Name; + }; + + class ChatServerMessage final : public ServerPacket + { + public: + ChatServerMessage() : ServerPacket(SMSG_CHAT_SERVER_MESSAGE, 4 + 2) { } + + WorldPacket const* Write() override; + + int32 MessageID = 0; + std::string StringParam; + }; } } diff --git a/src/server/game/Server/Packets/CombatLogPackets.cpp b/src/server/game/Server/Packets/CombatLogPackets.cpp index e44db70c76a..0702ad63f05 100644 --- a/src/server/game/Server/Packets/CombatLogPackets.cpp +++ b/src/server/game/Server/Packets/CombatLogPackets.cpp @@ -33,11 +33,11 @@ WorldPacket const* WorldPackets::CombatLog::SpellNonMeleeDamageLog::Write() _worldPacket.WriteBit(Periodic); _worldPacket.WriteBits(Flags, 9); _worldPacket.WriteBit(false); // Debug info - _worldPacket.WriteBit(LogData.HasValue); + _worldPacket.WriteBit(LogData.is_initialized()); _worldPacket.FlushBits(); - if (LogData.HasValue) - _worldPacket << LogData.Value; + if (LogData) + _worldPacket << *LogData; return &_worldPacket; } @@ -50,11 +50,100 @@ WorldPacket const* WorldPackets::CombatLog::EnvironmentalDamageLog::Write() _worldPacket << Resisted; _worldPacket << Absorbed; - _worldPacket.WriteBit(LogData.HasValue); + _worldPacket.WriteBit(LogData.is_initialized()); _worldPacket.FlushBits(); - if (LogData.HasValue) - _worldPacket << LogData.Value; + if (LogData) + _worldPacket << *LogData; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::CombatLog::SpellExecuteLog::Write() +{ + _worldPacket << Caster; + _worldPacket << SpellID; + + _worldPacket << uint32(Effects.size()); + + for (SpellLogEffect const& effect : Effects) + { + _worldPacket << effect.Effect; + + _worldPacket << uint32(effect.PowerDrainTargets.size()); + _worldPacket << uint32(effect.ExtraAttacksTargets.size()); + _worldPacket << uint32(effect.DurabilityDamageTargets.size()); + _worldPacket << uint32(effect.GenericVictimTargets.size()); + _worldPacket << uint32(effect.TradeSkillTargets.size()); + _worldPacket << uint32(effect.FeedPetTargets.size()); + + for (SpellLogEffectPowerDrainParams const& powerDrainTarget : effect.PowerDrainTargets) + { + _worldPacket << powerDrainTarget.Victim; + _worldPacket << powerDrainTarget.Points; + _worldPacket << powerDrainTarget.PowerType; + _worldPacket << powerDrainTarget.Amplitude; + } + + for (SpellLogEffectExtraAttacksParams const& extraAttacksTarget : effect.ExtraAttacksTargets) + { + _worldPacket << extraAttacksTarget.Victim; + _worldPacket << extraAttacksTarget.NumAttacks; + } + + for (SpellLogEffectDurabilityDamageParams const& durabilityDamageTarget : effect.DurabilityDamageTargets) + { + _worldPacket << durabilityDamageTarget.Victim; + _worldPacket << durabilityDamageTarget.ItemID; + _worldPacket << durabilityDamageTarget.Amount; + } + + for (SpellLogEffectGenericVictimParams const& genericVictimTarget : effect.GenericVictimTargets) + _worldPacket << genericVictimTarget.Victim; + + for (SpellLogEffectTradeSkillItemParams const& tradeSkillTarget : effect.TradeSkillTargets) + _worldPacket << tradeSkillTarget.ItemID; + + + for (SpellLogEffectFeedPetParams const& feedPetTarget : effect.FeedPetTargets) + _worldPacket << feedPetTarget.ItemID; + } + + _worldPacket.WriteBit(LogData.is_initialized()); + _worldPacket.FlushBits(); + + if (LogData) + _worldPacket << *LogData; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::CombatLog::SpellHealLog::Write() +{ + _worldPacket << TargetGUID; + _worldPacket << CasterGUID; + + _worldPacket << SpellID; + _worldPacket << Health; + _worldPacket << OverHeal; + _worldPacket << Absorbed; + + _worldPacket.WriteBit(Crit); + _worldPacket.WriteBit(Multistrike); + + _worldPacket.WriteBit(CritRollMade.is_initialized()); + _worldPacket.WriteBit(CritRollNeeded.is_initialized()); + _worldPacket.WriteBit(LogData.is_initialized()); + _worldPacket.FlushBits(); + + if (CritRollMade) + _worldPacket << *CritRollMade; + + if (CritRollNeeded) + _worldPacket << *CritRollNeeded; + + if (LogData) + _worldPacket << *LogData; return &_worldPacket; } diff --git a/src/server/game/Server/Packets/CombatLogPackets.h b/src/server/game/Server/Packets/CombatLogPackets.h index 606322e5d35..c74e8112698 100644 --- a/src/server/game/Server/Packets/CombatLogPackets.h +++ b/src/server/game/Server/Packets/CombatLogPackets.h @@ -19,6 +19,7 @@ #define CombatLogPackets_h__ #include "Packet.h" +#include "Spell.h" #include "SpellPackets.h" namespace WorldPackets @@ -61,6 +62,52 @@ namespace WorldPackets int32 Absorbed = 0; Optional<Spells::SpellCastLogData> LogData; /// @todo: find the correct way where to use it, in sniff always false }; + + class SpellExecuteLog final : public ServerPacket + { + public: + struct SpellLogEffect + { + int32 Effect = 0; + + std::vector<SpellLogEffectPowerDrainParams> PowerDrainTargets; + std::vector<SpellLogEffectExtraAttacksParams> ExtraAttacksTargets; + std::vector<SpellLogEffectDurabilityDamageParams> DurabilityDamageTargets; + std::vector<SpellLogEffectGenericVictimParams> GenericVictimTargets; + std::vector<SpellLogEffectTradeSkillItemParams> TradeSkillTargets; + std::vector<SpellLogEffectFeedPetParams> FeedPetTargets; + }; + + SpellExecuteLog() : ServerPacket(SMSG_SPELL_EXECUTE_LOG, 16 + 4 + 4 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid Caster; + int32 SpellID = 0; + std::vector<SpellLogEffect> Effects; + Optional<Spells::SpellCastLogData> LogData; /// @todo: find the correct way where to use it, in sniff always false + }; + + class SpellHealLog final : public ServerPacket + { + public: + + SpellHealLog() : ServerPacket(SMSG_SPELL_HEAL_LOG, 16 + 16 + 4 * 4 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid CasterGUID; + ObjectGuid TargetGUID; + int32 SpellID = 0; + int32 Health = 0; + int32 OverHeal = 0; + int32 Absorbed = 0; + bool Crit = false; + bool Multistrike = false; + Optional<float> CritRollMade; + Optional<float> CritRollNeeded; + Optional<Spells::SpellCastLogData> LogData; /// @todo: find the correct way where to use it, in sniff always false + }; } } diff --git a/src/server/game/Server/Packets/CombatPackets.cpp b/src/server/game/Server/Packets/CombatPackets.cpp index e5100450b55..e095e951e36 100644 --- a/src/server/game/Server/Packets/CombatPackets.cpp +++ b/src/server/game/Server/Packets/CombatPackets.cpp @@ -96,8 +96,8 @@ WorldPacket const* WorldPackets::Combat::AIReaction::Write() WorldPacket const* WorldPackets::Combat::AttackerStateUpdate::Write() { - if (_worldPacket.WriteBit(LogData.HasValue)) - _worldPacket << LogData.Value; + if (_worldPacket.WriteBit(LogData.is_initialized())) + _worldPacket << *LogData; // Placeholder for size which will be calculated at the end based on packet size // Client uses this size to copy remaining packet to another CDataStore @@ -109,15 +109,16 @@ WorldPacket const* WorldPackets::Combat::AttackerStateUpdate::Write() _worldPacket << VictimGUID; _worldPacket << Damage; _worldPacket << OverDamage; - if (_worldPacket.WriteBit(SubDmg.HasValue)) + + if (_worldPacket.WriteBit(SubDmg.is_initialized())) { - _worldPacket << SubDmg.Value.SchoolMask; - _worldPacket << SubDmg.Value.FDamage; - _worldPacket << SubDmg.Value.Damage; + _worldPacket << SubDmg->SchoolMask; + _worldPacket << SubDmg->FDamage; + _worldPacket << SubDmg->Damage; if (HitInfo & (HITINFO_FULL_ABSORB | HITINFO_PARTIAL_ABSORB)) - _worldPacket << SubDmg.Value.Absorbed; + _worldPacket << SubDmg->Absorbed; if (HitInfo & (HITINFO_FULL_RESIST | HITINFO_PARTIAL_RESIST)) - _worldPacket << SubDmg.Value.Resisted; + _worldPacket << SubDmg->Resisted; } _worldPacket << VictimState; diff --git a/src/server/game/Server/Packets/EquipmentSetPackets.cpp b/src/server/game/Server/Packets/EquipmentSetPackets.cpp index 0dc948f5170..3fe30d2b8e7 100644 --- a/src/server/game/Server/Packets/EquipmentSetPackets.cpp +++ b/src/server/game/Server/Packets/EquipmentSetPackets.cpp @@ -40,9 +40,10 @@ WorldPacket const* WorldPackets::EquipmentSet::LoadEquipmentSet::Write() _worldPacket.WriteBits(equipSet->SetName.length(), 8); _worldPacket.WriteBits(equipSet->SetIcon.length(), 9); + _worldPacket.FlushBits(); + _worldPacket.WriteString(equipSet->SetName); _worldPacket.WriteString(equipSet->SetIcon); - _worldPacket.FlushBits(); } return &_worldPacket; diff --git a/src/server/game/Server/Packets/EquipmentSetPackets.h b/src/server/game/Server/Packets/EquipmentSetPackets.h index a26eee383ae..a7936cc1b79 100644 --- a/src/server/game/Server/Packets/EquipmentSetPackets.h +++ b/src/server/game/Server/Packets/EquipmentSetPackets.h @@ -63,7 +63,7 @@ namespace WorldPackets void Read() override; - uint64 ID; + uint64 ID = 0; }; class UseEquipmentSet final : public ClientPacket diff --git a/src/server/game/Server/Packets/GarrisonPackets.cpp b/src/server/game/Server/Packets/GarrisonPackets.cpp new file mode 100644 index 00000000000..8dff6ff86d4 --- /dev/null +++ b/src/server/game/Server/Packets/GarrisonPackets.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "GarrisonPackets.h" + +WorldPacket const* WorldPackets::Garrison::GarrisonCreateResult::Write() +{ + _worldPacket << uint32(Result); + _worldPacket << uint32(GarrSiteLevelID); + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonPlotInfo& plotInfo) +{ + data << uint32(plotInfo.GarrPlotInstanceID); + data << plotInfo.PlotPos.PositionXYZOStream(); + data << uint32(plotInfo.PlotType); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo) +{ + data << uint32(buildingInfo.GarrPlotInstanceID); + data << uint32(buildingInfo.GarrBuildingID); + data << uint32(buildingInfo.TimeBuilt); + data << uint32(buildingInfo.CurrentGarSpecID); + data << uint32(buildingInfo.TimeSpecCooldown); + data.WriteBit(buildingInfo.Active); + data.FlushBits(); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonFollower const& follower) +{ + data << uint64(follower.DbID); + data << uint32(follower.GarrFollowerID); + data << uint32(follower.Quality); + data << uint32(follower.FollowerLevel); + data << uint32(follower.ItemLevelWeapon); + data << uint32(follower.ItemLevelArmor); + data << uint32(follower.Xp); + data << uint32(follower.CurrentBuildingID); + data << uint32(follower.CurrentMissionID); + data << uint32(follower.AbilityID.size()); + data << uint32(follower.FollowerStatus); + if (!follower.AbilityID.empty()) + data.append(follower.AbilityID.data(), follower.AbilityID.size()); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonMission const& mission) +{ + data << uint64(mission.DbID); + data << uint32(mission.MissionRecID); + data << uint32(mission.OfferTime); + data << uint32(mission.OfferDuration); + data << uint32(mission.StartTime); + data << uint32(mission.TravelDuration); + data << uint32(mission.MissionDuration); + data << uint32(mission.MissionState); + + return data; +} + +WorldPacket const* WorldPackets::Garrison::GetGarrisonInfoResult::Write() +{ + _worldPacket.reserve(4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + + Buildings.size() * sizeof(GarrisonBuildingInfo) + + Plots.size() * sizeof(GarrisonPlotInfo) + + Followers.size() * (sizeof(GarrisonFollower) + 5 * 4) + + Missions.size() * sizeof(GarrisonMission) + + ArchivedMissions.size() * 4); + + _worldPacket << int32(GarrSiteID); + _worldPacket << int32(GarrSiteLevelID); + _worldPacket << int32(FactionIndex); + _worldPacket << uint32(Buildings.size()); + _worldPacket << uint32(Plots.size()); + _worldPacket << uint32(Followers.size()); + _worldPacket << uint32(Missions.size()); + _worldPacket << uint32(ArchivedMissions.size()); + _worldPacket << int32(NumFollowerActivationsRemaining); + + for (GarrisonBuildingInfo const* building : Buildings) + _worldPacket << *building; + + for (GarrisonPlotInfo* plot : Plots) + _worldPacket << *plot; + + for (GarrisonFollower const* follower : Followers) + _worldPacket << *follower; + + for (GarrisonMission const* mission : Missions) + _worldPacket << *mission; + + if (!ArchivedMissions.empty()) + _worldPacket.append(ArchivedMissions.data(), ArchivedMissions.size()); + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonRemoteBuildingInfo const& building) +{ + data << uint32(building.GarrPlotInstanceID); + data << uint32(building.GarrBuildingID); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonRemoteSiteInfo const& site) +{ + data << uint32(site.GarrSiteLevelID); + data << uint32(site.Buildings.size()); + for (WorldPackets::Garrison::GarrisonRemoteBuildingInfo const& building : site.Buildings) + data << building; + + return data; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonRemoteInfo::Write() +{ + _worldPacket << uint32(Sites.size()); + for (GarrisonRemoteSiteInfo const& site : Sites) + _worldPacket << site; + + return &_worldPacket; +} + +void WorldPackets::Garrison::GarrisonPurchaseBuilding::Read() +{ + _worldPacket >> NpcGUID; + _worldPacket >> PlotInstanceID; + _worldPacket >> BuildingID; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonPlaceBuildingResult::Write() +{ + _worldPacket << uint32(Result); + _worldPacket << BuildingInfo; + _worldPacket.WriteBit(PlayActivationCinematic); + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +void WorldPackets::Garrison::GarrisonCancelConstruction::Read() +{ + _worldPacket >> NpcGUID; + _worldPacket >> PlotInstanceID; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonBuildingRemoved::Write() +{ + _worldPacket << uint32(Result); + _worldPacket << uint32(GarrPlotInstanceID); + _worldPacket << uint32(GarrBuildingID); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonLearnBlueprintResult::Write() +{ + _worldPacket << uint32(Result); + _worldPacket << uint32(BuildingID); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonUnlearnBlueprintResult::Write() +{ + _worldPacket << uint32(Result); + _worldPacket << uint32(BuildingID); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationDataResult::Write() +{ + _worldPacket << uint32(BlueprintsKnown ? BlueprintsKnown->size() : 0); + _worldPacket << uint32(SpecializationsKnown ? SpecializationsKnown->size() : 0); + if (BlueprintsKnown) + for (uint32 blueprint : *BlueprintsKnown) + _worldPacket << uint32(blueprint); + + if (SpecializationsKnown) + for (uint32 specialization : *SpecializationsKnown) + _worldPacket << uint32(specialization); + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonBuildingLandmark& landmark) +{ + data << uint32(landmark.GarrBuildingPlotInstID); + data << landmark.Pos.PositionXYZStream(); + + return data; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonBuildingLandmarks::Write() +{ + _worldPacket << uint32(Landmarks.size()); + for (GarrisonBuildingLandmark& landmark : Landmarks) + _worldPacket << landmark; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonPlotPlaced::Write() +{ + _worldPacket << *PlotInfo; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Garrison::GarrisonPlotRemoved::Write() +{ + _worldPacket << uint32(GarrPlotInstanceID); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/GarrisonPackets.h b/src/server/game/Server/Packets/GarrisonPackets.h new file mode 100644 index 00000000000..288074284b5 --- /dev/null +++ b/src/server/game/Server/Packets/GarrisonPackets.h @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GarrisonPackets_h__ +#define GarrisonPackets_h__ + +#include "Packet.h" +#include "ObjectGuid.h" +#include "Position.h" +#include "PacketUtilities.h" + +namespace WorldPackets +{ + namespace Garrison + { + class GarrisonCreateResult final : public ServerPacket + { + public: + GarrisonCreateResult() : ServerPacket(SMSG_GARRISON_CREATE_RESULT, 4 + 4) { } + + WorldPacket const* Write() override; + + uint32 GarrSiteLevelID = 0; + uint32 Result = 0; + }; + + class GetGarrisonInfo final : public ClientPacket + { + public: + GetGarrisonInfo(WorldPacket&& packet) : ClientPacket(CMSG_GET_GARRISON_INFO, std::move(packet)) { } + + void Read() override { } + }; + + struct GarrisonPlotInfo + { + uint32 GarrPlotInstanceID = 0; + Position PlotPos; + uint32 PlotType = 0; + }; + + struct GarrisonBuildingInfo + { + uint32 GarrPlotInstanceID = 0; + uint32 GarrBuildingID = 0; + time_t TimeBuilt = time_t(0); + uint32 CurrentGarSpecID = 0; + time_t TimeSpecCooldown = time_t(2288912640); // 06/07/1906 18:35:44 - another in the series of magic blizz dates + bool Active = false; + }; + + struct GarrisonFollower + { + uint64 DbID = 0; + uint32 GarrFollowerID = 0; + uint32 Quality = 0; + uint32 FollowerLevel = 0; + uint32 ItemLevelWeapon = 0; + uint32 ItemLevelArmor = 0; + uint32 Xp = 0; + uint32 CurrentBuildingID = 0; + uint32 CurrentMissionID = 0; + std::vector<uint32> AbilityID; + uint32 FollowerStatus; + }; + + struct GarrisonMission + { + uint64 DbID = 0; + uint32 MissionRecID = 0; + time_t OfferTime = time_t(0); + uint32 OfferDuration = 0; + time_t StartTime = time_t(2288912640); + uint32 TravelDuration = 0; + uint32 MissionDuration = 0; + uint32 MissionState = 0; + }; + + class GetGarrisonInfoResult final : public ServerPacket + { + public: + GetGarrisonInfoResult() : ServerPacket(SMSG_GET_GARRISON_INFO_RESULT) { } + + WorldPacket const* Write() override; + + uint32 GarrSiteID = 0; + uint32 GarrSiteLevelID = 0; + uint32 FactionIndex = 0; + uint32 NumFollowerActivationsRemaining = 0; + std::vector<GarrisonPlotInfo*> Plots; + std::vector<GarrisonBuildingInfo*> Buildings; + std::vector<GarrisonFollower*> Followers; + std::vector<GarrisonMission*> Missions; + std::vector<int32> ArchivedMissions; + }; + + struct GarrisonRemoteBuildingInfo + { + GarrisonRemoteBuildingInfo() : GarrPlotInstanceID(0), GarrBuildingID(0) { } + GarrisonRemoteBuildingInfo(uint32 plotInstanceId, uint32 buildingId) : GarrPlotInstanceID(plotInstanceId), GarrBuildingID(buildingId) { } + + uint32 GarrPlotInstanceID; + uint32 GarrBuildingID; + }; + + struct GarrisonRemoteSiteInfo + { + uint32 GarrSiteLevelID = 0; + std::vector<GarrisonRemoteBuildingInfo> Buildings; + }; + + class GarrisonRemoteInfo final : public ServerPacket + { + public: + GarrisonRemoteInfo() : ServerPacket(SMSG_GARRISON_REMOTE_INFO) { } + + WorldPacket const* Write() override; + + std::vector<GarrisonRemoteSiteInfo> Sites; + }; + + class GarrisonPurchaseBuilding final : public ClientPacket + { + public: + GarrisonPurchaseBuilding(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_PURCHASE_BUILDING, std::move(packet)) { } + + void Read() override; + + ObjectGuid NpcGUID; + uint32 BuildingID = 0; + uint32 PlotInstanceID = 0; + }; + + class GarrisonPlaceBuildingResult final : public ServerPacket + { + public: + GarrisonPlaceBuildingResult() : ServerPacket(SMSG_GARRISON_PLACE_BUILDING_RESULT) { } + + WorldPacket const* Write() override; + + uint32 Result = 0; + GarrisonBuildingInfo BuildingInfo; + bool PlayActivationCinematic = false; + }; + + class GarrisonCancelConstruction final : public ClientPacket + { + public: + GarrisonCancelConstruction(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_CANCEL_CONSTRUCTION, std::move(packet)) { } + + void Read() override; + + ObjectGuid NpcGUID; + uint32 PlotInstanceID = 0; + }; + + class GarrisonBuildingRemoved final : public ServerPacket + { + public: + GarrisonBuildingRemoved() : ServerPacket(SMSG_GARRISON_BUILDING_REMOVED, 4 + 4 + 4) { } + + WorldPacket const* Write() override; + + uint32 Result = 0; + uint32 GarrPlotInstanceID = 0; + uint32 GarrBuildingID = 0; + }; + + class GarrisonLearnBlueprintResult final : public ServerPacket + { + public: + GarrisonLearnBlueprintResult() : ServerPacket(SMSG_GARRISON_LEARN_BLUEPRINT_RESULT, 4 + 4) { } + + WorldPacket const* Write() override; + + uint32 BuildingID = 0; + uint32 Result = 0; + }; + + class GarrisonUnlearnBlueprintResult final : public ServerPacket + { + public: + GarrisonUnlearnBlueprintResult() : ServerPacket(SMSG_GARRISON_UNLEARN_BLUEPRINT_RESULT, 4 + 4) { } + + WorldPacket const* Write() override; + + uint32 BuildingID = 0; + uint32 Result = 0; + }; + + class GarrisonRequestBlueprintAndSpecializationData final : public ClientPacket + { + public: + GarrisonRequestBlueprintAndSpecializationData(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA, std::move(packet)) { } + + void Read() override { } + }; + + class GarrisonRequestBlueprintAndSpecializationDataResult final : public ServerPacket + { + public: + GarrisonRequestBlueprintAndSpecializationDataResult() : ServerPacket(SMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA_RESULT, 400) { } + + WorldPacket const* Write() override; + + std::unordered_set<uint32> const* SpecializationsKnown = nullptr; + std::unordered_set<uint32> const* BlueprintsKnown = nullptr; + }; + + class GarrisonGetBuildingLandmarks final : public ClientPacket + { + public: + GarrisonGetBuildingLandmarks(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_GET_BUILDING_LANDMARKS, std::move(packet)) { } + + void Read() override { } + }; + + struct GarrisonBuildingLandmark + { + GarrisonBuildingLandmark() : GarrBuildingPlotInstID(0), Pos() { } + GarrisonBuildingLandmark(uint32 buildingPlotInstId, Position const& pos) : GarrBuildingPlotInstID(buildingPlotInstId), Pos(pos) { } + + uint32 GarrBuildingPlotInstID; + Position Pos; + }; + + class GarrisonBuildingLandmarks final : public ServerPacket + { + public: + GarrisonBuildingLandmarks() : ServerPacket(SMSG_GARRISON_BUILDING_LANDMARKS) { } + + WorldPacket const* Write() override; + + std::vector<GarrisonBuildingLandmark> Landmarks; + }; + + class GarrisonPlotPlaced final : public ServerPacket + { + public: + GarrisonPlotPlaced() : ServerPacket(SMSG_GARRISON_PLOT_PLACED) { } + + WorldPacket const* Write() override; + + GarrisonPlotInfo* PlotInfo = nullptr; + }; + + class GarrisonPlotRemoved final : public ServerPacket + { + public: + GarrisonPlotRemoved() : ServerPacket(SMSG_GARRISON_PLOT_REMOVED, 4) { } + + WorldPacket const* Write() override; + + uint32 GarrPlotInstanceID = 0; + }; + } +} + +#endif // GarrisonPackets_h__ diff --git a/src/server/game/Server/Packets/GuildPackets.cpp b/src/server/game/Server/Packets/GuildPackets.cpp index 7fcc0f05eda..1e361b3b7f6 100644 --- a/src/server/game/Server/Packets/GuildPackets.cpp +++ b/src/server/game/Server/Packets/GuildPackets.cpp @@ -29,32 +29,36 @@ WorldPackets::Guild::QueryGuildInfoResponse::QueryGuildInfoResponse() WorldPacket const* WorldPackets::Guild::QueryGuildInfoResponse::Write() { _worldPacket << GuildGuid; - _worldPacket.WriteBit(Info.HasValue); + _worldPacket.WriteBit(Info.is_initialized()); + _worldPacket.FlushBits(); - if (Info.HasValue) + if (Info) { - _worldPacket << Info.Value.GuildGUID; - _worldPacket << uint32(Info.Value.VirtualRealmAddress); - _worldPacket << uint32(Info.Value.Ranks.size()); - _worldPacket << uint32(Info.Value.EmblemStyle); - _worldPacket << uint32(Info.Value.EmblemColor); - _worldPacket << uint32(Info.Value.BorderStyle); - _worldPacket << uint32(Info.Value.BorderColor); - _worldPacket << uint32(Info.Value.BackgroundColor); - - for (GuildInfo::GuildInfoRank const& rank : Info.Value.Ranks) + _worldPacket << Info->GuildGUID; + _worldPacket << uint32(Info->VirtualRealmAddress); + _worldPacket << uint32(Info->Ranks.size()); + _worldPacket << uint32(Info->EmblemStyle); + _worldPacket << uint32(Info->EmblemColor); + _worldPacket << uint32(Info->BorderStyle); + _worldPacket << uint32(Info->BorderColor); + _worldPacket << uint32(Info->BackgroundColor); + + for (GuildInfo::GuildInfoRank const& rank : Info->Ranks) { _worldPacket << uint32(rank.RankID); _worldPacket << uint32(rank.RankOrder); _worldPacket.WriteBits(rank.RankName.size(), 7); + _worldPacket.FlushBits(); + _worldPacket.WriteString(rank.RankName); } - _worldPacket.WriteBits(Info.Value.GuildName.size(), 7); - _worldPacket.WriteString(Info.Value.GuildName); + _worldPacket.WriteBits(Info->GuildName.size(), 7); + _worldPacket.FlushBits(); + + _worldPacket.WriteString(Info->GuildName); } - _worldPacket.FlushBits(); return &_worldPacket; } @@ -69,7 +73,6 @@ WorldPacket const* WorldPackets::Guild::GuildRoster::Write() for (GuildRosterMemberData const& member : MemberData) _worldPacket << member; - _worldPacket.ResetBitPos(); _worldPacket.WriteBits(WelcomeText.length(), 10); _worldPacket.WriteBits(InfoText.length(), 10); _worldPacket.FlushBits(); @@ -672,30 +675,30 @@ WorldPacket const* WorldPackets::Guild::GuildBankLogQueryResults::Write() _worldPacket << logEntry.TimeOffset; _worldPacket << logEntry.EntryType; - _worldPacket.WriteBit(logEntry.Money.HasValue); - _worldPacket.WriteBit(logEntry.ItemID.HasValue); - _worldPacket.WriteBit(logEntry.Count.HasValue); - _worldPacket.WriteBit(logEntry.OtherTab.HasValue); + _worldPacket.WriteBit(logEntry.Money.is_initialized()); + _worldPacket.WriteBit(logEntry.ItemID.is_initialized()); + _worldPacket.WriteBit(logEntry.Count.is_initialized()); + _worldPacket.WriteBit(logEntry.OtherTab.is_initialized()); _worldPacket.FlushBits(); - if (logEntry.Money.HasValue) - _worldPacket << logEntry.Money.Value; + if (logEntry.Money.is_initialized()) + _worldPacket << *logEntry.Money; - if (logEntry.ItemID.HasValue) - _worldPacket << logEntry.ItemID.Value; + if (logEntry.ItemID.is_initialized()) + _worldPacket << *logEntry.ItemID; - if (logEntry.Count.HasValue) - _worldPacket << logEntry.Count.Value; + if (logEntry.Count.is_initialized()) + _worldPacket << *logEntry.Count; - if (logEntry.OtherTab.HasValue) - _worldPacket << logEntry.OtherTab.Value; + if (logEntry.OtherTab.is_initialized()) + _worldPacket << *logEntry.OtherTab; } - _worldPacket.WriteBit(WeeklyBonusMoney.HasValue); + _worldPacket.WriteBit(WeeklyBonusMoney.is_initialized()); _worldPacket.FlushBits(); - if (WeeklyBonusMoney.HasValue) - _worldPacket << WeeklyBonusMoney.Value; + if (WeeklyBonusMoney) + _worldPacket << *WeeklyBonusMoney; return &_worldPacket; } @@ -748,11 +751,11 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Guild::GuildNewsEvent con for (ObjectGuid memberGuid : newsEvent.MemberList) data << memberGuid; - data.WriteBit(newsEvent.Item.HasValue); + data.WriteBit(newsEvent.Item.is_initialized()); data.FlushBits(); - if (newsEvent.Item.HasValue) - data << newsEvent.Item.Value; // WorldPackets::Item::ItemInstance + if (newsEvent.Item) + data << *newsEvent.Item; // WorldPackets::Item::ItemInstance return data; } @@ -811,3 +814,17 @@ WorldPacket const* WorldPackets::Guild::PlayerSaveGuildEmblem::Write() return &_worldPacket; } + + +void WorldPackets::Guild::GuildSetAchievementTracking::Read() +{ + uint32 count; + _worldPacket >> count; + + for (uint32 i = 0; i < count; ++i) + { + uint32 value; + _worldPacket >> value; + AchievementIDs.insert(value); + } +} diff --git a/src/server/game/Server/Packets/GuildPackets.h b/src/server/game/Server/Packets/GuildPackets.h index 3202d2a3581..eab723c77af 100644 --- a/src/server/game/Server/Packets/GuildPackets.h +++ b/src/server/game/Server/Packets/GuildPackets.h @@ -1006,6 +1006,16 @@ namespace WorldPackets int32 Error = 0; }; + + class GuildSetAchievementTracking final : public ClientPacket + { + public: + GuildSetAchievementTracking(WorldPacket&& packet) : ClientPacket(CMSG_GUILD_SET_ACHIEVEMENT_TRACKING, std::move(packet)) { } + + void Read() override; + + std::set<uint32> AchievementIDs; + }; } } diff --git a/src/server/game/Server/Packets/InspectPackets.cpp b/src/server/game/Server/Packets/InspectPackets.cpp index 9d98d30bd74..5c703c57c0c 100644 --- a/src/server/game/Server/Packets/InspectPackets.cpp +++ b/src/server/game/Server/Packets/InspectPackets.cpp @@ -92,11 +92,11 @@ WorldPacket const* WorldPackets::Inspect::InspectResult::Write() for (size_t i = 0; i < Talents.size(); ++i) _worldPacket << uint16(Talents[i]); - _worldPacket.WriteBit(GuildData.HasValue); + _worldPacket.WriteBit(GuildData.is_initialized()); _worldPacket.FlushBits(); - if (GuildData.HasValue) - _worldPacket << GuildData.Value; + if (GuildData) + _worldPacket << *GuildData; return &_worldPacket; } diff --git a/src/server/game/Server/Packets/InstancePackets.cpp b/src/server/game/Server/Packets/InstancePackets.cpp new file mode 100644 index 00000000000..50b2a66a8b8 --- /dev/null +++ b/src/server/game/Server/Packets/InstancePackets.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "InstancePackets.h" + +WorldPacket const* WorldPackets::Instance::UpdateLastInstance::Write() +{ + _worldPacket << uint32(MapID); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Instance::UpdateInstanceOwnership::Write() +{ + _worldPacket << int32(IOwnInstance); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/InstancePackets.h b/src/server/game/Server/Packets/InstancePackets.h new file mode 100644 index 00000000000..09f6c1efdcb --- /dev/null +++ b/src/server/game/Server/Packets/InstancePackets.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef InstancePackets_h__ +#define InstancePackets_h__ + +#include "Packet.h" +#include "ObjectGuid.h" + +namespace WorldPackets +{ + namespace Instance + { + class UpdateLastInstance final : public ServerPacket + { + public: + UpdateLastInstance() : ServerPacket(SMSG_UPDATE_LAST_INSTANCE, 4) { } + + WorldPacket const* Write() override; + + uint32 MapID = 0; + }; + + // This packet is no longer sent - it is only here for documentation purposes + class UpdateInstanceOwnership final : public ServerPacket + { + public: + UpdateInstanceOwnership() : ServerPacket(SMSG_UPDATE_INSTANCE_OWNERSHIP, 4) { } + + WorldPacket const* Write() override; + + int32 IOwnInstance = 0; // Used to control whether "Reset all instances" button appears on the UI - Script_CanShowResetInstances() + // but it has been deperecated in favor of simply checking group leader, being inside an instance or using dungeon finder + }; + } +} + +#endif // InstancePackets_h__ diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp index 958a6c9c33a..a4da605ca08 100644 --- a/src/server/game/Server/Packets/ItemPackets.cpp +++ b/src/server/game/Server/Packets/ItemPackets.cpp @@ -100,18 +100,20 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceDa return data; } -ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemBonusInstanceData& itemBonusInstanceData) +ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Item::ItemBonusInstanceData>& itemBonusInstanceData) { uint32 bonusListIdSize; - data >> itemBonusInstanceData.Context; + itemBonusInstanceData = boost::in_place(); + + data >> itemBonusInstanceData->Context; data >> bonusListIdSize; for (uint32 i = 0u; i < bonusListIdSize; ++i) { uint32 bonusId; data >> bonusId; - itemBonusInstanceData.BonusListIDs.push_back(bonusId); + itemBonusInstanceData->BonusListIDs.push_back(bonusId); } return data; @@ -123,15 +125,15 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemInstance const& data << int32(itemInstance.RandomPropertiesSeed); data << int32(itemInstance.RandomPropertiesID); - data.WriteBit(itemInstance.ItemBonus.HasValue); - data.WriteBit(itemInstance.Modifications.HasValue); + data.WriteBit(itemInstance.ItemBonus.is_initialized()); + data.WriteBit(itemInstance.Modifications.is_initialized()); data.FlushBits(); - if (itemInstance.ItemBonus.HasValue) - data << itemInstance.ItemBonus.Value; + if (itemInstance.ItemBonus) + data << *itemInstance.ItemBonus; - if (itemInstance.Modifications.HasValue) - data << itemInstance.Modifications.Value; + if (itemInstance.Modifications) + data << *itemInstance.Modifications; return data; } @@ -142,14 +144,18 @@ ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::ItemInstance& itemI data >> itemInstance.RandomPropertiesSeed; data >> itemInstance.RandomPropertiesID; - itemInstance.ItemBonus.HasValue = data.ReadBit(); - itemInstance.Modifications.HasValue = data.ReadBit(); + bool const hasItemBonus = data.ReadBit(); + bool const hasModifications = data.ReadBit(); - if (itemInstance.ItemBonus.HasValue) - data >> itemInstance.ItemBonus.Value; + if (hasItemBonus) + data >> itemInstance.ItemBonus; - if (itemInstance.Modifications.HasValue) - data >> itemInstance.Modifications.Value; + if (hasModifications) + { + WorldPackets::CompactArray<int32> modifications; + data >> modifications; + itemInstance.Modifications = std::move(modifications); + } return data; } @@ -174,18 +180,19 @@ void WorldPackets::Item::ItemInstance::Initialize(::Item const* item) std::vector<uint32> const& bonusListIds = item->GetDynamicValues(ITEM_DYNAMIC_FIELD_BONUSLIST_IDS); if (!bonusListIds.empty()) { - ItemBonus.HasValue = true; - ItemBonus.Value.BonusListIDs.insert(ItemBonus.Value.BonusListIDs.end(), bonusListIds.begin(), bonusListIds.end()); - ItemBonus.Value.Context = item->GetUInt32Value(ITEM_FIELD_CONTEXT); + ItemBonus = boost::in_place(); + ItemBonus->BonusListIDs.insert(ItemBonus->BonusListIDs.end(), bonusListIds.begin(), bonusListIds.end()); + ItemBonus->Context = item->GetUInt32Value(ITEM_FIELD_CONTEXT); } uint32 mask = item->GetUInt32Value(ITEM_FIELD_MODIFIERS_MASK); - Modifications.HasValue = mask != 0; + if (mask != 0) + Modifications = WorldPackets::CompactArray<int32>(); for (size_t i = 0; mask != 0; mask >>= 1, ++i) { if ((mask & 1) != 0) - Modifications.Value.Insert(i, item->GetModifier(ItemModifier(i))); + Modifications->Insert(i, item->GetModifier(ItemModifier(i))); } } @@ -196,9 +203,9 @@ void WorldPackets::Item::ItemInstance::Initialize(::LootItem const& lootItem) RandomPropertiesID = lootItem.randomPropertyId; if (!lootItem.BonusListIDs.empty()) { - ItemBonus.HasValue = true; - ItemBonus.Value.BonusListIDs = lootItem.BonusListIDs; - ItemBonus.Value.Context = 0; /// @todo + ItemBonus = boost::in_place(); + ItemBonus->BonusListIDs = lootItem.BonusListIDs; + ItemBonus->Context = 0; /// @todo } /// no Modifications @@ -357,3 +364,13 @@ WorldPacket const* WorldPackets::Item::ReadItemResultOK::Write() return &_worldPacket; } + +void WorldPackets::Item::WrapItem::Read() +{ + _worldPacket >> Inv; +} + +void WorldPackets::Item::CancelTempEnchantment::Read() +{ + _worldPacket >> Slot; +} diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h index f9c700b0cb4..7b0b9e41e4b 100644 --- a/src/server/game/Server/Packets/ItemPackets.h +++ b/src/server/game/Server/Packets/ItemPackets.h @@ -343,6 +343,26 @@ namespace WorldPackets ObjectGuid Item; }; + class WrapItem final : public ClientPacket + { + public: + WrapItem(WorldPacket&& packet) : ClientPacket(CMSG_WRAP_ITEM, std::move(packet)) { } + + void Read() override; + + InvUpdate Inv; + }; + + class CancelTempEnchantment final : public ClientPacket + { + public: + CancelTempEnchantment(WorldPacket&& packet) : ClientPacket(CMSG_CANCEL_TEMP_ENCHANTMENT, std::move(packet)) { } + + void Read() override; + + int32 Slot = 0; + }; + ByteBuffer& operator>>(ByteBuffer& data, InvUpdate& invUpdate); } } diff --git a/src/server/game/Server/Packets/MailPackets.cpp b/src/server/game/Server/Packets/MailPackets.cpp index b1de05aac25..7ff189bbe2e 100644 --- a/src/server/game/Server/Packets/MailPackets.cpp +++ b/src/server/game/Server/Packets/MailPackets.cpp @@ -70,13 +70,13 @@ WorldPackets::Mail::MailListEntry::MailListEntry(::Mail const* mail, ::Player* p switch (mail->messageType) { case MAIL_NORMAL: - SenderCharacter.Set(ObjectGuid::Create<HighGuid::Player>(mail->sender)); + SenderCharacter = ObjectGuid::Create<HighGuid::Player>(mail->sender); break; case MAIL_CREATURE: case MAIL_GAMEOBJECT: case MAIL_AUCTION: case MAIL_CALENDAR: - AltSenderID.Set(mail->sender); + AltSenderID = mail->sender; break; } @@ -115,18 +115,18 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Mail::MailListEntry const for (auto const& att : entry.Attachments) data << att; - data.WriteBit(entry.SenderCharacter.HasValue); - data.WriteBit(entry.AltSenderID.HasValue); + data.WriteBit(entry.SenderCharacter.is_initialized()); + data.WriteBit(entry.AltSenderID.is_initialized()); data.WriteBits(entry.Subject.size(), 8); data.WriteBits(entry.Body.size(), 13); data.FlushBits(); - if (entry.SenderCharacter.HasValue) - data << entry.SenderCharacter.Value; + if (entry.SenderCharacter) + data << *entry.SenderCharacter; - if (entry.AltSenderID.HasValue) - data << int32(entry.AltSenderID.Value); + if (entry.AltSenderID) + data << int32(*entry.AltSenderID); data.WriteString(entry.Subject); data.WriteString(entry.Body); @@ -273,3 +273,10 @@ WorldPacket const* WorldPackets::Mail::NotifyRecievedMail::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Mail::ShowMailbox::Write() +{ + _worldPacket << PostmasterGUID; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/MailPackets.h b/src/server/game/Server/Packets/MailPackets.h index f1d82ebb397..2486d65fe5b 100644 --- a/src/server/game/Server/Packets/MailPackets.h +++ b/src/server/game/Server/Packets/MailPackets.h @@ -246,6 +246,15 @@ namespace WorldPackets float Delay = 0.0f; }; + class ShowMailbox final : public ServerPacket + { + public: + ShowMailbox() : ServerPacket(SMSG_SHOW_MAILBOX, 16) { } + + WorldPacket const* Write() override; + + ObjectGuid PostmasterGUID; + }; } } diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp index 49f6d8501cf..a12ff537050 100644 --- a/src/server/game/Server/Packets/MiscPackets.cpp +++ b/src/server/game/Server/Packets/MiscPackets.cpp @@ -50,15 +50,15 @@ WorldPacket const* WorldPackets::Misc::SetCurrency::Write() _worldPacket << uint32(Type); _worldPacket << uint32(Quantity); _worldPacket << uint32(Flags); - _worldPacket.WriteBit(WeeklyQuantity.HasValue); - _worldPacket.WriteBit(TrackedQuantity.HasValue); + _worldPacket.WriteBit(WeeklyQuantity.is_initialized()); + _worldPacket.WriteBit(TrackedQuantity.is_initialized()); _worldPacket.WriteBit(SuppressChatLog); - if (WeeklyQuantity.HasValue) - _worldPacket << uint32(WeeklyQuantity.Value); + if (WeeklyQuantity) + _worldPacket << uint32(*WeeklyQuantity); - if (TrackedQuantity.HasValue) - _worldPacket << uint32(TrackedQuantity.Value); + if (TrackedQuantity) + _worldPacket << uint32(*TrackedQuantity); _worldPacket.FlushBits(); @@ -79,18 +79,18 @@ WorldPacket const* WorldPackets::Misc::SetupCurrency::Write() _worldPacket << uint32(data.Type); _worldPacket << uint32(data.Quantity); - _worldPacket.WriteBit(data.WeeklyQuantity.HasValue); - _worldPacket.WriteBit(data.MaxWeeklyQuantity.HasValue); - _worldPacket.WriteBit(data.TrackedQuantity.HasValue); + _worldPacket.WriteBit(data.WeeklyQuantity.is_initialized()); + _worldPacket.WriteBit(data.MaxWeeklyQuantity.is_initialized()); + _worldPacket.WriteBit(data.TrackedQuantity.is_initialized()); _worldPacket.WriteBits(data.Flags, 5); - if (data.WeeklyQuantity.HasValue) - _worldPacket << uint32(data.WeeklyQuantity.Value); - if (data.MaxWeeklyQuantity.HasValue) - _worldPacket << uint32(data.MaxWeeklyQuantity.Value); - if (data.TrackedQuantity.HasValue) - _worldPacket << uint32(data.TrackedQuantity.Value); + if (data.WeeklyQuantity) + _worldPacket << uint32(*data.WeeklyQuantity); + if (data.MaxWeeklyQuantity) + _worldPacket << uint32(*data.MaxWeeklyQuantity); + if (data.TrackedQuantity) + _worldPacket << uint32(*data.TrackedQuantity); } _worldPacket.FlushBits(); @@ -154,22 +154,22 @@ WorldPacket const* WorldPackets::Misc::WorldServerInfo::Write() _worldPacket << uint32(DifficultyID); _worldPacket << uint8(IsTournamentRealm); _worldPacket << uint32(WeeklyReset); - _worldPacket.WriteBit(RestrictedAccountMaxLevel.HasValue); - _worldPacket.WriteBit(RestrictedAccountMaxMoney.HasValue); - _worldPacket.WriteBit(IneligibleForLootMask.HasValue); - _worldPacket.WriteBit(InstanceGroupSize.HasValue); + _worldPacket.WriteBit(RestrictedAccountMaxLevel.is_initialized()); + _worldPacket.WriteBit(RestrictedAccountMaxMoney.is_initialized()); + _worldPacket.WriteBit(IneligibleForLootMask.is_initialized()); + _worldPacket.WriteBit(InstanceGroupSize.is_initialized()); - if (RestrictedAccountMaxLevel.HasValue) - _worldPacket << uint32(RestrictedAccountMaxLevel.Value); + if (RestrictedAccountMaxLevel) + _worldPacket << uint32(*RestrictedAccountMaxLevel); - if (RestrictedAccountMaxMoney.HasValue) - _worldPacket << uint32(RestrictedAccountMaxMoney.Value); + if (RestrictedAccountMaxMoney) + _worldPacket << uint32(*RestrictedAccountMaxMoney); - if (IneligibleForLootMask.HasValue) - _worldPacket << uint32(IneligibleForLootMask.Value); + if (IneligibleForLootMask) + _worldPacket << uint32(*IneligibleForLootMask); - if (InstanceGroupSize.HasValue) - _worldPacket << uint32(InstanceGroupSize.Value); + if (InstanceGroupSize) + _worldPacket << uint32(*InstanceGroupSize); _worldPacket.FlushBits(); @@ -439,3 +439,15 @@ WorldPacket const* WorldPackets::Misc::PlaySound::Write() return &_worldPacket; } + +void WorldPackets::Misc::FarSight::Read() +{ + Enable = _worldPacket.ReadBit(); +} + +WorldPacket const* WorldPackets::Misc::Dismount::Write() +{ + _worldPacket << Guid; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h index c79fb5ba762..fda0e44990e 100644 --- a/src/server/game/Server/Packets/MiscPackets.h +++ b/src/server/game/Server/Packets/MiscPackets.h @@ -606,6 +606,42 @@ namespace WorldPackets ObjectGuid SourceObjectGuid; int32 SoundKitID = 0; }; + + class CompleteCinematic final : public ClientPacket + { + public: + CompleteCinematic(WorldPacket&& packet) : ClientPacket(CMSG_COMPLETE_CINEMATIC, std::move(packet)) { } + + void Read() override { } + }; + + class NextCinematicCamera final : public ClientPacket + { + public: + NextCinematicCamera(WorldPacket&& packet) : ClientPacket(CMSG_NEXT_CINEMATIC_CAMERA, std::move(packet)) { } + + void Read() override { } + }; + + class FarSight final : public ClientPacket + { + public: + FarSight(WorldPacket&& packet) : ClientPacket(CMSG_FAR_SIGHT, std::move(packet)) { } + + void Read() override; + + bool Enable = false; + }; + + class Dismount final : public ServerPacket + { + public: + Dismount() : ServerPacket(SMSG_DISMOUNT, 16) { } + + WorldPacket const* Write() override; + + ObjectGuid Guid; + }; } } diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index 4392f6c8a05..14fb2ecb33c 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -198,9 +198,9 @@ ByteBuffer& WorldPackets::operator<<(ByteBuffer& data, Movement::MonsterSplineFi data << monsterSplineFilter.BaseSpeed; data << monsterSplineFilter.StartOffset; data << monsterSplineFilter.DistToPrevFilterKey; + data << monsterSplineFilter.AddedToStart; for (WorldPackets::Movement::MonsterSplineFilterKey const& filterKey : monsterSplineFilter.FilterKeys) data << filterKey; - data << monsterSplineFilter.AddedToStart; data.WriteBits(monsterSplineFilter.FilterFlags, 2); data.FlushBits(); @@ -227,7 +227,7 @@ ByteBuffer& WorldPackets::operator<<(ByteBuffer& data, Movement::MovementSpline for (G3D::Vector3 const& pos : movementSpline.PackedDeltas) data.appendPackXYZ(pos.x, pos.y, pos.z); data.WriteBits(movementSpline.Face, 2); - data.WriteBit(movementSpline.SplineFilter.HasValue); + data.WriteBit(movementSpline.SplineFilter.is_initialized()); data.FlushBits(); switch (movementSpline.Face) @@ -244,8 +244,8 @@ ByteBuffer& WorldPackets::operator<<(ByteBuffer& data, Movement::MovementSpline break; } - if (movementSpline.SplineFilter.HasValue) - data << movementSpline.SplineFilter.Value; + if (movementSpline.SplineFilter) + data << *movementSpline.SplineFilter; return data; } @@ -479,16 +479,16 @@ WorldPacket const* WorldPackets::Movement::MoveUpdate::Write() WorldPacket const* WorldPackets::Movement::TransferPending::Write() { _worldPacket << int32(MapID); - _worldPacket.WriteBit(Ship.HasValue); - _worldPacket.WriteBit(TransferSpellID.HasValue); - if (Ship.HasValue) + _worldPacket.WriteBit(Ship.is_initialized()); + _worldPacket.WriteBit(TransferSpellID.is_initialized()); + if (Ship) { - _worldPacket << uint32(Ship.Value.ID); - _worldPacket << int32(Ship.Value.OriginMapID); + _worldPacket << uint32(Ship->ID); + _worldPacket << int32(Ship->OriginMapID); } - if (TransferSpellID.HasValue) - _worldPacket << int32(TransferSpellID.Value); + if (TransferSpellID) + _worldPacket << int32(*TransferSpellID); _worldPacket.FlushBits(); @@ -519,18 +519,18 @@ WorldPacket const* WorldPackets::Movement::MoveTeleport::Write() _worldPacket << Pos.PositionXYZStream(); _worldPacket << Facing; - _worldPacket.WriteBit(TransportGUID.HasValue); - _worldPacket.WriteBit(Vehicle.HasValue); + _worldPacket.WriteBit(TransportGUID.is_initialized()); + _worldPacket.WriteBit(Vehicle.is_initialized()); _worldPacket.FlushBits(); - if (TransportGUID.HasValue) - _worldPacket << TransportGUID.Value; + if (TransportGUID) + _worldPacket << *TransportGUID; - if (Vehicle.HasValue) + if (Vehicle) { - _worldPacket << Vehicle.Value.VehicleSeatIndex; - _worldPacket.WriteBit(Vehicle.Value.VehicleExitVoluntary); - _worldPacket.WriteBit(Vehicle.Value.VehicleExitTeleport); + _worldPacket << Vehicle->VehicleSeatIndex; + _worldPacket.WriteBit(Vehicle->VehicleExitVoluntary); + _worldPacket.WriteBit(Vehicle->VehicleExitTeleport); _worldPacket.FlushBits(); } @@ -552,44 +552,44 @@ WorldPacket const* WorldPackets::Movement::MoveUpdateTeleport::Write() _worldPacket.FlushBits(); } - _worldPacket.WriteBit(WalkSpeed.HasValue); - _worldPacket.WriteBit(RunSpeed.HasValue); - _worldPacket.WriteBit(RunBackSpeed.HasValue); - _worldPacket.WriteBit(SwimSpeed.HasValue); - _worldPacket.WriteBit(SwimBackSpeed.HasValue); - _worldPacket.WriteBit(FlightSpeed.HasValue); - _worldPacket.WriteBit(FlightBackSpeed.HasValue); - _worldPacket.WriteBit(TurnRate.HasValue); - _worldPacket.WriteBit(PitchRate.HasValue); + _worldPacket.WriteBit(WalkSpeed.is_initialized()); + _worldPacket.WriteBit(RunSpeed.is_initialized()); + _worldPacket.WriteBit(RunBackSpeed.is_initialized()); + _worldPacket.WriteBit(SwimSpeed.is_initialized()); + _worldPacket.WriteBit(SwimBackSpeed.is_initialized()); + _worldPacket.WriteBit(FlightSpeed.is_initialized()); + _worldPacket.WriteBit(FlightBackSpeed.is_initialized()); + _worldPacket.WriteBit(TurnRate.is_initialized()); + _worldPacket.WriteBit(PitchRate.is_initialized()); _worldPacket.FlushBits(); - if (WalkSpeed.HasValue) - _worldPacket << WalkSpeed.Value; + if (WalkSpeed) + _worldPacket << *WalkSpeed; - if (RunSpeed.HasValue) - _worldPacket << RunSpeed.Value; + if (RunSpeed) + _worldPacket << *RunSpeed; - if (RunBackSpeed.HasValue) - _worldPacket << RunBackSpeed.Value; + if (RunBackSpeed) + _worldPacket << *RunBackSpeed; - if (SwimSpeed.HasValue) - _worldPacket << SwimSpeed.Value; + if (SwimSpeed) + _worldPacket << *SwimSpeed; - if (SwimBackSpeed.HasValue) - _worldPacket << SwimBackSpeed.Value; + if (SwimBackSpeed) + _worldPacket << *SwimBackSpeed; - if (FlightSpeed.HasValue) - _worldPacket << FlightSpeed.Value; + if (FlightSpeed) + _worldPacket << *FlightSpeed; - if (FlightBackSpeed.HasValue) - _worldPacket << FlightBackSpeed.Value; + if (FlightBackSpeed) + _worldPacket << *FlightBackSpeed; - if (TurnRate.HasValue) - _worldPacket << TurnRate.Value; + if (TurnRate) + _worldPacket << *TurnRate; - if (PitchRate.HasValue) - _worldPacket << PitchRate.Value; + if (PitchRate) + _worldPacket << *PitchRate; return &_worldPacket; } diff --git a/src/server/game/Server/Packets/NPCPackets.cpp b/src/server/game/Server/Packets/NPCPackets.cpp index 2ca1ad7447d..a6c74459bf5 100644 --- a/src/server/game/Server/Packets/NPCPackets.cpp +++ b/src/server/game/Server/Packets/NPCPackets.cpp @@ -163,3 +163,31 @@ WorldPacket const* WorldPackets::NPC::GossipPOI::Write() return &_worldPacket; } + +void WorldPackets::NPC::SpiritHealerActivate::Read() +{ + _worldPacket >> Healer; +} + +WorldPacket const* WorldPackets::NPC::SpiritHealerConfirm::Write() +{ + _worldPacket << Unit; + + return &_worldPacket; +} + +void WorldPackets::NPC::TrainerBuySpell::Read() +{ + _worldPacket >> TrainerGUID; + _worldPacket >> TrainerID; + _worldPacket >> SpellID; +} + +WorldPacket const* WorldPackets::NPC::TrainerBuyFailed::Write() +{ + _worldPacket << TrainerGUID; + _worldPacket << SpellID; + _worldPacket << TrainerFailedReason; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/NPCPackets.h b/src/server/game/Server/Packets/NPCPackets.h index a6e265b5d9f..990ef897986 100644 --- a/src/server/game/Server/Packets/NPCPackets.h +++ b/src/server/game/Server/Packets/NPCPackets.h @@ -196,6 +196,50 @@ namespace WorldPackets int32 Importance = 0; std::string Name; }; + + class SpiritHealerActivate final : public ClientPacket + { + public: + SpiritHealerActivate(WorldPacket&& packet) : ClientPacket(CMSG_SPIRIT_HEALER_ACTIVATE, std::move(packet)) { } + + void Read() override; + + ObjectGuid Healer; + }; + + class SpiritHealerConfirm final : public ServerPacket + { + public: + SpiritHealerConfirm() : ServerPacket(SMSG_SPIRIT_HEALER_CONFIRM, 16) { } + + WorldPacket const* Write() override; + + ObjectGuid Unit; + }; + + class TrainerBuySpell final : public ClientPacket + { + public: + TrainerBuySpell(WorldPacket&& packet) : ClientPacket(CMSG_TRAINER_BUY_SPELL, std::move(packet)) { } + + void Read() override; + + ObjectGuid TrainerGUID; + int32 TrainerID = 0; + int32 SpellID = 0; + }; + + class TrainerBuyFailed final : public ServerPacket + { + public: + TrainerBuyFailed() : ServerPacket(SMSG_TRAINER_BUY_FAILED, 16 + 4 + 4) { } + + WorldPacket const* Write() override; + + ObjectGuid TrainerGUID; + int32 SpellID = 0; + int32 TrainerFailedReason = 0; + }; } } diff --git a/src/server/game/Server/Packets/PacketUtilities.h b/src/server/game/Server/Packets/PacketUtilities.h index 32d9f8b8cab..f92d949d1be 100644 --- a/src/server/game/Server/Packets/PacketUtilities.h +++ b/src/server/game/Server/Packets/PacketUtilities.h @@ -49,9 +49,35 @@ inline ByteBuffer& operator>>(ByteBuffer& data, G3D::Vector3& v) namespace WorldPackets { template <typename T> - struct CompactArray + class CompactArray { public: + CompactArray() : _mask(0) { } + + CompactArray(CompactArray const& right) + : _mask(right._mask), _contents(right._contents) { } + + CompactArray(CompactArray&& right) + : _mask(right._mask), _contents(std::move(right._contents)) + { + right._mask = 0; + } + + CompactArray& operator= (CompactArray const& right) + { + _mask = right._mask; + _contents = right._contents; + return *this; + } + + CompactArray& operator= (CompactArray&& right) + { + _mask = right._mask; + right._mask = 0; + _contents = std::move(right._contents); + return *this; + } + uint32 GetMask() const { return _mask; } T const& operator[](size_t index) const { return _contents.at(index); } size_t GetSize() const { return _contents.size(); } @@ -73,7 +99,7 @@ namespace WorldPackets } private: - uint32 _mask = 0; + uint32 _mask; std::vector<T> _contents; }; diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp index 9ac9d79a41f..f7806a9e588 100644 --- a/src/server/game/Server/Packets/QueryPackets.cpp +++ b/src/server/game/Server/Packets/QueryPackets.cpp @@ -100,15 +100,15 @@ void WorldPackets::Query::QueryPlayerName::Read() ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupHint const& lookupHint) { - data.WriteBit(lookupHint.VirtualRealmAddress.HasValue); - data.WriteBit(lookupHint.NativeRealmAddress.HasValue); + data.WriteBit(lookupHint.VirtualRealmAddress.is_initialized()); + data.WriteBit(lookupHint.NativeRealmAddress.is_initialized()); data.FlushBits(); - if (lookupHint.VirtualRealmAddress.HasValue) - data << uint32(lookupHint.VirtualRealmAddress.Value); + if (lookupHint.VirtualRealmAddress) + data << uint32(*lookupHint.VirtualRealmAddress); - if (lookupHint.NativeRealmAddress.HasValue) - data << uint32(lookupHint.NativeRealmAddress.Value); + if (lookupHint.NativeRealmAddress) + data << uint32(*lookupHint.NativeRealmAddress); return data; } @@ -176,8 +176,6 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupDa data << uint8(lookupData.Level); data.WriteString(lookupData.Name); - data.FlushBits(); - return data; } @@ -210,6 +208,8 @@ WorldPacket const* WorldPackets::Query::QueryPageTextResponse::Write() _worldPacket << Info.ID; _worldPacket << Info.NextPageID; _worldPacket.WriteBits(Info.Text.length(), 12); + _worldPacket.FlushBits(); + _worldPacket.WriteString(Info.Text); } @@ -290,6 +290,7 @@ WorldPacket const* WorldPackets::Query::QueryGameObjectResponse::Write() { _worldPacket << GameObjectID; _worldPacket.WriteBit(Allow); + _worldPacket.FlushBits(); if (Allow) { @@ -434,3 +435,57 @@ WorldPacket const* WorldPackets::Query::QuestCompletionNPCResponse::Write() return &_worldPacket; } + +void WorldPackets::Query::QueryPetName::Read() +{ + _worldPacket >> UnitGUID; +} + +WorldPacket const* WorldPackets::Query::QueryPetNameResponse::Write() +{ + _worldPacket << UnitGUID; + _worldPacket.WriteBit(Allow); + + if (Allow) + { + _worldPacket.WriteBits(Name.length(), 8); + _worldPacket.WriteBit(HasDeclined); + + for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + _worldPacket.WriteBits(DeclinedNames.name[i].length(), 7); + + for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + _worldPacket.WriteString(DeclinedNames.name[i]); + + _worldPacket << Timestamp; + _worldPacket.WriteString(Name); + } + + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +void WorldPackets::Query::ItemTextQuery::Read() +{ + _worldPacket >> Id; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::ItemTextCache const& itemTextCache) +{ + data.WriteBits(itemTextCache.Text.length(), 13); + data.FlushBits(); + + data.WriteString(itemTextCache.Text); + + return data; +} + +WorldPacket const* WorldPackets::Query::QueryItemTextResponse::Write() +{ + _worldPacket.WriteBit(Valid); + _worldPacket << Id; + _worldPacket << Item; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/QueryPackets.h b/src/server/game/Server/Packets/QueryPackets.h index 8e9613019c8..88bf5a887f6 100644 --- a/src/server/game/Server/Packets/QueryPackets.h +++ b/src/server/game/Server/Packets/QueryPackets.h @@ -392,6 +392,59 @@ namespace WorldPackets std::vector<QuestCompletionNPC> QuestCompletionNPCs; }; + + class QueryPetName final : public ClientPacket + { + public: + QueryPetName(WorldPacket&& packet) : ClientPacket(CMSG_QUERY_PET_NAME, std::move(packet)) { } + + void Read() override; + + ObjectGuid UnitGUID; + }; + + class QueryPetNameResponse final : public ServerPacket + { + public: + QueryPetNameResponse() : ServerPacket(SMSG_QUERY_PET_NAME_RESPONSE, 16 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid UnitGUID; + bool Allow = false; + + bool HasDeclined = false; + DeclinedName DeclinedNames; + uint32 Timestamp = 0; + std::string Name; + }; + + class ItemTextQuery final : public ClientPacket + { + public: + ItemTextQuery(WorldPacket&& packet) : ClientPacket(CMSG_ITEM_TEXT_QUERY, std::move(packet)) { } + + void Read() override; + + ObjectGuid Id; + }; + + struct ItemTextCache + { + std::string Text; + }; + + class QueryItemTextResponse final : public ServerPacket + { + public: + QueryItemTextResponse() : ServerPacket(SMSG_QUERY_ITEM_TEXT_RESPONSE) { } + + WorldPacket const* Write() override; + + ObjectGuid Id; + bool Valid = false; + ItemTextCache Item; + }; } } diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp index 5a5320a4e2f..ad4001899fe 100644 --- a/src/server/game/Server/Packets/QuestPackets.cpp +++ b/src/server/game/Server/Packets/QuestPackets.cpp @@ -149,10 +149,12 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write() _worldPacket << questObjective.UnkFloat; _worldPacket << int32(questObjective.VisualEffects.size()); - for (auto& visualEffect : questObjective.VisualEffects) + for (int32 visualEffect : questObjective.VisualEffects) _worldPacket << visualEffect; _worldPacket.WriteBits(questObjective.Description.size(), 8); + _worldPacket.FlushBits(); + _worldPacket.WriteString(questObjective.Description); } @@ -165,6 +167,7 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write() _worldPacket.WriteBits(Info.PortraitTurnInText.size(), 10); _worldPacket.WriteBits(Info.PortraitTurnInName.size(), 8); _worldPacket.WriteBits(Info.QuestCompletionLog.size(), 11); + _worldPacket.FlushBits(); _worldPacket.WriteString(Info.LogTitle); _worldPacket.WriteString(Info.LogDescription); @@ -277,6 +280,7 @@ WorldPacket const* WorldPackets::Quest::QuestGiverOfferRewardMessage::Write() _worldPacket.WriteBits(PortraitGiverName.size(), 8); _worldPacket.WriteBits(PortraitGiverText.size(), 10); _worldPacket.WriteBits(PortraitTurnInName.size(), 8); + _worldPacket.FlushBits(); _worldPacket.WriteString(QuestTitle); _worldPacket.WriteString(RewardText); @@ -362,6 +366,7 @@ WorldPacket const* WorldPackets::Quest::QuestGiverQuestDetails::Write() _worldPacket.WriteBit(DisplayPopup); _worldPacket.WriteBit(StartCheat); _worldPacket.WriteBit(AutoLaunched); + _worldPacket.FlushBits(); _worldPacket.WriteString(QuestTitle); _worldPacket.WriteString(DescriptionText); @@ -406,6 +411,7 @@ WorldPacket const* WorldPackets::Quest::QuestGiverRequestItems::Write() _worldPacket.WriteBits(QuestTitle.size(), 9); _worldPacket.WriteBits(CompletionText.size(), 12); + _worldPacket.FlushBits(); _worldPacket.WriteString(QuestTitle); _worldPacket.WriteString(CompletionText); @@ -477,6 +483,8 @@ WorldPacket const* WorldPackets::Quest::QuestConfirmAcceptResponse::Write() _worldPacket << InitiatedBy; _worldPacket.WriteBits(QuestTitle.size(), 10); + _worldPacket.FlushBits(); + _worldPacket.WriteString(QuestTitle); return &_worldPacket; diff --git a/src/server/game/Server/Packets/ReferAFriendPackets.cpp b/src/server/game/Server/Packets/ReferAFriendPackets.cpp index 0f3211936f6..8bc017223f8 100644 --- a/src/server/game/Server/Packets/ReferAFriendPackets.cpp +++ b/src/server/game/Server/Packets/ReferAFriendPackets.cpp @@ -30,6 +30,7 @@ void WorldPackets::RaF::GrantLevel::Read() WorldPacket const* WorldPackets::RaF::ProposeLevelGrant::Write() { _worldPacket << Sender; + return &_worldPacket; } @@ -39,6 +40,8 @@ WorldPacket const* WorldPackets::RaF::ReferAFriendFailure::Write() // Client uses this string only if Reason == ERR_REFER_A_FRIEND_NOT_IN_GROUP || Reason == ERR_REFER_A_FRIEND_SUMMON_OFFLINE_S // but always reads it from packet _worldPacket.WriteBits(Str.length(), 6); + _worldPacket.FlushBits(); _worldPacket.WriteString(Str); + return &_worldPacket; } diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index 01164039420..421a2e9a46c 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -104,9 +104,9 @@ WorldPacket const* WorldPackets::Spells::AuraUpdate::Write() for (auto& aura : Auras) { _worldPacket << aura.Slot; - if (_worldPacket.WriteBit(aura.AuraData.HasValue)) + if (_worldPacket.WriteBit(aura.AuraData.is_initialized())) { - AuraDataInfo const& data = aura.AuraData.Value; + AuraDataInfo const& data = *aura.AuraData; _worldPacket << uint32(data.SpellID); _worldPacket << uint8(data.Flags); _worldPacket << uint32(data.ActiveFlags); @@ -121,18 +121,18 @@ WorldPacket const* WorldPackets::Spells::AuraUpdate::Write() if (!data.EstimatedPoints.empty()) _worldPacket.append(data.EstimatedPoints.data(), data.EstimatedPoints.size()); - _worldPacket.WriteBit(data.CastUnit.HasValue); - _worldPacket.WriteBit(data.Duration.HasValue); - _worldPacket.WriteBit(data.Remaining.HasValue); + _worldPacket.WriteBit(data.CastUnit.is_initialized()); + _worldPacket.WriteBit(data.Duration.is_initialized()); + _worldPacket.WriteBit(data.Remaining.is_initialized()); - if (data.CastUnit.HasValue) - _worldPacket << data.CastUnit.Value; + if (data.CastUnit) + _worldPacket << *data.CastUnit; - if (data.Duration.HasValue) - _worldPacket << uint32(data.Duration.Value); + if (data.Duration) + _worldPacket << uint32(*data.Duration); - if (data.Remaining.HasValue) - _worldPacket << uint32(data.Remaining.Value); + if (data.Remaining) + _worldPacket << uint32(*data.Remaining); } _worldPacket.FlushBits(); @@ -141,12 +141,13 @@ WorldPacket const* WorldPackets::Spells::AuraUpdate::Write() return &_worldPacket; } -ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Spells::TargetLocation& location) +ByteBuffer& operator>>(ByteBuffer& buffer, Optional<WorldPackets::Spells::TargetLocation>& location) { - buffer >> location.Transport; - buffer >> location.Location.m_positionX; - buffer >> location.Location.m_positionY; - buffer >> location.Location.m_positionZ; + location = boost::in_place(); + buffer >> location->Transport; + buffer >> location->Location.m_positionX; + buffer >> location->Location.m_positionY; + buffer >> location->Location.m_positionZ; return buffer; } @@ -155,22 +156,22 @@ ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Spells::SpellTargetData buffer.ResetBitPos(); targetData.Flags = buffer.ReadBits(23); - targetData.SrcLocation.HasValue = buffer.ReadBit(); - targetData.DstLocation.HasValue = buffer.ReadBit(); - targetData.Orientation.HasValue = buffer.ReadBit(); + bool const hasSrcLocation = buffer.ReadBit(); + bool const hasDstLocation = buffer.ReadBit(); + bool const hasOrientation = buffer.ReadBit(); uint32 nameLength = buffer.ReadBits(7); buffer >> targetData.Unit; buffer >> targetData.Item; - if (targetData.SrcLocation.HasValue) - buffer >> targetData.SrcLocation.Value; + if (hasSrcLocation) + buffer >> targetData.SrcLocation; - if (targetData.DstLocation.HasValue) - buffer >> targetData.DstLocation.Value; + if (hasDstLocation) + buffer >> targetData.DstLocation; - if (targetData.Orientation.HasValue) - buffer >> targetData.Orientation.Value; + if (hasOrientation) + targetData.Orientation = buffer.read<float>(); targetData.Name = buffer.ReadString(nameLength); @@ -195,11 +196,15 @@ ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Spells::SpellCastReques buffer.ResetBitPos(); request.SendCastFlags = buffer.ReadBits(5); - request.MoveUpdate.HasValue = buffer.ReadBit(); + bool const hasMoveUpdate = buffer.ReadBit(); request.Weight.resize(buffer.ReadBits(2)); - if (request.MoveUpdate.HasValue) - buffer >> request.MoveUpdate.Value; + if (hasMoveUpdate) + { + MovementInfo movementInfo; + buffer >> movementInfo; + request.MoveUpdate = movementInfo; + } for (WorldPackets::Spells::SpellWeight& weight : request.Weight) { @@ -244,23 +249,23 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation co ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData const& spellTargetData) { data.WriteBits(spellTargetData.Flags, 23); - data.WriteBit(spellTargetData.SrcLocation.HasValue); - data.WriteBit(spellTargetData.DstLocation.HasValue); - data.WriteBit(spellTargetData.Orientation.HasValue); + data.WriteBit(spellTargetData.SrcLocation.is_initialized()); + data.WriteBit(spellTargetData.DstLocation.is_initialized()); + data.WriteBit(spellTargetData.Orientation.is_initialized()); data.WriteBits(spellTargetData.Name.size(), 7); data.FlushBits(); data << spellTargetData.Unit; data << spellTargetData.Item; - if (spellTargetData.SrcLocation.HasValue) - data << spellTargetData.SrcLocation.Value; + if (spellTargetData.SrcLocation) + data << *spellTargetData.SrcLocation; - if (spellTargetData.DstLocation.HasValue) - data << spellTargetData.DstLocation.Value; + if (spellTargetData.DstLocation) + data << *spellTargetData.DstLocation; - if (spellTargetData.Orientation.HasValue) - data << spellTargetData.Orientation.Value; + if (spellTargetData.Orientation) + data << *spellTargetData.Orientation; data.WriteString(spellTargetData.Name); @@ -368,15 +373,15 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastData con data << targetLoc; data.WriteBits(spellCastData.CastFlagsEx, 18); - data.WriteBit(spellCastData.RemainingRunes.HasValue); - data.WriteBit(spellCastData.ProjectileVisual.HasValue); + data.WriteBit(spellCastData.RemainingRunes.is_initialized()); + data.WriteBit(spellCastData.ProjectileVisual.is_initialized()); data.FlushBits(); - if (spellCastData.RemainingRunes.HasValue) - data << spellCastData.RemainingRunes.Value; + if (spellCastData.RemainingRunes) + data << *spellCastData.RemainingRunes; - if (spellCastData.ProjectileVisual.HasValue) - data << spellCastData.ProjectileVisual.Value; + if (spellCastData.ProjectileVisual) + data << *spellCastData.ProjectileVisual; return data; } @@ -392,11 +397,11 @@ WorldPacket const* WorldPackets::Spells::SpellGo::Write() { _worldPacket << Cast; - _worldPacket.WriteBit(LogData.HasValue); + _worldPacket.WriteBit(LogData.is_initialized()); _worldPacket.FlushBits(); - if (LogData.HasValue) - _worldPacket << LogData.Value; + if (LogData) + _worldPacket << *LogData; return &_worldPacket; } @@ -658,15 +663,15 @@ WorldPacket const* WorldPackets::Spells::SpellChannelStart::Write() _worldPacket << CasterGUID; _worldPacket << int32(SpellID); _worldPacket << uint32(ChannelDuration); - _worldPacket.WriteBit(InterruptImmunities.HasValue); - _worldPacket.WriteBit(HealPrediction.HasValue); + _worldPacket.WriteBit(InterruptImmunities.is_initialized()); + _worldPacket.WriteBit(HealPrediction.is_initialized()); _worldPacket.FlushBits(); - if (InterruptImmunities.HasValue) - _worldPacket << InterruptImmunities.Value; + if (InterruptImmunities) + _worldPacket << *InterruptImmunities; - if (HealPrediction.HasValue) - _worldPacket << HealPrediction.Value; + if (HealPrediction) + _worldPacket << *HealPrediction; return &_worldPacket; } @@ -677,3 +682,27 @@ WorldPacket const* WorldPackets::Spells::SpellChannelUpdate::Write() _worldPacket << int32(TimeRemaining); return &_worldPacket; } + +WorldPacket const* WorldPackets::Spells::ResurrectRequest::Write() +{ + _worldPacket << ResurrectOffererGUID; + _worldPacket << ResurrectOffererVirtualRealmAddress; + + _worldPacket << PetNumber; + _worldPacket << SpellID; + + _worldPacket.WriteBits(Name.length(), 6); + _worldPacket.WriteBit(UseTimer); + _worldPacket.WriteBit(Sickness); + + _worldPacket.FlushBits(); + + _worldPacket.WriteString(Name); + + return &_worldPacket; +} + +void WorldPackets::Spells::UnlearnSkill::Read() +{ + _worldPacket >> SkillLine; +} diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index 1f7cdd0b93a..9408ac13398 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -660,6 +660,40 @@ namespace WorldPackets ObjectGuid CasterGUID; int32 TimeRemaining = 0; }; + + class ResurrectRequest final : public ServerPacket + { + public: + ResurrectRequest() : ServerPacket(SMSG_RESURRECT_REQUEST, 16 + 4 + 4 + 4 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid ResurrectOffererGUID; + uint32 ResurrectOffererVirtualRealmAddress = 0; + uint32 PetNumber = 0; + int32 SpellID = 0; + bool UseTimer = false; + bool Sickness = false; + std::string Name; + }; + + class UnlearnSkill final : public ClientPacket + { + public: + UnlearnSkill(WorldPacket&& packet) : ClientPacket(CMSG_UNLEARN_SKILL, std::move(packet)) { } + + void Read() override; + + uint32 SkillLine = 0; + }; + + class SelfRes final : public ClientPacket + { + public: + SelfRes(WorldPacket&& packet) : ClientPacket(CMSG_SELF_RES, std::move(packet)) { } + + void Read() override { } + }; } } diff --git a/src/server/game/Server/Packets/SystemPackets.cpp b/src/server/game/Server/Packets/SystemPackets.cpp index d7a0d5b5fef..b03994aebab 100644 --- a/src/server/game/Server/Packets/SystemPackets.cpp +++ b/src/server/game/Server/Packets/SystemPackets.cpp @@ -31,14 +31,14 @@ WorldPacket const* WorldPackets::System::FeatureSystemStatus::Write() _worldPacket << uint32(TokenRedeemIndex); _worldPacket.WriteBit(VoiceEnabled); - _worldPacket.WriteBit(EuropaTicketSystemStatus.HasValue); + _worldPacket.WriteBit(EuropaTicketSystemStatus.is_initialized()); _worldPacket.WriteBit(ScrollOfResurrectionEnabled); _worldPacket.WriteBit(BpayStoreEnabled); _worldPacket.WriteBit(BpayStoreAvailable); _worldPacket.WriteBit(BpayStoreDisabledByParentalControls); _worldPacket.WriteBit(ItemRestorationButtonEnabled); _worldPacket.WriteBit(BrowserEnabled); - _worldPacket.WriteBit(SessionAlert.HasValue); + _worldPacket.WriteBit(SessionAlert.is_initialized()); _worldPacket.WriteBit(RecruitAFriendSendingEnabled); _worldPacket.WriteBit(CharUndeleteEnabled); _worldPacket.WriteBit(RestrictedAccount); @@ -52,24 +52,24 @@ WorldPacket const* WorldPackets::System::FeatureSystemStatus::Write() _worldPacket.FlushBits(); - if (EuropaTicketSystemStatus.HasValue) + if (EuropaTicketSystemStatus) { - _worldPacket.WriteBit(EuropaTicketSystemStatus.Value.TicketsEnabled); - _worldPacket.WriteBit(EuropaTicketSystemStatus.Value.BugsEnabled); - _worldPacket.WriteBit(EuropaTicketSystemStatus.Value.ComplaintsEnabled); - _worldPacket.WriteBit(EuropaTicketSystemStatus.Value.SuggestionsEnabled); - - _worldPacket << uint32(EuropaTicketSystemStatus.Value.ThrottleState.MaxTries); - _worldPacket << uint32(EuropaTicketSystemStatus.Value.ThrottleState.PerMilliseconds); - _worldPacket << uint32(EuropaTicketSystemStatus.Value.ThrottleState.TryCount); - _worldPacket << uint32(EuropaTicketSystemStatus.Value.ThrottleState.LastResetTimeBeforeNow); + _worldPacket.WriteBit(EuropaTicketSystemStatus->TicketsEnabled); + _worldPacket.WriteBit(EuropaTicketSystemStatus->BugsEnabled); + _worldPacket.WriteBit(EuropaTicketSystemStatus->ComplaintsEnabled); + _worldPacket.WriteBit(EuropaTicketSystemStatus->SuggestionsEnabled); + + _worldPacket << uint32(EuropaTicketSystemStatus->ThrottleState.MaxTries); + _worldPacket << uint32(EuropaTicketSystemStatus->ThrottleState.PerMilliseconds); + _worldPacket << uint32(EuropaTicketSystemStatus->ThrottleState.TryCount); + _worldPacket << uint32(EuropaTicketSystemStatus->ThrottleState.LastResetTimeBeforeNow); } - if (SessionAlert.HasValue) + if (SessionAlert) { - _worldPacket << int32(SessionAlert.Value.Delay); - _worldPacket << int32(SessionAlert.Value.Period); - _worldPacket << int32(SessionAlert.Value.DisplayTime); + _worldPacket << int32(SessionAlert->Delay); + _worldPacket << int32(SessionAlert->Period); + _worldPacket << int32(SessionAlert->DisplayTime); } /*if (bit61) @@ -121,6 +121,8 @@ WorldPacket const* WorldPackets::System::SetTimeZoneInformation::Write() { _worldPacket.WriteBits(ServerTimeTZ.length(), 7); _worldPacket.WriteBits(GameTimeTZ.length(), 7); + _worldPacket.FlushBits(); + _worldPacket.WriteString(ServerTimeTZ); _worldPacket.WriteString(GameTimeTZ); diff --git a/src/server/game/Server/Packets/TicketPackets.cpp b/src/server/game/Server/Packets/TicketPackets.cpp index ba5725bfe23..cdbeea53e32 100644 --- a/src/server/game/Server/Packets/TicketPackets.cpp +++ b/src/server/game/Server/Packets/TicketPackets.cpp @@ -69,27 +69,28 @@ void WorldPackets::Ticket::GMTicketAcknowledgeSurvey::Read() WorldPacket const* WorldPackets::Ticket::GMTicketGetTicketResponse::Write() { _worldPacket << Result; - _worldPacket.WriteBit(Info.HasValue); + _worldPacket.WriteBit(Info.is_initialized()); + _worldPacket.FlushBits(); - if (Info.HasValue) + if (Info) { - _worldPacket << int32(Info.Value.TicketID); - _worldPacket << uint8(Info.Value.Category); - _worldPacket.AppendPackedTime(Info.Value.TicketOpenTime); - _worldPacket.AppendPackedTime(Info.Value.OldestTicketTime); - _worldPacket.AppendPackedTime(Info.Value.UpdateTime); - _worldPacket << uint8(Info.Value.AssignedToGM); - _worldPacket << uint8(Info.Value.OpenedByGM); - _worldPacket << int32(Info.Value.WaitTimeOverrideMinutes); - - _worldPacket.WriteBits(Info.Value.TicketDescription.size(), 11); - _worldPacket.WriteBits(Info.Value.WaitTimeOverrideMessage.size(), 10); - - _worldPacket.WriteString(Info.Value.TicketDescription); - _worldPacket.WriteString(Info.Value.WaitTimeOverrideMessage); + _worldPacket << int32(Info->TicketID); + _worldPacket << uint8(Info->Category); + _worldPacket.AppendPackedTime(Info->TicketOpenTime); + _worldPacket.AppendPackedTime(Info->OldestTicketTime); + _worldPacket.AppendPackedTime(Info->UpdateTime); + _worldPacket << uint8(Info->AssignedToGM); + _worldPacket << uint8(Info->OpenedByGM); + _worldPacket << int32(Info->WaitTimeOverrideMinutes); + + _worldPacket.WriteBits(Info->TicketDescription.size(), 11); + _worldPacket.WriteBits(Info->WaitTimeOverrideMessage.size(), 10); + _worldPacket.FlushBits(); + + _worldPacket.WriteString(Info->TicketDescription); + _worldPacket.WriteString(Info->WaitTimeOverrideMessage); } - _worldPacket.FlushBits(); return &_worldPacket; } @@ -104,8 +105,8 @@ void WorldPackets::Ticket::GMTicketCreate::Read() Description = _worldPacket.ReadString(descLength); _worldPacket.ResetBitPos(); - NeedMoreHelp = _worldPacket.ReadBit(); NeedResponse = _worldPacket.ReadBit(); + NeedMoreHelp = _worldPacket.ReadBit(); _worldPacket >> DataLength; if (DataLength > 0) @@ -227,82 +228,94 @@ ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Ticket::SupportTicketSubm bool hasReportLineIndex = data.ReadBit(); if (hasReportLineIndex) - chatlog.ReportLineIndex.Set(data.read<uint32>()); + chatlog.ReportLineIndex = data.read<uint32>(); data.ResetBitPos(); return data; } -ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketMailInfo& mail) +ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketMailInfo>& mail) { - data >> mail.MailID; + mail = boost::in_place(); + + data >> mail->MailID; uint16 bodyLength = data.ReadBits(13); uint16 subjectLength = data.ReadBits(9); - mail.MailBody = data.ReadString(bodyLength); - mail.MailSubject = data.ReadString(subjectLength); + mail->MailBody = data.ReadString(bodyLength); + mail->MailSubject = data.ReadString(subjectLength); return data; } -ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketCalendarEventInfo& event) +ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketCalendarEventInfo>& event) { - data >> event.EventID; - data >> event.InviteID; + event = boost::in_place(); + + data >> event->EventID; + data >> event->InviteID; uint8 titleLength = data.ReadBits(8); - event.EventTitle = data.ReadString(titleLength); + event->EventTitle = data.ReadString(titleLength); return data; } -ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketPetInfo& pet) +ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketPetInfo>& pet) { - data >> pet.PetID; + pet = boost::in_place(); + + data >> pet->PetID; uint8 nameLength = data.ReadBits(8); - pet.PetName = data.ReadString(nameLength); + pet->PetName = data.ReadString(nameLength); return data; } -ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketGuildInfo& guild) +ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Ticket::SupportTicketSubmitComplaint::SupportTicketGuildInfo>& guild) { - data >> guild.GuildID; + guild = boost::in_place(); + + data >> guild->GuildID; uint8 nameLength = data.ReadBits(8); - guild.GuildName = data.ReadString(nameLength); + guild->GuildName = data.ReadString(nameLength); return data; } -ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Ticket::SupportTicketSubmitComplaint::Struct5E4383& str) +ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Ticket::SupportTicketSubmitComplaint::Struct5E4383>& str) { - data >> str.RideTicket; - data >> str._40; - data >> str._56; - data >> str._72; + str = boost::in_place(); + + data >> str->RideTicket; + data >> str->_40; + data >> str->_56; + data >> str->_72; uint8 _88Length = data.ReadBits(8); uint8 _217Length = data.ReadBits(8); uint8 _1242Length = data.ReadBits(8); - str._88 = data.ReadString(_88Length); - str._217 = data.ReadString(_217Length); - str._1242 = data.ReadString(_1242Length); + str->_88 = data.ReadString(_88Length); + str->_217 = data.ReadString(_217Length); + str->_1242 = data.ReadString(_1242Length); return data; } -ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Ticket::SupportTicketSubmitComplaint::Struct5E3DFB& str) +ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Ticket::SupportTicketSubmitComplaint::Struct5E3DFB>& str) { - data >> str.RideTicket; + str = boost::in_place(); + + data >> str->RideTicket; uint16 _32Length = data.ReadBits(9); data.ResetBitPos(); - str._32 = data.ReadString(_32Length); + str->_32 = data.ReadString(_32Length); return data; } @@ -327,40 +340,22 @@ void WorldPackets::Ticket::SupportTicketSubmitComplaint::Read() Note = _worldPacket.ReadString(noteLength); if (hasMailInfo) - { - _worldPacket >> MailInfo.Value; - MailInfo.HasValue = true; - } + _worldPacket >> MailInfo; if (hasCalendarInfo) - { - _worldPacket >> CalenderInfo.Value; - CalenderInfo.HasValue = true; - } + _worldPacket >> CalenderInfo; if (hasPetInfo) - { - _worldPacket >> PetInfo.Value; - PetInfo.HasValue = true; - } + _worldPacket >> PetInfo; if (hasGuildInfo) - { - _worldPacket >> GuildInfo.Value; - GuildInfo.HasValue = true; - } + _worldPacket >> GuildInfo; if (has5E4383) - { - _worldPacket >> _5E4383.Value; - _5E4383.HasValue = true; - } + _worldPacket >> _5E4383; if (has5E3DFB) - { - _worldPacket >> _5E3DFB.Value; - _5E3DFB.HasValue = true; - } + _worldPacket >> _5E3DFB; } WorldPacket const* WorldPackets::Ticket::ComplaintResult::Write() @@ -370,3 +365,12 @@ WorldPacket const* WorldPackets::Ticket::ComplaintResult::Write() return &_worldPacket; } + +void WorldPackets::Ticket::BugReport::Read() +{ + Type = _worldPacket.ReadBit(); + uint32 diagLen = _worldPacket.ReadBits(12); + uint32 textLen = _worldPacket.ReadBits(10); + DiagInfo = _worldPacket.ReadString(diagLen); + Text = _worldPacket.ReadString(textLen); +} diff --git a/src/server/game/Server/Packets/TicketPackets.h b/src/server/game/Server/Packets/TicketPackets.h index e11adf912ed..2cab591b171 100644 --- a/src/server/game/Server/Packets/TicketPackets.h +++ b/src/server/game/Server/Packets/TicketPackets.h @@ -359,6 +359,18 @@ namespace WorldPackets uint32 ComplaintType = 0; uint8 Result = 0; }; + + class BugReport final : public ClientPacket + { + public: + BugReport(WorldPacket&& packet) : ClientPacket(CMSG_BUG_REPORT, std::move(packet)) { } + + void Read() override; + + uint32 Type = 0; + std::string Text; + std::string DiagInfo; + }; } } diff --git a/src/server/game/Server/Packets/TokenPackets.cpp b/src/server/game/Server/Packets/TokenPackets.cpp index af186a1cf4b..a197eefdec8 100644 --- a/src/server/game/Server/Packets/TokenPackets.cpp +++ b/src/server/game/Server/Packets/TokenPackets.cpp @@ -31,10 +31,25 @@ WorldPacket const* WorldPackets::Token::UpdateListedAuctionableTokensResponse::W { _worldPacket << auctionableTokenAuctionable.UnkInt1; _worldPacket << auctionableTokenAuctionable.UnkInt2; - _worldPacket << auctionableTokenAuctionable.UnkInt3; - _worldPacket << auctionableTokenAuctionable.UnkInt4; - _worldPacket << auctionableTokenAuctionable.UnkInt5; + _worldPacket << auctionableTokenAuctionable.Owner; + _worldPacket << auctionableTokenAuctionable.BuyoutPrice; + _worldPacket << auctionableTokenAuctionable.EndTime; } return &_worldPacket; } + +void WorldPackets::Token::RequestWowTokenMarketPrice::Read() +{ + _worldPacket >> UnkInt; +} + +WorldPacket const* WorldPackets::Token::RequestWowTokenMarketPriceResponse::Write() +{ + _worldPacket << CurrentMarketPrice; + _worldPacket << UnkInt; + _worldPacket << Result; + _worldPacket << UnkInt2; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/TokenPackets.h b/src/server/game/Server/Packets/TokenPackets.h index 126fbe59982..0db58bbac7d 100644 --- a/src/server/game/Server/Packets/TokenPackets.h +++ b/src/server/game/Server/Packets/TokenPackets.h @@ -45,15 +45,38 @@ namespace WorldPackets { uint64 UnkInt1 = 0; uint32 UnkInt2 = 0; - uint32 UnkInt3 = 0; - uint64 UnkInt4 = 0; - uint32 UnkInt5 = 0; + uint32 Owner = 0; + uint64 BuyoutPrice = 0; + uint32 EndTime = 0; }; uint32 UnkInt = 0; // send CMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST uint32 Result = 0; std::vector<AuctionableTokenAuctionable> AuctionableTokenAuctionableList; }; + + class RequestWowTokenMarketPrice final : public ClientPacket + { + public: + RequestWowTokenMarketPrice(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_WOW_TOKEN_MARKET_PRICE, std::move(packet)) { } + + void Read() override; + + uint32 UnkInt = 0; + }; + + class RequestWowTokenMarketPriceResponse final : public ServerPacket + { + public: + RequestWowTokenMarketPriceResponse() : ServerPacket(SMSG_REQUEST_WOW_TOKEN_MARKET_PRICE_RESPONSE, 20) { } + + WorldPacket const* Write() override; + + uint64 CurrentMarketPrice = 0; + uint32 UnkInt = 0; // send CMSG_REQUEST_WOW_TOKEN_MARKET_PRICE + uint32 Result = 0; + uint32 UnkInt2 = 0; + }; } } diff --git a/src/server/game/Server/Packets/TradePackets.cpp b/src/server/game/Server/Packets/TradePackets.cpp index ef5ebb13e20..707d7a814ff 100644 --- a/src/server/game/Server/Packets/TradePackets.cpp +++ b/src/server/game/Server/Packets/TradePackets.cpp @@ -104,8 +104,8 @@ ByteBuffer& operator<<(ByteBuffer& buffer, WorldPackets::Trade::TradeUpdated::Tr buffer << uint32(tradeItem.EntryID); buffer << uint32(tradeItem.StackCount); buffer << tradeItem.GiftCreator; - if (buffer.WriteBit(tradeItem.Unwrapped.HasValue)) - buffer << tradeItem.Unwrapped.Value; + if (buffer.WriteBit(tradeItem.Unwrapped.is_initialized())) + buffer << *tradeItem.Unwrapped; return buffer; } diff --git a/src/server/game/Server/Packets/WhoPackets.cpp b/src/server/game/Server/Packets/WhoPackets.cpp index 7a1704e2567..632aeba0e12 100644 --- a/src/server/game/Server/Packets/WhoPackets.cpp +++ b/src/server/game/Server/Packets/WhoPackets.cpp @@ -25,9 +25,10 @@ void WorldPackets::Who::WhoIsRequest::Read() WorldPacket const* WorldPackets::Who::WhoIsResponse::Write() { _worldPacket.WriteBits(AccountName.length(), 11); - _worldPacket.WriteString(AccountName); _worldPacket.FlushBits(); + _worldPacket.WriteString(AccountName); + return &_worldPacket; } @@ -39,11 +40,13 @@ ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoWord& word) return data; } -ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoRequestServerInfo& serverInfo) +ByteBuffer& operator>>(ByteBuffer& data, Optional<WorldPackets::Who::WhoRequestServerInfo>& serverInfo) { - data >> serverInfo.FactionGroup; - data >> serverInfo.Locale; - data >> serverInfo.RequesterVirtualRealmAddress; + serverInfo = boost::in_place(); + + data >> serverInfo->FactionGroup; + data >> serverInfo->Locale; + data >> serverInfo->RequesterVirtualRealmAddress; return data; } @@ -64,7 +67,8 @@ ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoRequest& request) request.ShowEnemies = data.ReadBit(); request.ShowArenaPlayers = data.ReadBit(); request.ExactName = data.ReadBit(); - request.ServerInfo.HasValue = data.ReadBit(); + + bool const hasWhoRequest = data.ReadBit(); request.Name = data.ReadString(nameLength); request.VirtualRealmName = data.ReadString(virtualRealmNameLength); @@ -73,9 +77,8 @@ ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Who::WhoRequest& request) for (size_t i = 0; i < request.Words.size(); ++i) data >> request.Words[i]; - - if (request.ServerInfo.HasValue) - data >> request.ServerInfo.Value; + if (hasWhoRequest) + data >> request.ServerInfo; return data; } @@ -100,10 +103,10 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Who::WhoEntry const& entr data.WriteBits(entry.GuildName.length(), 7); data.WriteBit(entry.IsGM); - data.WriteString(entry.GuildName); - data.FlushBits(); + data.WriteString(entry.GuildName); + return data; } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index b5ec9e91f82..07632e48b40 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -23,16 +23,18 @@ #include "Packets/BankPackets.h" #include "Packets/BattlegroundPackets.h" #include "Packets/BlackMarketPackets.h" -#include "Packets/CharacterPackets.h" #include "Packets/ChannelPackets.h" +#include "Packets/CharacterPackets.h" #include "Packets/ChatPackets.h" #include "Packets/ClientConfigPackets.h" #include "Packets/CombatPackets.h" #include "Packets/DuelPackets.h" #include "Packets/EquipmentSetPackets.h" #include "Packets/GameObjectPackets.h" +#include "Packets/GarrisonPackets.h" #include "Packets/GuildPackets.h" #include "Packets/InspectPackets.h" +#include "Packets/InstancePackets.h" #include "Packets/ItemPackets.h" #include "Packets/LootPackets.h" #include "Packets/MailPackets.h" @@ -47,9 +49,9 @@ #include "Packets/ScenePackets.h" #include "Packets/SocialPackets.h" #include "Packets/TalentPackets.h" +#include "Packets/TicketPackets.h" #include "Packets/TokenPackets.h" #include "Packets/TradePackets.h" -#include "Packets/TicketPackets.h" #include "Packets/VehiclePackets.h" #include "Packets/VoidStoragePackets.h" #include "Packets/WhoPackets.h" @@ -216,7 +218,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_BLACK_MARKET_BID_ON_ITEM, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_BLACK_MARKET_OPEN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::BlackMarket::BlackMarketOpen, &WorldSession::HandleBlackMarketOpen); DEFINE_HANDLER(CMSG_BLACK_MARKET_REQUEST_ITEMS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_OPCODE_HANDLER_OLD(CMSG_BUG_REPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBugReportOpcode ); + DEFINE_HANDLER(CMSG_BUG_REPORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Ticket::BugReport, &WorldSession::HandleBugReportOpcode); DEFINE_HANDLER(CMSG_BUSY_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::BusyTrade, &WorldSession::HandleBusyTradeOpcode); DEFINE_HANDLER(CMSG_BUY_BACK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::BuyBackItem, &WorldSession::HandleBuybackItem); DEFINE_HANDLER(CMSG_BUY_BANK_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Bank::BuyBankSlot, &WorldSession::HandleBuyBankSlotOpcode); @@ -249,7 +251,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_CANCEL_MOD_SPEED_NO_CONTROL_AURAS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_CANCEL_MOUNT_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::CancelMountAura, &WorldSession::HandleCancelMountAuraOpcode); DEFINE_HANDLER(CMSG_CANCEL_QUEUED_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode); + DEFINE_HANDLER(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::CancelTempEnchantment, &WorldSession::HandleCancelTempEnchantmentOpcode); DEFINE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, WorldPackets::Trade::CancelTrade, &WorldSession::HandleCancelTradeOpcode); DEFINE_HANDLER(CMSG_CAN_DUEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Duel::CanDuel, &WorldSession::HandleCanDuel); DEFINE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Spells::CastSpell, &WorldSession::HandleCastSpellOpcode); @@ -325,7 +327,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_COMMENTATOR_START_WARGAME, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_OPCODE_HANDLER_OLD(CMSG_COMPLAINT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleComplainOpcode ); DEFINE_HANDLER(CMSG_COMPLETE_ALL_READY_SHIPMENTS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_OPCODE_HANDLER_OLD(CMSG_COMPLETE_CINEMATIC, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCompleteCinematic ); + DEFINE_HANDLER(CMSG_COMPLETE_CINEMATIC, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::CompleteCinematic, &WorldSession::HandleCompleteCinematic); DEFINE_HANDLER(CMSG_COMPLETE_MOVIE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_OPCODE_HANDLER_OLD(CMSG_CONFIRM_RESPEC_WIPE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleConfirmRespecWipeOpcode ); DEFINE_HANDLER(CMSG_CONNECT_TO_FAILED, STATUS_NEVER, PROCESS_INPLACE, WorldPacket, &WorldSession::Handle_EarlyProccess); @@ -364,21 +366,21 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_ENGINE_SURVEY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_ENUM_CHARACTERS, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::EnumCharacters, &WorldSession::HandleCharEnumOpcode); DEFINE_HANDLER(CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::EnumCharacters, &WorldSession::HandleCharUndeleteEnumOpcode); - DEFINE_OPCODE_HANDLER_OLD(CMSG_FAR_SIGHT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleFarSightOpcode ); + DEFINE_HANDLER(CMSG_FAR_SIGHT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::FarSight, &WorldSession::HandleFarSightOpcode); DEFINE_HANDLER(CMSG_GAME_OBJ_REPORT_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::GameObject::GameObjReportUse, &WorldSession::HandleGameobjectReportUse); DEFINE_HANDLER(CMSG_GAME_OBJ_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::GameObject::GameObjUse, &WorldSession::HandleGameObjectUseOpcode); DEFINE_HANDLER(CMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_GARRISON_CANCEL_CONSTRUCTION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_GARRISON_CANCEL_CONSTRUCTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonCancelConstruction, &WorldSession::HandleGarrisonCancelConstruction); DEFINE_HANDLER(CMSG_GARRISON_CHECK_UPGRADEABLE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GARRISON_COMPLETE_MISSION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GARRISON_GENERATE_RECRUITS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_GARRISON_GET_BUILDING_LANDMARKS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_GARRISON_GET_BUILDING_LANDMARKS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonGetBuildingLandmarks, &WorldSession::HandleGarrisonGetBuildingLandmarks); DEFINE_HANDLER(CMSG_GARRISON_MISSION_BONUS_ROLL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_GARRISON_PURCHASE_BUILDING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_GARRISON_PURCHASE_BUILDING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonPurchaseBuilding, &WorldSession::HandleGarrisonPurchaseBuilding); DEFINE_HANDLER(CMSG_GARRISON_RECRUIT_FOLLOWER, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GARRISON_REMOVE_FOLLOWER, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData, &WorldSession::HandleGarrisonRequestBlueprintAndSpecializationData); DEFINE_HANDLER(CMSG_GARRISON_REQUEST_LANDING_PAGE_SHIPMENT_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GARRISON_REQUEST_SHIPMENT_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GARRISON_SET_BUILDING_ACTIVE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -389,7 +391,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_GARRISON_SWAP_BUILDINGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GENERATE_RANDOM_CHARACTER_NAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::GenerateRandomCharacterName, &WorldSession::HandleRandomizeCharNameOpcode); DEFINE_HANDLER(CMSG_GET_CHALLENGE_MODE_REWARDS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_GET_GARRISON_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_GET_GARRISON_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GetGarrisonInfo, &WorldSession::HandleGetGarrisonInfo); DEFINE_HANDLER(CMSG_GET_ITEM_PURCHASE_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::GetItemPurchaseData, &WorldSession::HandleGetItemPurchaseData); DEFINE_OPCODE_HANDLER_OLD(CMSG_GET_MIRROR_IMAGE_DATA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMirrorImageDataRequest ); DEFINE_HANDLER(CMSG_GET_PVP_OPTIONS_ENABLED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Battleground::GetPVPOptionsEnabled, &WorldSession::HandleGetPVPOptionsEnabled); @@ -445,7 +447,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_GUILD_QUERY_NEWS, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Guild::GuildQueryNews, &WorldSession::HandleGuildQueryNews); DEFINE_HANDLER(CMSG_GUILD_QUERY_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_GUILD_REPLACE_GUILD_MASTER, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_OPCODE_HANDLER_OLD(CMSG_GUILD_SET_ACHIEVEMENT_TRACKING, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildSetAchievementTracking); + DEFINE_HANDLER(CMSG_GUILD_SET_ACHIEVEMENT_TRACKING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildSetAchievementTracking, &WorldSession::HandleGuildSetAchievementTracking); DEFINE_HANDLER(CMSG_GUILD_SET_FOCUSED_ACHIEVEMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Achievement::GuildSetFocusedAchievement, &WorldSession::HandleGuildSetFocusedAchievement); DEFINE_HANDLER(CMSG_GUILD_SET_GUILD_MASTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildSetGuildMaster, &WorldSession::HandleGuildSetGuildMaster); DEFINE_HANDLER(CMSG_GUILD_SET_MEMBER_NOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildSetMemberNote, &WorldSession::HandleGuildSetMemberNote); @@ -462,7 +464,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_INSPECT_PVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Inspect::InspectPVPRequest, &WorldSession::HandleInspectPVP); DEFINE_OPCODE_HANDLER_OLD(CMSG_INSTANCE_LOCK_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceLockResponse); DEFINE_OPCODE_HANDLER_OLD(CMSG_ITEM_PURCHASE_REFUND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefund ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_ITEM_TEXT_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleItemTextQuery ); + DEFINE_HANDLER(CMSG_ITEM_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Query::ItemTextQuery, &WorldSession::HandleItemTextQuery); DEFINE_HANDLER(CMSG_JOIN_PET_BATTLE_QUEUE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_JOIN_RATED_BATTLEGROUND, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_KEEP_ALIVE, STATUS_NEVER, PROCESS_INPLACE, WorldPacket, &WorldSession::Handle_EarlyProccess); @@ -579,7 +581,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_MOVE_TOGGLE_COLLISION_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_MOVE_WATER_WALK_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Movement::MovementAckMessage, &WorldSession::HandleMovementAckMessage); DEFINE_HANDLER(CMSG_NEUTRAL_PLAYER_SELECT_FACTION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_OPCODE_HANDLER_OLD(CMSG_NEXT_CINEMATIC_CAMERA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleNextCinematicCamera ); + DEFINE_HANDLER(CMSG_NEXT_CINEMATIC_CAMERA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::NextCinematicCamera, &WorldSession::HandleNextCinematicCamera); DEFINE_HANDLER(CMSG_OBJECT_UPDATE_FAILED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::ObjectUpdateFailed, &WorldSession::HandleObjectUpdateFailedOpcode); DEFINE_HANDLER(CMSG_OBJECT_UPDATE_RESCUED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Misc::ObjectUpdateRescued, &WorldSession::HandleObjectUpdateRescuedOpcode); DEFINE_HANDLER(CMSG_OFFER_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::OfferPetition, &WorldSession::HandleOfferPetition); @@ -631,7 +633,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_QUERY_NPC_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Query::QueryNPCText, &WorldSession::HandleNpcTextQueryOpcode); DEFINE_HANDLER(CMSG_QUERY_PAGE_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Query::QueryPageText, &WorldSession::HandleQueryPageText); DEFINE_HANDLER(CMSG_QUERY_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::QueryPetition, &WorldSession::HandleQueryPetition); - DEFINE_OPCODE_HANDLER_OLD(CMSG_QUERY_PET_NAME, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetNameQuery ); + DEFINE_HANDLER(CMSG_QUERY_PET_NAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Query::QueryPetName, &WorldSession::HandleQueryPetName); DEFINE_HANDLER(CMSG_QUERY_PLAYER_NAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Query::QueryPlayerName, &WorldSession::HandleNameQueryOpcode); DEFINE_HANDLER(CMSG_QUERY_QUEST_COMPLETION_NPCS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Query::QueryQuestCompletionNPCs, &WorldSession::HandleQueryQuestCompletionNPCs); DEFINE_HANDLER(CMSG_QUERY_QUEST_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Quest::QueryQuestInfo, &WorldSession::HandleQuestQueryOpcode); @@ -687,7 +689,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_NEXT_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::RequestVehicleNextSeat, &WorldSession::HandleRequestVehicleNextSeat); DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_PREV_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::RequestVehiclePrevSeat, &WorldSession::HandleRequestVehiclePrevSeat); DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_SWITCH_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::RequestVehicleSwitchSeat, &WorldSession::HandleRequestVehicleSwitchSeat); - DEFINE_HANDLER(CMSG_REQUEST_WOW_TOKEN_MARKET_PRICE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_REQUEST_WOW_TOKEN_MARKET_PRICE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Token::RequestWowTokenMarketPrice, &WorldSession::HandleRequestWowTokenMarketPrice); DEFINE_HANDLER(CMSG_RESET_CHALLENGE_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_OPCODE_HANDLER_OLD(CMSG_RESET_INSTANCES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleResetInstancesOpcode ); DEFINE_HANDLER(CMSG_RESURRECT_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::ResurrectResponse, &WorldSession::HandleResurrectResponse); @@ -699,7 +701,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_CANCELED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Scenes::ScenePlaybackCanceled, &WorldSession::HandleScenePlaybackCanceled); DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_COMPLETE, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Scenes::ScenePlaybackComplete, &WorldSession::HandleScenePlaybackComplete); DEFINE_HANDLER(CMSG_SCENE_TRIGGER_EVENT, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Scenes::SceneTriggerEvent, &WorldSession::HandleSceneTriggerEvent); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SELF_RES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSelfResOpcode ); + DEFINE_HANDLER(CMSG_SELF_RES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::SelfRes, &WorldSession::HandleSelfResOpcode); DEFINE_HANDLER(CMSG_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SellItem, &WorldSession::HandleSellItemOpcode); DEFINE_HANDLER(CMSG_SELL_WOW_TOKEN_CONFIRM, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_SELL_WOW_TOKEN_START, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -723,9 +725,9 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_SET_DIFFICULTY_ID, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_SET_DUNGEON_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetDungeonDifficulty, &WorldSession::HandleSetDungeonDifficultyOpcode); DEFINE_HANDLER(CMSG_SET_EVERYONE_IS_ASSISTANT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_FACTION_AT_WAR, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionAtWar ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_FACTION_INACTIVE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionInactiveOpcode ); - DEFINE_HANDLER(CMSG_SET_FACTION_NOT_AT_WAR, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_SET_FACTION_AT_WAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionAtWar, &WorldSession::HandleSetFactionAtWar); + DEFINE_HANDLER(CMSG_SET_FACTION_INACTIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionInactive, &WorldSession::HandleSetFactionInactiveOpcode); + DEFINE_HANDLER(CMSG_SET_FACTION_NOT_AT_WAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionNotAtWar, &WorldSession::HandleSetFactionNotAtWar); DEFINE_HANDLER(CMSG_SET_INSERT_ITEMS_LEFT_TO_RIGHT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_SET_LFG_BONUS_FACTION_ID, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_LOOT_METHOD, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMethodOpcode ); @@ -740,7 +742,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ROLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupSetRolesOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SAVED_INSTANCE_EXTEND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend ); DEFINE_HANDLER(CMSG_SET_SELECTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetSelection, &WorldSession::HandleSetSelectionOpcode); - DEFINE_HANDLER(CMSG_SET_SHEATHED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Combat::SetSheathed, &WorldSession::HandleSetSheathedOpcode); + DEFINE_HANDLER(CMSG_SET_SHEATHED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Combat::SetSheathed, &WorldSession::HandleSetSheathedOpcode); DEFINE_HANDLER(CMSG_SET_SORT_BAGS_RIGHT_TO_LEFT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_SET_SPECIALIZATION, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Talent::SetSpecialization, &WorldSession::HandleSetSpecializationOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TAXI_BENCHMARK_MODE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode ); @@ -749,7 +751,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_SET_TRADE_GOLD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::SetTradeGold, &WorldSession::HandleSetTradeGoldOpcode); DEFINE_HANDLER(CMSG_SET_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::SetTradeItem, &WorldSession::HandleSetTradeItemOpcode); DEFINE_HANDLER(CMSG_SET_USING_PARTY_GARRISON, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_WATCHED_FACTION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetWatchedFactionOpcode ); + DEFINE_HANDLER(CMSG_SET_WATCHED_FACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetWatchedFaction, &WorldSession::HandleSetWatchedFactionOpcode); DEFINE_HANDLER(CMSG_SHOWING_CLOAK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::ShowingCloak, &WorldSession::HandleShowingCloakOpcode); DEFINE_HANDLER(CMSG_SHOWING_HELM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::ShowingHelm, &WorldSession::HandleShowingHelmOpcode); DEFINE_HANDLER(CMSG_SHOW_TRADE_SKILL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -760,7 +762,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_SORT_BANK_BAGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_SORT_REAGENT_BANK_BAGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_OPCODE_HANDLER_OLD(CMSG_SPELL_CLICK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSpellClick ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SPIRIT_HEALER_ACTIVATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSpiritHealerActivateOpcode); + DEFINE_HANDLER(CMSG_SPIRIT_HEALER_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::SpiritHealerActivate, &WorldSession::HandleSpiritHealerActivate); DEFINE_HANDLER(CMSG_SPLIT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SplitItem, &WorldSession::HandleSplitItemOpcode); DEFINE_HANDLER(CMSG_STAND_STATE_CHANGE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::StandStateChange, &WorldSession::HandleStandStateChangeOpcode); DEFINE_HANDLER(CMSG_START_SPECTATOR_WAR_GAME, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -789,7 +791,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_TOGGLE_PVP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTogglePvP ); DEFINE_OPCODE_HANDLER_OLD(CMSG_TOTEM_DESTROYED, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTotemDestroyed ); DEFINE_HANDLER(CMSG_TOY_SET_FAVORITE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_OPCODE_HANDLER_OLD(CMSG_TRAINER_BUY_SPELL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerBuySpellOpcode ); + DEFINE_HANDLER(CMSG_TRAINER_BUY_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::TrainerBuySpell, &WorldSession::HandleTrainerBuySpellOpcode); DEFINE_HANDLER(CMSG_TRAINER_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleTrainerListOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_TRANSMOGRIFY_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogrifyItems ); DEFINE_HANDLER(CMSG_TURN_IN_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::TurnInPetition, &WorldSession::HandleTurnInPetition); @@ -801,7 +803,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_UI_TIME_REQUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Misc::UITimeRequest, &WorldSession::HandleUITimeRequest); DEFINE_HANDLER(CMSG_UNACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::UnacceptTrade, &WorldSession::HandleUnacceptTradeOpcode); DEFINE_HANDLER(CMSG_UNDELETE_CHARACTER, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::UndeleteCharacter, &WorldSession::HandleCharUndeleteOpcode); - DEFINE_OPCODE_HANDLER_OLD(CMSG_UNLEARN_SKILL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUnlearnSkillOpcode ); + DEFINE_HANDLER(CMSG_UNLEARN_SKILL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::UnlearnSkill, &WorldSession::HandleUnlearnSkillOpcode); DEFINE_HANDLER(CMSG_UNLEARN_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_UNLOCK_VOID_STORAGE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::VoidStorage::UnlockVoidStorage, &WorldSession::HandleVoidStorageUnlock); DEFINE_HANDLER(CMSG_UPDATE_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::ClientConfig::UserClientUpdateAccountData, &WorldSession::HandleUpdateAccountData); @@ -827,7 +829,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_WHO_IS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Who::WhoIsRequest, &WorldSession::HandleWhoIsOpcode); DEFINE_HANDLER(CMSG_WORLD_PORT_RESPONSE, STATUS_TRANSFER, PROCESS_THREADUNSAFE, WorldPackets::Movement::WorldPortResponse, &WorldSession::HandleMoveWorldportAckOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_WORLD_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_WRAP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode ); + DEFINE_HANDLER(CMSG_WRAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::WrapItem, &WorldSession::HandleWrapItem); #undef DEFINE_OPCODE_HANDLER_OLD #undef DEFINE_HANDLER @@ -969,11 +971,11 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CALENDAR_SEND_EVENT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CALENDAR_SEND_NUM_PENDING, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAMERA_SHAKE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_AUTO_REPEAT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_AUTO_REPEAT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_COMBAT, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_ORPHAN_SPELL_VISUAL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_ORPHAN_SPELL_VISUAL, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_SCENE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_SPELL_VISUAL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_SPELL_VISUAL, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_SPELL_VISUAL_KIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAN_DUEL_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAST_FAILED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1008,10 +1010,10 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_IS_DOWN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_NOT_IN_PARTY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_PLAYER_AMBIGUOUS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_PLAYER_NOTFOUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_PLAYER_NOTFOUND, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_RECONNECT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_RESTRICTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_SERVER_MESSAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_SERVER_MESSAGE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHEAT_IGNORE_DIMISHING_RETURNS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHECK_WARGAME_ENTRY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHUNKED_PACKET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1021,13 +1023,13 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_COOLDOWNS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_LOSS_OF_CONTROL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_SPELL_CHARGES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_TARGET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_TARGET, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COIN_REMOVED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMBAT_EVENT_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMMENTATOR_MAP_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMMENTATOR_PLAYER_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMMENTATOR_STATE_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMPLAINT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMPLAINT_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMPLETE_SHIPMENT_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMPRESSED_PACKET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONNECT_TO, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1058,7 +1060,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DIFFERENT_INSTANCE_FROM_PARTY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISENCHANT_CREDIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISMOUNT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISMOUNT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISMOUNT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPEL_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPLAY_GAME_ERROR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1107,51 +1109,51 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_SPEED_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_TIME_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_TIME_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_ACTIVATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_LANDMARKS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_REMOVED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_SET_ACTIVE_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_COMPLETE_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_CREATE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_DELETE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL2, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_XP, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_IS_UPGRADEABLE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LANDINGPAGE_SHIPMENTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LEARN_BLUEPRINT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LEARN_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LIST_FOLLOWERS_CHEAT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LIST_MISSIONS_CHEAT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_MISSION_BONUS_ROLL_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_NUM_FOLLOWER_ACTIVATIONS_REMAINING, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_ARCHITECT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_MISSION_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_TRADESKILL_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLACE_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_PLACED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_REMOVED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_LAST_USED_TIME, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_USED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUITMENT_FOLLOWERS_GENERATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUIT_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOTE_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOVE_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_START_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_UNLEARN_BLUEPRINT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_UPGRADE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_ACTIVATED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_LANDMARKS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_REMOVED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_SET_ACTIVE_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_COMPLETE_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_CREATE_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_DELETE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL2, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_XP, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_IS_UPGRADEABLE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LANDINGPAGE_SHIPMENTS, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LEARN_BLUEPRINT_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LEARN_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LIST_FOLLOWERS_CHEAT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LIST_MISSIONS_CHEAT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_MISSION_BONUS_ROLL_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_NUM_FOLLOWER_ACTIVATIONS_REMAINING, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_ARCHITECT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_MISSION_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_TRADESKILL_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLACE_BUILDING_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_PLACED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_REMOVED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_LAST_USED_TIME, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_USED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUITMENT_FOLLOWERS_GENERATED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUIT_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOTE_INFO, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOVE_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_START_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_UNLEARN_BLUEPRINT_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_UPGRADE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GENERATE_RANDOM_CHARACTER_NAME_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_ACCOUNT_CHARACTER_LIST_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_DISPLAYED_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_GARRISON_INFO_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_SHIPMENTS_OF_TYPE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_SHIPMENT_INFO_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_DISPLAYED_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_GARRISON_INFO_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_SHIPMENTS_OF_TYPE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_SHIPMENT_INFO_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_PLAYER_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_REQUEST_PLAYER_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_TICKET_CASE_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1504,11 +1506,11 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_GAME_OBJECT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_GARRISON_CREATURE_NAME_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_GUILD_INFO_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_ITEM_TEXT_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_ITEM_TEXT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_NPC_TEXT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_PAGE_TEXT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_PETITION_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_PET_NAME_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_PET_NAME_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_PLAYER_NAME_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_QUEST_INFO_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_TIME_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1558,6 +1560,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_REPORT_PVP_PLAYER_AFK_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REQUEST_CEMETERY_LIST_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REQUEST_PVP_REWARDS_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_REQUEST_WOW_TOKEN_MARKET_PRICE_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESEARCH_COMPLETE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_COMPRESSION_CONTEXT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_FAILED_NOTIFY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1568,7 +1571,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_CAST_BAR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_COMMS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_TOKEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHANGED_INFORM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHOSEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1608,9 +1611,9 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_DF_FAST_LAUNCH_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_DUNGEON_DIFFICULTY, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_AT_WAR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_NOT_VISIBLE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_NOT_VISIBLE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_STANDING, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_VISIBLE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_VISIBLE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FLAT_SPELL_MODIFIER, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FORCED_REACTIONS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_ITEM_PURCHASE_DATA, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1629,7 +1632,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_TIME_ZONE_INFORMATION, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_VEHICLE_REC_ID, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_BANK, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_MAILBOX, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_MAILBOX, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_NEUTRAL_PLAYER_FACTION_SELECT_UI, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_TAXI_NODES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_TRADE_SKILL_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1643,11 +1646,11 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DELAYED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DISPELL_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_ENERGIZE_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_EXECUTE_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_EXECUTE_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_HEAL_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_HEAL_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_INSTAKILL_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_INTERRUPT_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_MISS_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1657,7 +1660,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_PERIODIC_AURA_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_STAND_STATE_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_START_ELAPSED_TIMER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_START_ELAPSED_TIMERS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1683,15 +1686,15 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_THREAT_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TIME_ADJUSTMENT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TIME_SYNC_REQUEST, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_TITLE_EARNED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_TITLE_LOST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_TITLE_EARNED, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_TITLE_LOST, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TOKEN_UNK1, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TOTEM_CREATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TOTEM_MOVED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_STATUS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_BUY_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_BUY_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_ABORTED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_PENDING, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_CINEMATIC, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1708,8 +1711,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_CHARACTER_FLAGS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_EXPANSION_LEVEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_OWNERSHIP, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_OWNERSHIP, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_OBJECT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_TALENT_DATA, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_TASK_PROGRESS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index ab59edf68c0..a17fe288ce6 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -1451,6 +1451,7 @@ enum OpcodeServer : uint32 SMSG_REPORT_PVP_PLAYER_AFK_RESULT = 0x12B2, SMSG_REQUEST_CEMETERY_LIST_RESPONSE = 0x1398, SMSG_REQUEST_PVP_REWARDS_RESPONSE = 0x0218, + SMSG_REQUEST_WOW_TOKEN_MARKET_PRICE_RESPONSE = 0x1215, SMSG_RESEARCH_COMPLETE = 0x1335, SMSG_RESET_COMPRESSION_CONTEXT = 0x0059, SMSG_RESET_FAILED_NOTIFY = 0x040D, @@ -1684,11 +1685,7 @@ enum PacketProcessing class WorldPacket; class WorldSession; -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif class OpcodeHandler { @@ -1765,11 +1762,7 @@ class OpcodeTable extern OpcodeTable opcodeTable; -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif void InitOpcodes(); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index e9fb8285d5a..fa557616450 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -322,6 +322,10 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (IsConnectionIdle()) m_Socket[CONNECTION_TYPE_REALM]->CloseSocket(); + if (updater.ProcessUnsafe()) + while (_player && _player->IsBeingTeleportedSeamlessly()) + HandleMoveWorldportAckOpcode(); + ///- Retrieve packets from the receive queue and call the appropriate handlers /// not process packets if socket already closed WorldPacket* packet = NULL; @@ -453,7 +457,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) //check if we are safe to proceed with logout //logout procedure should happen only in World::UpdateSessions() method!!! - if (updater.ProcessLogout()) + if (updater.ProcessUnsafe()) { time_t currTime = time(NULL); ///- If necessary, log the player out @@ -911,14 +915,11 @@ bool WorldSession::IsAddonRegistered(const std::string& prefix) const void WorldSession::HandleUnregisterAddonPrefixesOpcode(WorldPacket& /*recvPacket*/) // empty packet { - _registeredAddonPrefixes.clear(); } void WorldSession::HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_ADDON_REGISTERED_PREFIXES"); - // This is always sent after CMSG_UNREGISTER_ALL_ADDON_PREFIXES uint32 count = recvPacket.ReadBits(25); @@ -1368,6 +1369,9 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co case CMSG_GM_TICKET_UPDATE_TEXT: // 0 15 1 async db query case CMSG_GM_TICKET_DELETE_TICKET: // 1 25 1 async db query case CMSG_GM_TICKET_RESPONSE_RESOLVE: // 1 25 1 async db query + case CMSG_SUPPORT_TICKET_SUBMIT_BUG: // not profiled 1 async db query + case CMSG_SUPPORT_TICKET_SUBMIT_SUGGESTION: // not profiled 1 async db query + case CMSG_SUPPORT_TICKET_SUBMIT_COMPLAINT: // not profiled 1 async db query case CMSG_CALENDAR_UPDATE_EVENT: // not profiled case CMSG_CALENDAR_REMOVE_EVENT: // not profiled case CMSG_CALENDAR_COPY_EVENT: // not profiled diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 2317605bf54..bd4fefdd665 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -152,6 +152,10 @@ namespace WorldPackets class ShowingCloak; class ShowingHelm; class SetTitle; + class SetFactionAtWar; + class SetFactionNotAtWar; + class SetFactionInactive; + class SetWatchedFaction; enum class LoginFailureReason : uint8; } @@ -210,6 +214,15 @@ namespace WorldPackets class GameObjUse; } + namespace Garrison + { + class GetGarrisonInfo; + class GarrisonPurchaseBuilding; + class GarrisonCancelConstruction; + class GarrisonRequestBlueprintAndSpecializationData; + class GarrisonGetBuildingLandmarks; + } + namespace Guild { class QueryGuildInfo; @@ -251,6 +264,7 @@ namespace WorldPackets class GuildSetGuildMaster; class GuildChallengeUpdateRequest; class SaveGuildEmblem; + class GuildSetAchievementTracking; } namespace Inspect @@ -276,6 +290,8 @@ namespace WorldPackets class SplitItem; class SwapInvItem; class SwapItem; + class WrapItem; + class CancelTempEnchantment; } namespace Loot @@ -319,6 +335,9 @@ namespace WorldPackets class RandomRollClient; class ObjectUpdateFailed; class ObjectUpdateRescued; + class CompleteCinematic; + class NextCinematicCamera; + class FarSight; } namespace Movement @@ -337,6 +356,8 @@ namespace WorldPackets { class Hello; class GossipSelectOption; + class SpiritHealerActivate; + class TrainerBuySpell; } namespace Petition @@ -363,8 +384,10 @@ namespace WorldPackets class QueryCorpseLocationFromClient; class QueryCorpseTransport; class QueryTime; + class QueryPetName; class QuestPOIQuery; class QueryQuestCompletionNPCs; + class ItemTextQuery; } namespace Quest @@ -422,6 +445,8 @@ namespace WorldPackets class UseItem; class OpenItem; class SetActionButton; + class UnlearnSkill; + class SelfRes; } namespace Talent @@ -444,11 +469,13 @@ namespace WorldPackets class SupportTicketSubmitBug; class SupportTicketSubmitSuggestion; class SupportTicketSubmitComplaint; + class BugReport; } namespace Token { class UpdateListedAuctionableTokens; + class RequestWowTokenMarketPrice; } namespace Trade @@ -621,8 +648,8 @@ public: explicit PacketFilter(WorldSession* pSession) : m_pSession(pSession) { } virtual ~PacketFilter() { } - virtual bool Process(WorldPacket* /*packet*/) { return true; } - virtual bool ProcessLogout() const { return true; } + virtual bool Process(WorldPacket* /*packet*/) = 0; + virtual bool ProcessUnsafe() const { return false; } protected: WorldSession* const m_pSession; @@ -639,9 +666,7 @@ public: explicit MapSessionFilter(WorldSession* pSession) : PacketFilter(pSession) { } ~MapSessionFilter() { } - virtual bool Process(WorldPacket* packet) override; - //in Map::Update() we do not process player logout! - virtual bool ProcessLogout() const override { return false; } + bool Process(WorldPacket* packet) override; }; //class used to filer only thread-unsafe packets from queue @@ -652,7 +677,8 @@ public: explicit WorldSessionFilter(WorldSession* pSession) : PacketFilter(pSession) { } ~WorldSessionFilter() { } - virtual bool Process(WorldPacket* packet) override; + bool Process(WorldPacket* packet) override; + bool ProcessUnsafe() const override { return true; } }; struct PacketCounter @@ -766,7 +792,7 @@ class WorldSession void HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlags, SpellCastTargets& targets); // Pet - void SendPetNameQuery(ObjectGuid guid, uint32 petnumber); + void SendQueryPetNameResponse(ObjectGuid guid); void SendStablePet(ObjectGuid guid); void SendStablePetCallback(PreparedQueryResult result, ObjectGuid guid); void SendPetStableResult(uint8 guid); @@ -966,6 +992,7 @@ class WorldSession void HandleSupportTicketSubmitBug(WorldPackets::Ticket::SupportTicketSubmitBug& packet); void HandleSupportTicketSubmitSuggestion(WorldPackets::Ticket::SupportTicketSubmitSuggestion& packet); void HandleSupportTicketSubmitComplaint(WorldPackets::Ticket::SupportTicketSubmitComplaint& packet); + void HandleBugReportOpcode(WorldPackets::Ticket::BugReport& bugReport); void HandleTogglePvP(WorldPacket& recvPacket); @@ -983,14 +1010,13 @@ class WorldSession void HandleDelIgnoreOpcode(WorldPackets::Social::DelIgnore& packet); void HandleSetContactNotesOpcode(WorldPackets::Social::SetContactNotes& packet); - void HandleBugReportOpcode(WorldPacket& recvPacket); - void HandleAreaTriggerOpcode(WorldPackets::Misc::AreaTrigger& packet); - void HandleSetFactionAtWar(WorldPacket& recvData); + void HandleSetFactionAtWar(WorldPackets::Character::SetFactionAtWar& packet); + void HandleSetFactionNotAtWar(WorldPackets::Character::SetFactionNotAtWar& packet); void HandleSetFactionCheat(WorldPacket& recvData); - void HandleSetWatchedFactionOpcode(WorldPacket& recvData); - void HandleSetFactionInactiveOpcode(WorldPacket& recvData); + void HandleSetWatchedFactionOpcode(WorldPackets::Character::SetWatchedFaction& packet); + void HandleSetFactionInactiveOpcode(WorldPackets::Character::SetFactionInactive& packet); void HandleRequestForcedReactionsOpcode(WorldPackets::Reputation::RequestForcedReactions& requestForcedReactions); void HandleUpdateAccountData(WorldPackets::ClientConfig::UserClientUpdateAccountData& packet); @@ -1070,7 +1096,7 @@ class WorldSession void HandleGuildAssignRank(WorldPackets::Guild::GuildAssignMemberRank& packet); void HandleGuildLeave(WorldPackets::Guild::GuildLeave& leave); void HandleGuildDelete(WorldPackets::Guild::GuildDelete& packet); - void HandleGuildSetAchievementTracking(WorldPacket& recvPacket); + void HandleGuildSetAchievementTracking(WorldPackets::Guild::GuildSetAchievementTracking& packet); void HandleGuildSetGuildMaster(WorldPackets::Guild::GuildSetGuildMaster& packet); void HandleGuildUpdateMotdText(WorldPackets::Guild::GuildUpdateMotdText& packet); void HandleGuildNewsUpdateSticky(WorldPackets::Guild::GuildNewsUpdateSticky& packet); @@ -1105,11 +1131,11 @@ class WorldSession void HandleTabardVendorActivateOpcode(WorldPackets::NPC::Hello& packet); void HandleBankerActivateOpcode(WorldPackets::NPC::Hello& packet); void HandleTrainerListOpcode(WorldPackets::NPC::Hello& packet); - void HandleTrainerBuySpellOpcode(WorldPacket& recvPacket); + void HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpell& packet); void HandlePetitionShowList(WorldPackets::Petition::PetitionShowList& packet); void HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet); void HandleGossipSelectOptionOpcode(WorldPackets::NPC::GossipSelectOption& packet); - void HandleSpiritHealerActivateOpcode(WorldPacket& recvPacket); + void HandleSpiritHealerActivate(WorldPackets::NPC::SpiritHealerActivate& packet); void HandleNpcTextQueryOpcode(WorldPackets::Query::QueryNPCText& packet); void HandleBinderActivateOpcode(WorldPackets::NPC::Hello& packet); void HandleListStabledPetsOpcode(WorldPacket& recvPacket); @@ -1121,7 +1147,7 @@ class WorldSession void HandleStableRevivePet(WorldPacket& recvPacket); void HandleStableSwapPet(WorldPacket& recvPacket); void HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId); - void SendTrainerBuyFailed(ObjectGuid guid, uint32 spellId, uint32 reason); + void SendTrainerBuyFailed(ObjectGuid trainerGUID, uint32 spellID, int32 trainerFailedReason); void HandleCanDuel(WorldPackets::Duel::CanDuel& packet); void HandleDuelResponseOpcode(WorldPackets::Duel::DuelResponse& duelResponse); @@ -1165,7 +1191,7 @@ class WorldSession void HandleMailMarkAsRead(WorldPackets::Mail::MailMarkAsRead& packet); void HandleMailReturnToSender(WorldPackets::Mail::MailReturnToSender& packet); void HandleMailDelete(WorldPackets::Mail::MailDelete& packet); - void HandleItemTextQuery(WorldPacket& recvData); + void HandleItemTextQuery(WorldPackets::Query::ItemTextQuery& itemTextQuery); void HandleMailCreateTextItem(WorldPackets::Mail::MailCreateTextItem& packet); void HandleQueryNextMailTime(WorldPackets::Mail::MailQueryNextMailTime& packet); void HandleCancelChanneling(WorldPacket& recvData); @@ -1176,7 +1202,6 @@ class WorldSession void HandleDestroyItemOpcode(WorldPackets::Item::DestroyItem& destroyItem); void HandleAutoEquipItemOpcode(WorldPackets::Item::AutoEquipItem& autoEquipItem); void HandleSellItemOpcode(WorldPackets::Item::SellItem& packet); - void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket); void HandleBuyItemOpcode(WorldPackets::Item::BuyItem& packet); void HandleListInventoryOpcode(WorldPackets::NPC::Hello& packet); void HandleAutoStoreBagItemOpcode(WorldPackets::Item::AutoStoreBagItem& packet); @@ -1184,7 +1209,7 @@ class WorldSession void HandleAutoEquipItemSlotOpcode(WorldPackets::Item::AutoEquipItemSlot& autoEquipItemSlot); void HandleSwapItem(WorldPackets::Item::SwapItem& swapItem); void HandleBuybackItem(WorldPackets::Item::BuyBackItem& packet); - void HandleWrapItemOpcode(WorldPacket& recvPacket); + void HandleWrapItem(WorldPackets::Item::WrapItem& packet); void HandleAttackSwingOpcode(WorldPackets::Combat::AttackSwing& packet); void HandleAttackStopOpcode(WorldPackets::Combat::AttackStop& packet); @@ -1201,7 +1226,7 @@ class WorldSession void HandleLearnTalentsOpcode(WorldPackets::Talent::LearnTalents& packet); void HandleConfirmRespecWipeOpcode(WorldPacket& recvPacket); - void HandleUnlearnSkillOpcode(WorldPacket& recvPacket); + void HandleUnlearnSkillOpcode(WorldPackets::Spells::UnlearnSkill& packet); void HandleSetSpecializationOpcode(WorldPackets::Talent::SetSpecialization& packet); void HandleQuestgiverStatusQueryOpcode(WorldPackets::Quest::QuestGiverStatusQuery& packet); @@ -1232,7 +1257,7 @@ class WorldSession void HandleChatMessageAFKOpcode(WorldPackets::Chat::ChatMessageAFK& chatMessageAFK); void HandleChatMessageDNDOpcode(WorldPackets::Chat::ChatMessageDND& chatMessageDND); void HandleChatMessageEmoteOpcode(WorldPackets::Chat::ChatMessageEmote& chatMessageEmote); - void SendPlayerNotFoundNotice(std::string const& name); + void SendChatPlayerNotfoundNotice(std::string const& name); void SendPlayerAmbiguousNotice(std::string const& name); void SendChatRestrictedNotice(ChatRestrictionType restriction); void HandleTextEmoteOpcode(WorldPackets::Chat::CTextEmote& packet); @@ -1259,8 +1284,8 @@ class WorldSession void HandleVoiceSessionEnableOpcode(WorldPacket& recvData); void HandleSetActiveVoiceChannel(WorldPacket& recvData); - void HandleCompleteCinematic(WorldPacket& recvPacket); - void HandleNextCinematicCamera(WorldPacket& recvPacket); + void HandleCompleteCinematic(WorldPackets::Misc::CompleteCinematic& packet); + void HandleNextCinematicCamera(WorldPackets::Misc::NextCinematicCamera& packet); void HandleQueryPageText(WorldPackets::Query::QueryPageText& packet); @@ -1270,7 +1295,7 @@ class WorldSession void HandlePetAction(WorldPacket& recvData); void HandlePetStopAttack(WorldPacket& recvData); void HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spellid, uint16 flag, ObjectGuid guid2, float x, float y, float z); - void HandlePetNameQuery(WorldPacket& recvData); + void HandleQueryPetName(WorldPackets::Query::QueryPetName& packet); void HandlePetSetAction(WorldPacket& recvData); void HandlePetAbandon(WorldPacket& recvData); void HandlePetRename(WorldPacket& recvData); @@ -1314,7 +1339,7 @@ class WorldSession void HandleWorldTeleportOpcode(WorldPacket& recvData); void HandleMinimapPingOpcode(WorldPacket& recvData); void HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient& packet); - void HandleFarSightOpcode(WorldPacket& recvData); + void HandleFarSightOpcode(WorldPackets::Misc::FarSight& packet); void HandleSetDungeonDifficultyOpcode(WorldPackets::Misc::SetDungeonDifficulty& setDungeonDifficulty); void HandleSetRaidDifficultyOpcode(WorldPackets::Misc::SetRaidDifficulty& setRaidDifficulty); void HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData); @@ -1353,14 +1378,14 @@ class WorldSession void SendLfgOfferContinue(uint32 dungeonEntry); void SendLfgTeleportError(uint8 err); - void HandleSelfResOpcode(WorldPacket& recvData); + void HandleSelfResOpcode(WorldPackets::Spells::SelfRes& packet); void HandleComplainOpcode(WorldPacket& recvData); void HandleRequestPetInfoOpcode(WorldPacket& recvData); // Socket gem void HandleSocketOpcode(WorldPacket& recvData); - void HandleCancelTempEnchantmentOpcode(WorldPacket& recvData); + void HandleCancelTempEnchantmentOpcode(WorldPackets::Item::CancelTempEnchantment& cancelTempEnchantment); void HandleGetItemPurchaseData(WorldPackets::Item::GetItemPurchaseData& packet); void HandleItemRefund(WorldPacket& recvData); @@ -1442,13 +1467,19 @@ class WorldSession // Token void HandleUpdateListedAuctionableTokens(WorldPackets::Token::UpdateListedAuctionableTokens& updateListedAuctionableTokens); - - void SendSpellCategoryCooldowns(); + void HandleRequestWowTokenMarketPrice(WorldPackets::Token::RequestWowTokenMarketPrice& requestWowTokenMarketPrice); // Compact Unit Frames (4.x) void HandleSaveCUFProfiles(WorldPacket& recvPacket); void SendLoadCUFProfiles(); + // Garrison + void HandleGetGarrisonInfo(WorldPackets::Garrison::GetGarrisonInfo& getGarrisonInfo); + void HandleGarrisonPurchaseBuilding(WorldPackets::Garrison::GarrisonPurchaseBuilding& garrisonPurchaseBuilding); + void HandleGarrisonCancelConstruction(WorldPackets::Garrison::GarrisonCancelConstruction& garrisonCancelConstruction); + void HandleGarrisonRequestBlueprintAndSpecializationData(WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData& garrisonRequestBlueprintAndSpecializationData); + void HandleGarrisonGetBuildingLandmarks(WorldPackets::Garrison::GarrisonGetBuildingLandmarks& garrisonGetBuildingLandmarks); + private: void InitializeQueryCallbackParameters(); void ProcessQueryCallbacks(); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 2b2b2458993..e4b98f1c54b 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -81,8 +81,8 @@ void WorldSocket::Start() initializer.Write(&header, sizeof(header.Setup.Size)); initializer.Write(ServerConnectionInitialize.c_str(), ServerConnectionInitialize.length()); - std::unique_lock<std::mutex> dummy(_writeLock, std::defer_lock); - QueuePacket(std::move(initializer), dummy); + std::unique_lock<std::mutex> guard(_writeLock); + QueuePacket(std::move(initializer), guard); } void WorldSocket::HandleSendAuthSession() @@ -182,6 +182,13 @@ void WorldSocket::ExtractOpcodeAndSize(ClientPktHeader const* header, uint32& op } } +void WorldSocket::SetWorldSession(WorldSession* session) +{ + std::lock_guard<std::mutex> sessionGuard(_worldSessionLock); + _worldSession = session; + _authed = true; +} + bool WorldSocket::ReadHeaderHandler() { ASSERT(_headerBuffer.GetActiveSize() == SizeOfClientHeader[_initialized][_authCrypt.IsInitialized()], "Header size " SZFMTD " different than expected %u", _headerBuffer.GetActiveSize(), SizeOfClientHeader[_initialized][_authCrypt.IsInitialized()]); @@ -724,22 +731,7 @@ void WorldSocket::HandleAuthContinuedSession(WorldPackets::Auth::AuthContinuedSe return; } - _worldSession = sWorld->FindSession(accountId); - if (!_worldSession) - { - SendAuthResponseError(AUTH_SESSION_EXPIRED); - TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: No active session found for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str()); - DelayedCloseSocket(); - return; - } - - _authed = true; - - WorldPackets::Auth::ResumeComms resumeComms; - SendPacketAndLogOpcode(*resumeComms.Write()); - - _worldSession->AddInstanceConnection(shared_from_this()); - _worldSession->HandleContinuePlayerLogin(); + sWorld->AddInstanceSocket(shared_from_this(), accountId); } void WorldSocket::HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& connectToFailed) @@ -783,8 +775,6 @@ void WorldSocket::HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& con void WorldSocket::SendAuthResponseError(uint8 code) { WorldPackets::Auth::AuthResponse response; - response.SuccessInfo.HasValue = false; - response.WaitInfo.HasValue = false; response.Result = code; SendPacketAndLogOpcode(*response.Write()); } diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 482f794344b..e42a310f470 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -85,12 +85,14 @@ public: ConnectionType GetConnectionType() const { return _type; } + void SendAuthResponseError(uint8 code); + void SetWorldSession(WorldSession* session); + protected: void OnClose() override; void ReadHandler() override; bool ReadHeaderHandler(); bool ReadDataHandler(); - private: /// writes network.opcode log /// accessing WorldSession is not threadsafe, only do it when holding _worldSessionLock @@ -104,7 +106,6 @@ private: void HandleAuthSession(WorldPackets::Auth::AuthSession& authSession); void HandleAuthContinuedSession(WorldPackets::Auth::AuthContinuedSession& authSession); void HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& connectToFailed); - void SendAuthResponseError(uint8 code); bool HandlePing(WorldPacket& recvPacket); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 543b818597e..a3b0c4788e7 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1408,7 +1408,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const { case FORM_CAT: // Savage Roar - if (target->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_DRUID, 0, 0x10000000, 0)) + if (target->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_DRUID, flag128(0, 0x10000000, 0))) target->CastSpell(target, 62071, true); // Nurturing Instinct if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT, SPELLFAMILY_DRUID, 2254, EFFECT_0)) @@ -1984,7 +1984,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo if (target->getClass() == CLASS_DRUID) { // Dash - if (AuraEffect* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8)) + if (AuraEffect* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, flag128(0, 0, 0x8))) aurEff->RecalculateAmount(); // Disarm handling @@ -5731,7 +5731,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) case 28820: { // Need remove self if Lightning Shield not active - if (!target->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0)) + if (!target->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, flag128(0x400, 0, 0))) target->RemoveAurasDueToSpell(28820); return; } @@ -6640,6 +6640,6 @@ void AuraEffect::HandleModSpellCategoryCooldown(AuraApplication const* aurApp, u if (!(mode & AURA_EFFECT_HANDLE_REAL)) return; - if (aurApp->GetTarget()->GetTypeId() == TYPEID_PLAYER) - aurApp->GetTarget()->ToPlayer()->GetSession()->SendSpellCategoryCooldowns(); + if (Player* player = aurApp->GetTarget()->ToPlayer()) + player->SendSpellCategoryCooldowns(); } diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 9e6f103be0d..c3247b41b35 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -213,12 +213,12 @@ void AuraApplication::BuildUpdatePacket(WorldPackets::Spells::AuraInfo& auraInfo // stack amount has priority over charges (checked on retail with spell 50262) auraData.Applications = aura->GetSpellInfo()->StackAmount ? aura->GetStackAmount() : aura->GetCharges(); if (!(auraData.Flags & AFLAG_NOCASTER)) - auraData.CastUnit.Set(aura->GetCasterGUID()); + auraData.CastUnit = aura->GetCasterGUID(); if (auraData.Flags & AFLAG_DURATION) { - auraData.Duration.Set(aura->GetMaxDuration()); - auraData.Remaining.Set(aura->GetDuration()); + auraData.Duration = aura->GetMaxDuration(); + auraData.Remaining = aura->GetDuration(); } if (auraData.Flags & AFLAG_SCALABLE) @@ -229,7 +229,7 @@ void AuraApplication::BuildUpdatePacket(WorldPackets::Spells::AuraInfo& auraInfo auraData.Points[effect->GetEffIndex()] = float(effect->GetAmount()); } - auraInfo.AuraData.Set(auraData); + auraInfo.AuraData = auraData; } void AuraApplication::ClientUpdate(bool remove) @@ -1112,9 +1112,6 @@ void Aura::UnregisterSingleTarget() { ASSERT(m_isSingleTarget); Unit* caster = GetCaster(); - /// @todo find a better way to do this. - if (!caster) - caster = ObjectAccessor::GetObjectInOrOutOfWorld(GetCasterGUID(), (Unit*)NULL); ASSERT(caster); caster->GetSingleCastAuras().remove(this); SetIsSingleTarget(false); @@ -1519,7 +1516,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b case SPELLFAMILY_ROGUE: // Remove Vanish on stealth remove if (GetId() == 1784) - target->RemoveAurasWithFamily(SPELLFAMILY_ROGUE, 0x0000800, 0, 0, target->GetGUID()); + target->RemoveAurasWithFamily(SPELLFAMILY_ROGUE, flag128(0x0000800, 0, 0, 0), target->GetGUID()); break; case SPELLFAMILY_PALADIN: // Remove the immunity shield marker on Forbearance removal if AW marker is not present diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1df9fd000f6..fb40de60048 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -58,6 +58,7 @@ #include "Battlefield.h" #include "BattlefieldMgr.h" #include "SpellPackets.h" +#include "CombatLogPackets.h" #include "SpellHistory.h" extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; @@ -120,32 +121,32 @@ SpellCastTargets::SpellCastTargets(Unit* caster, WorldPackets::Spells::SpellCast m_objectTargetGUID(spellCastRequest.Target.Unit), m_itemTargetGUID(spellCastRequest.Target.Item), m_itemTargetEntry(0), m_pitch(0.0f), m_speed(0.0f), m_strTarget(spellCastRequest.Target.Name) { - if (spellCastRequest.Target.SrcLocation.HasValue) + if (spellCastRequest.Target.SrcLocation) { - m_src._transportGUID = spellCastRequest.Target.SrcLocation.Value.Transport; + m_src._transportGUID = spellCastRequest.Target.SrcLocation->Transport; Position* pos; if (!m_src._transportGUID.IsEmpty()) pos = &m_src._transportOffset; else pos = &m_src._position; - pos->Relocate(spellCastRequest.Target.SrcLocation.Value.Location); - if (spellCastRequest.Target.Orientation.HasValue) - pos->SetOrientation(spellCastRequest.Target.Orientation.Value); + pos->Relocate(spellCastRequest.Target.SrcLocation->Location); + if (spellCastRequest.Target.Orientation) + pos->SetOrientation(*spellCastRequest.Target.Orientation); } - if (spellCastRequest.Target.DstLocation.HasValue) + if (spellCastRequest.Target.DstLocation) { - m_dst._transportGUID = spellCastRequest.Target.DstLocation.Value.Transport; + m_dst._transportGUID = spellCastRequest.Target.DstLocation->Transport; Position* pos; if (!m_dst._transportGUID.IsEmpty()) pos = &m_dst._transportOffset; else pos = &m_dst._position; - pos->Relocate(spellCastRequest.Target.DstLocation.Value.Location); - if (spellCastRequest.Target.Orientation.HasValue) - pos->SetOrientation(spellCastRequest.Target.Orientation.Value); + pos->Relocate(spellCastRequest.Target.DstLocation->Location); + if (spellCastRequest.Target.Orientation) + pos->SetOrientation(*spellCastRequest.Target.Orientation); } SetPitch(spellCastRequest.MissileTrajectory.Pitch); @@ -221,24 +222,22 @@ void SpellCastTargets::Write(WorldPackets::Spells::SpellTargetData& data) if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION) { - WorldPackets::Spells::TargetLocation& target = data.SrcLocation.Value; - target.Transport = m_src._transportGUID; // relative position guid here - transport for example + data.SrcLocation = boost::in_place(); + data.SrcLocation->Transport = m_src._transportGUID; // relative position guid here - transport for example if (!m_src._transportGUID.IsEmpty()) - target.Location = m_src._transportOffset; + data.SrcLocation->Location = m_src._transportOffset; else - target.Location = m_src._position; - data.SrcLocation.HasValue = true; + data.SrcLocation->Location = m_src._position; } if (m_targetMask & TARGET_FLAG_DEST_LOCATION) { - WorldPackets::Spells::TargetLocation& target = data.DstLocation.Value; - target.Transport = m_dst._transportGUID; // relative position guid here - transport for example + data.DstLocation = boost::in_place(); + data.DstLocation->Transport = m_dst._transportGUID; // relative position guid here - transport for example if (!m_dst._transportGUID.IsEmpty()) - target.Location = m_dst._transportOffset; + data.DstLocation->Location = m_dst._transportOffset; else - target.Location = m_dst._position; - data.DstLocation.HasValue = true; + data.DstLocation->Location = m_dst._position; } if (m_targetMask & TARGET_FLAG_STRING) @@ -667,7 +666,7 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)), && !m_spellInfo->IsPassive() && !m_spellInfo->IsPositive(); CleanupTargetList(); - memset(m_effectExecuteData, 0, MAX_SPELL_EFFECTS * sizeof(ByteBuffer*)); + CleanupExecuteLogList(); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) m_destTargets[i] = SpellDestination(*m_caster); @@ -696,8 +695,7 @@ Spell::~Spell() ASSERT(m_caster->ToPlayer()->m_spellModTakingSpell != this); delete m_spellValue; - - CheckEffectExecuteData(); + CleanupExecuteLogList(); } void Spell::InitExplicitTargets(SpellCastTargets const& targets) @@ -2300,10 +2298,10 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) target->processed = true; // Target checked in apply effects procedure // Get mask of effects for target - uint8 mask = target->effectMask; + uint32 mask = target->effectMask; Unit* unit = m_caster->GetGUID() == target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target->targetGUID); - if (!unit) + if (!unit && target->targetGUID.IsPlayer()) // only players may be targeted across maps { uint8 farMask = 0; // create far target mask @@ -2314,14 +2312,15 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (!farMask) return; + // find unit in world - unit = ObjectAccessor::FindUnit(target->targetGUID); + unit = ObjectAccessor::FindPlayer(target->targetGUID); if (!unit) return; // do far effects on the unit // can't use default call because of threading, do stuff as fast as possible - for(SpellEffectInfo const* effect : GetEffects()) + for (SpellEffectInfo const* effect : GetEffects()) if (effect && (farMask & (1 << effect->EffectIndex))) HandleEffects(unit, NULL, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); return; @@ -2851,8 +2850,8 @@ bool Spell::UpdateChanneledTargetList() if (m_channelTargetEffectMask == 0) return true; - uint8 channelTargetEffectMask = m_channelTargetEffectMask; - uint8 channelAuraMask = 0; + uint32 channelTargetEffectMask = m_channelTargetEffectMask; + uint32 channelAuraMask = 0; for (SpellEffectInfo const* effect : GetEffects()) if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) channelAuraMask |= 1 << effect->EffectIndex; @@ -3509,7 +3508,7 @@ void Spell::_handle_finish_phase() if (m_caster->m_extraAttacks && HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) { - if (Unit* victim = ObjectAccessor::FindUnit(m_targets.GetOrigUnitTargetGUID())) + if (Unit* victim = ObjectAccessor::GetUnit(*m_caster, m_targets.GetOrigUnitTargetGUID())) m_caster->HandleProcExtraAttackFor(victim); else m_caster->m_extraAttacks = 0; @@ -3890,29 +3889,28 @@ void Spell::SendSpellStart() if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list { - WorldPackets::Spells::RuneData& runeData = castData.RemainingRunes.Value; + castData.RemainingRunes = boost::in_place(); + //TODO: There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster if (Player* player = m_caster->ToPlayer()) { - runeData.Start = m_runesState; // runes state before - runeData.Count = player->GetRunesState(); // runes state after + castData.RemainingRunes->Start = m_runesState; // runes state before + castData.RemainingRunes->Count = player->GetRunesState(); // runes state after for (uint8 i = 0; i < MAX_RUNES; ++i) { // float casts ensure the division is performed on floats as we need float result float baseCd = float(player->GetRuneBaseCooldown(i)); - runeData.Cooldowns.push_back((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed + castData.RemainingRunes->Cooldowns.push_back((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed } } else { - runeData.Start = 0; - runeData.Count = 0; + castData.RemainingRunes->Start = 0; + castData.RemainingRunes->Count = 0; for (uint8 i = 0; i < MAX_RUNES; ++i) - runeData.Cooldowns.push_back(0); + castData.RemainingRunes->Cooldowns.push_back(0); } - - castData.RemainingRunes.HasValue = true; } /** @todo implement spell ammo packet data @@ -4009,29 +4007,28 @@ void Spell::SendSpellGo() if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list { - WorldPackets::Spells::RuneData& runeData = castData.RemainingRunes.Value; + castData.RemainingRunes = boost::in_place(); + //TODO: There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster if (Player* player = m_caster->ToPlayer()) { - runeData.Start = m_runesState; // runes state before - runeData.Count = player->GetRunesState(); // runes state after + castData.RemainingRunes->Start = m_runesState; // runes state before + castData.RemainingRunes->Count = player->GetRunesState(); // runes state after for (uint8 i = 0; i < MAX_RUNES; ++i) { // float casts ensure the division is performed on floats as we need float result float baseCd = float(player->GetRuneBaseCooldown(i)); - runeData.Cooldowns.push_back((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed + castData.RemainingRunes->Cooldowns.push_back((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed } } else { - runeData.Start = 0; - runeData.Count = 0; + castData.RemainingRunes->Start = 0; + castData.RemainingRunes->Count = 0; for (uint8 i = 0; i < MAX_RUNES; ++i) - runeData.Cooldowns.push_back(0); + castData.RemainingRunes->Cooldowns.push_back(0); } - - castData.RemainingRunes.HasValue = true; } if (castFlags & CAST_FLAG_ADJUST_MISSILE) @@ -4081,54 +4078,69 @@ void Spell::UpdateSpellCastDataTargets(WorldPackets::Spells::SpellCastData& data m_channelTargetEffectMask = 0; } -void Spell::SendLogExecute() +void Spell::SendSpellExecuteLog() { - WorldPacket data(SMSG_SPELL_EXECUTE_LOG, (8+4+4+4+4+8)); - - data << m_caster->GetPackGUID(); + WorldPackets::CombatLog::SpellExecuteLog spellExecuteLog; - data << uint32(m_spellInfo->Id); + spellExecuteLog.Caster = m_caster->GetGUID(); + spellExecuteLog.SpellID = m_spellInfo->Id; - uint8 effCount = 0; - for (SpellEffectInfo const* effect : GetEffects()) - { - if (effect && m_effectExecuteData[effect->EffectIndex]) - ++effCount; - } - - if (!effCount) + if (_powerDrainTargets->empty() && _extraAttacksTargets->empty() && + _durabilityDamageTargets->empty() && _genericVictimTargets->empty() && + _tradeSkillTargets->empty() && _feedPetTargets->empty()) return; - data << uint32(effCount); for (SpellEffectInfo const* effect : GetEffects()) { - if (!effect || !m_effectExecuteData[effect->EffectIndex]) + WorldPackets::CombatLog::SpellExecuteLog::SpellLogEffect spellLogEffect; + if (!effect) continue; - data << uint32(effect->Effect); // spell effect + spellLogEffect.Effect = effect->Effect; + + for (SpellLogEffectPowerDrainParams const& powerDrainParam : _powerDrainTargets[effect->EffectIndex]) + spellLogEffect.PowerDrainTargets.push_back(powerDrainParam); + + for (SpellLogEffectExtraAttacksParams const& extraAttacksTarget : _extraAttacksTargets[effect->EffectIndex]) + spellLogEffect.ExtraAttacksTargets.push_back(extraAttacksTarget); + + for (SpellLogEffectDurabilityDamageParams const& durabilityDamageTarget : _durabilityDamageTargets[effect->EffectIndex]) + spellLogEffect.DurabilityDamageTargets.push_back(durabilityDamageTarget); + + for (SpellLogEffectGenericVictimParams const& genericVictimTarget : _genericVictimTargets[effect->EffectIndex]) + spellLogEffect.GenericVictimTargets.push_back(genericVictimTarget); + + for (SpellLogEffectTradeSkillItemParams const& tradeSkillTarget : _tradeSkillTargets[effect->EffectIndex]) + spellLogEffect.TradeSkillTargets.push_back(tradeSkillTarget); - data.append(*m_effectExecuteData[effect->EffectIndex]); + for (SpellLogEffectFeedPetParams const& feedPetTarget : _feedPetTargets[effect->EffectIndex]) + spellLogEffect.FeedPetTargets.push_back(feedPetTarget); - delete m_effectExecuteData[effect->EffectIndex]; - m_effectExecuteData[effect->EffectIndex] = NULL; + spellExecuteLog.Effects.push_back(spellLogEffect); } - m_caster->SendMessageToSet(&data, true); + + m_caster->SendMessageToSet(spellExecuteLog.Write(), true); } -void Spell::ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit* target, uint32 powerType, uint32 powerTaken, float gainMultiplier) +void Spell::ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit* target, uint32 powerType, uint32 points, float amplitude) { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << target->GetPackGUID(); - *m_effectExecuteData[effIndex] << uint32(powerTaken); - *m_effectExecuteData[effIndex] << uint32(powerType); - *m_effectExecuteData[effIndex] << float(gainMultiplier); + SpellLogEffectPowerDrainParams spellLogEffectPowerDrainParams; + + spellLogEffectPowerDrainParams.Victim = target->GetGUID(); + spellLogEffectPowerDrainParams.Points = points; + spellLogEffectPowerDrainParams.PowerType = powerType; + spellLogEffectPowerDrainParams.Amplitude = amplitude; + + _powerDrainTargets[effIndex].push_back(spellLogEffectPowerDrainParams); } -void Spell::ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit* victim, uint32 attCount) +void Spell::ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit* victim, uint32 numAttacks) { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << victim->GetPackGUID(); - *m_effectExecuteData[effIndex] << uint32(attCount); + SpellLogEffectExtraAttacksParams spellLogEffectExtraAttacksParams; + spellLogEffectExtraAttacksParams.Victim = victim->GetGUID(); + spellLogEffectExtraAttacksParams.NumAttacks = numAttacks; + + _extraAttacksTargets[effIndex].push_back(spellLogEffectExtraAttacksParams); } void Spell::ExecuteLogEffectInterruptCast(uint8 /*effIndex*/, Unit* victim, uint32 spellId) @@ -4176,48 +4188,72 @@ void Spell::ExecuteLogEffectInterruptCast(uint8 /*effIndex*/, Unit* victim, uint m_caster->SendMessageToSet(&data, true); } -void Spell::ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit* victim, int32 itemId, int32 slot) +void Spell::ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit* victim, int32 itemId, int32 amount) { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << victim->GetPackGUID(); - *m_effectExecuteData[effIndex] << int32(itemId); - *m_effectExecuteData[effIndex] << int32(slot); + SpellLogEffectDurabilityDamageParams spellLogEffectDurabilityDamageParams; + spellLogEffectDurabilityDamageParams.Victim = victim->GetGUID(); + spellLogEffectDurabilityDamageParams.ItemID = itemId; + spellLogEffectDurabilityDamageParams.Amount = amount; + + _durabilityDamageTargets[effIndex].push_back(spellLogEffectDurabilityDamageParams); } void Spell::ExecuteLogEffectOpenLock(uint8 effIndex, Object* obj) { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << obj->GetPackGUID(); + SpellLogEffectGenericVictimParams spellLogEffectGenericVictimParams; + spellLogEffectGenericVictimParams.Victim = obj->GetGUID(); + + _genericVictimTargets[effIndex].push_back(spellLogEffectGenericVictimParams); } void Spell::ExecuteLogEffectCreateItem(uint8 effIndex, uint32 entry) { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << uint32(entry); + SpellLogEffectTradeSkillItemParams spellLogEffectTradeSkillItemParams; + spellLogEffectTradeSkillItemParams.ItemID = entry; + + _tradeSkillTargets[effIndex].push_back(spellLogEffectTradeSkillItemParams); } void Spell::ExecuteLogEffectDestroyItem(uint8 effIndex, uint32 entry) { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << uint32(entry); + SpellLogEffectFeedPetParams spellLogEffectFeedPetParams; + spellLogEffectFeedPetParams.ItemID = entry; + + _feedPetTargets[effIndex].push_back(spellLogEffectFeedPetParams); } void Spell::ExecuteLogEffectSummonObject(uint8 effIndex, WorldObject* obj) { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << obj->GetPackGUID(); + SpellLogEffectGenericVictimParams spellLogEffectGenericVictimParams; + spellLogEffectGenericVictimParams.Victim = obj->GetGUID(); + + _genericVictimTargets[effIndex].push_back(spellLogEffectGenericVictimParams); } void Spell::ExecuteLogEffectUnsummonObject(uint8 effIndex, WorldObject* obj) { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << obj->GetPackGUID(); + SpellLogEffectGenericVictimParams spellLogEffectGenericVictimParams; + spellLogEffectGenericVictimParams.Victim = obj->GetGUID(); + + _genericVictimTargets[effIndex].push_back(spellLogEffectGenericVictimParams); +} + +void Spell::ExecuteLogEffectResurrect(uint8 effect, Unit* target) +{ + SpellLogEffectGenericVictimParams spellLogEffectGenericVictimParams; + spellLogEffectGenericVictimParams.Victim = target->GetGUID(); + + _genericVictimTargets[effect].push_back(spellLogEffectGenericVictimParams); } -void Spell::ExecuteLogEffectResurrect(uint8 effIndex, Unit* target) +void Spell::CleanupExecuteLogList() { - InitEffectExecuteData(effIndex); - *m_effectExecuteData[effIndex] << target->GetPackGUID(); + _durabilityDamageTargets->clear(); + _extraAttacksTargets->clear(); + _feedPetTargets->clear(); + _genericVictimTargets->clear(); + _powerDrainTargets->clear(); + _tradeSkillTargets->clear(); } void Spell::SendInterrupted(uint8 result) @@ -4276,21 +4312,26 @@ void Spell::SendResurrectRequest(Player* target) // get resurrector name for creature resurrections, otherwise packet will be not accepted // for player resurrections the name is looked up by guid std::string const sentName(m_caster->GetTypeId() == TYPEID_PLAYER - ? "" - : m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex())); + ? "" : m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex())); - WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+sentName.size()+1+1+1+4)); - data << m_caster->GetGUID(); - data << uint32(sentName.size() + 1); + WorldPackets::Spells::ResurrectRequest resurrectRequest; + resurrectRequest.ResurrectOffererGUID = m_caster->GetGUID(); + resurrectRequest.ResurrectOffererVirtualRealmAddress = GetVirtualRealmAddress(); - data << sentName; - data << uint8(0); // null terminator + if (Pet* pet = target->GetPet()) + { + if (CharmInfo* charmInfo = pet->GetCharmInfo()) + resurrectRequest.PetNumber = charmInfo->GetPetNumber(); + } - data << uint8(m_caster->GetTypeId() == TYPEID_PLAYER ? 0 : 1); // "you'll be afflicted with resurrection sickness" - // override delay sent with SMSG_CORPSE_RECLAIM_DELAY, set instant resurrection for spells with this attribute - // 4.2.2 edit : id of the spell used to resurect. (used client-side for Mass Resurect) - data << uint32(m_spellInfo->Id); - target->GetSession()->SendPacket(&data); + resurrectRequest.SpellID = m_spellInfo->Id; + + //packet.ReadBit("UseTimer"); /// @todo: 6.x Has to be implemented + resurrectRequest.Sickness = m_caster->GetTypeId() != TYPEID_PLAYER; // "you'll be afflicted with resurrection sickness" + + resurrectRequest.Name = sentName; + + target->GetSession()->SendPacket(resurrectRequest.Write()); } void Spell::TakeCastItem() @@ -4544,7 +4585,7 @@ void Spell::TakeReagents() ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetTemplate() : NULL; // do not take reagents for these item casts - if (castItemTemplate && castItemTemplate->GetFlags() & ITEM_PROTO_FLAG_TRIGGERED_CAST) + if (castItemTemplate && castItemTemplate->GetFlags() & ITEM_FLAG_TRIGGERED_CAST) return; Player* p_caster = m_caster->ToPlayer(); @@ -5975,7 +6016,7 @@ SpellCastResult Spell::CheckItems() } // do not take reagents for these item casts - if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_TRIGGERED_CAST)) + if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_TRIGGERED_CAST)) { bool checkReagents = !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST) && !player->CanNoReagentCast(m_spellInfo); // Not own traded item (in trader trade slot) requires reagents even if triggered spell @@ -6102,7 +6143,7 @@ SpellCastResult Spell::CheckItems() if (m_targets.GetItemTarget()->GetOwner() != m_caster) return SPELL_FAILED_NOT_TRADEABLE; // do not allow to enchant vellum from scroll made by vellum-prevent exploit - if (m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_TRIGGERED_CAST) + if (m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_TRIGGERED_CAST) return SPELL_FAILED_TOTEM_CATEGORY; ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, effect->ItemType, 1); @@ -6225,7 +6266,7 @@ SpellCastResult Spell::CheckItems() if (!m_targets.GetItemTarget()) return SPELL_FAILED_CANT_BE_PROSPECTED; //ensure item is a prospectable ore - if (!(m_targets.GetItemTarget()->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_PROSPECTABLE)) + if (!(m_targets.GetItemTarget()->GetTemplate()->GetFlags() & ITEM_FLAG_PROSPECTABLE)) return SPELL_FAILED_CANT_BE_PROSPECTED; //prevent prospecting in trade slot if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID()) @@ -6248,7 +6289,7 @@ SpellCastResult Spell::CheckItems() if (!m_targets.GetItemTarget()) return SPELL_FAILED_CANT_BE_MILLED; //ensure item is a millable herb - if (!(m_targets.GetItemTarget()->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_MILLABLE)) + if (!(m_targets.GetItemTarget()->GetTemplate()->GetFlags() & ITEM_FLAG_MILLABLE)) return SPELL_FAILED_CANT_BE_MILLED; //prevent milling in trade slot if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID()) @@ -6946,35 +6987,11 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value) void Spell::PrepareTargetProcessing() { - CheckEffectExecuteData(); } void Spell::FinishTargetProcessing() { - SendLogExecute(); -} - -void Spell::InitEffectExecuteData(uint32 effIndex) -{ - ASSERT(effIndex < MAX_SPELL_EFFECTS); - if (!m_effectExecuteData[effIndex]) - { - m_effectExecuteData[effIndex] = new ByteBuffer(0x20); - // first dword - target counter - *m_effectExecuteData[effIndex] << uint32(1); - } - else - { - // increase target counter by one - uint32 count = (*m_effectExecuteData[effIndex]).read<uint32>(0); - (*m_effectExecuteData[effIndex]).put<uint32>(0, ++count); - } -} - -void Spell::CheckEffectExecuteData() -{ - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - ASSERT(!m_effectExecuteData[i]); + SendSpellExecuteLog(); } void Spell::LoadScripts() @@ -7485,7 +7502,7 @@ bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target) } else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE)) { - if (!_caster->HasInLine(target, _caster->GetObjectSize())) + if (!_caster->HasInLine(target, _caster->GetObjectSize() + target->GetObjectSize())) return false; } else @@ -7502,7 +7519,7 @@ WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Po bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target) { // return all targets on missile trajectory (0 - size of a missile) - if (!_caster->HasInLine(target, 0)) + if (!_caster->HasInLine(target, target->GetObjectSize())) return false; return WorldObjectSpellAreaTargetCheck::operator ()(target); } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 4190cca0ab4..7af7644d924 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -105,6 +105,43 @@ struct SpellDestination Position _transportOffset; }; + +struct SpellLogEffectPowerDrainParams +{ + ObjectGuid Victim; + uint32 Points = 0; + uint32 PowerType = 0; + float Amplitude = 0; +}; + +struct SpellLogEffectExtraAttacksParams +{ + ObjectGuid Victim; + uint32 NumAttacks = 0; +}; + +struct SpellLogEffectDurabilityDamageParams +{ + ObjectGuid Victim; + int32 ItemID = 0; + int32 Amount = 0; +}; + +struct SpellLogEffectGenericVictimParams +{ + ObjectGuid Victim; +}; + +struct SpellLogEffectTradeSkillItemParams +{ + int32 ItemID = 0; +}; + +struct SpellLogEffectFeedPetParams +{ + int32 ItemID = 0; +}; + class SpellCastTargets { public: @@ -368,6 +405,8 @@ class Spell void EffectCreateAreaTrigger(SpellEffIndex effIndex); void EffectRemoveTalent(SpellEffIndex effIndex); void EffectDestroyItem(SpellEffIndex effIndex); + void EffectLearnGarrisonBuilding(SpellEffIndex effIndex); + void EffectCreateGarrison(SpellEffIndex effIndex); typedef std::set<Aura*> UsedSpellMods; @@ -453,17 +492,18 @@ class Spell void SendSpellStart(); void SendSpellGo(); void SendSpellCooldown(); - void SendLogExecute(); - void ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit* target, uint32 powerType, uint32 powerTaken, float gainMultiplier); - void ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit* victim, uint32 attCount); + void SendSpellExecuteLog(); + void ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit* target, uint32 powerType, uint32 points, float amplitude); + void ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit* victim, uint32 numAttacks); void ExecuteLogEffectInterruptCast(uint8 effIndex, Unit* victim, uint32 spellId); - void ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit* victim, int32 itemId, int32 slot); + void ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit* victim, int32 itemId, int32 amount); void ExecuteLogEffectOpenLock(uint8 effIndex, Object* obj); void ExecuteLogEffectCreateItem(uint8 effIndex, uint32 entry); void ExecuteLogEffectDestroyItem(uint8 effIndex, uint32 entry); void ExecuteLogEffectSummonObject(uint8 effIndex, WorldObject* obj); void ExecuteLogEffectUnsummonObject(uint8 effIndex, WorldObject* obj); void ExecuteLogEffectResurrect(uint8 effIndex, Unit* target); + void CleanupExecuteLogList(); void SendInterrupted(uint8 result); void SendChannelUpdate(uint32 time); void SendChannelStart(uint32 duration); @@ -631,7 +671,7 @@ class Spell uint64 timeDelay; SpellMissInfo missCondition:8; SpellMissInfo reflectResult:8; - uint32 effectMask:32; + uint32 effectMask; bool processed:1; bool alive:1; bool crit:1; @@ -645,8 +685,8 @@ class Spell { ObjectGuid targetGUID; uint64 timeDelay; - uint32 effectMask:32; - bool processed:1; + uint32 effectMask; + bool processed; }; std::vector<GOTargetInfo> m_UniqueGOTargetInfo; @@ -677,10 +717,6 @@ class Spell void PrepareTargetProcessing(); void FinishTargetProcessing(); - // spell execution log - void InitEffectExecuteData(uint32 effIndex); - void CheckEffectExecuteData(); - // Scripting system void LoadScripts(); void CallScriptBeforeCastHandlers(); @@ -735,7 +771,12 @@ class Spell uint32 m_auraScaleMask; PathGenerator m_preGeneratedPath; - ByteBuffer * m_effectExecuteData[MAX_SPELL_EFFECTS]; + std::vector<SpellLogEffectPowerDrainParams> _powerDrainTargets[MAX_SPELL_EFFECTS]; + std::vector<SpellLogEffectExtraAttacksParams> _extraAttacksTargets[MAX_SPELL_EFFECTS]; + std::vector<SpellLogEffectDurabilityDamageParams> _durabilityDamageTargets[MAX_SPELL_EFFECTS]; + std::vector<SpellLogEffectGenericVictimParams> _genericVictimTargets[MAX_SPELL_EFFECTS]; + std::vector<SpellLogEffectTradeSkillItemParams> _tradeSkillTargets[MAX_SPELL_EFFECTS]; + std::vector<SpellLogEffectFeedPetParams> _feedPetTargets[MAX_SPELL_EFFECTS]; #ifdef MAP_BASED_RAND_GEN int32 irand(int32 min, int32 max) { return int32 (m_caster->GetMap()->mtRand.randInt(max - min)) + min; } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 3106ac4bc5a..97e82426e9d 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -67,6 +67,7 @@ #include "GuildMgr.h" #include "ReputationMgr.h" #include "AreaTrigger.h" +#include "Garrison.h" #include "DuelPackets.h" #include "MiscPackets.h" #include "SpellPackets.h" @@ -265,8 +266,8 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectNULL, //189 SPELL_EFFECT_LOOT &Spell::EffectNULL, //190 SPELL_EFFECT_190 &Spell::EffectNULL, //191 SPELL_EFFECT_TELEPORT_TO_DIGSITE - &Spell::EffectNULL, //192 SPELL_EFFECT_192 - &Spell::EffectNULL, //193 SPELL_EFFECT_193 + &Spell::EffectNULL, //192 SPELL_EFFECT_UNCAGE_BATTLEPET + &Spell::EffectNULL, //193 SPELL_EFFECT_START_PET_BATTLE &Spell::EffectNULL, //194 SPELL_EFFECT_194 &Spell::EffectNULL, //195 SPELL_EFFECT_195 &Spell::EffectNULL, //196 SPELL_EFFECT_196 @@ -277,53 +278,53 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectNULL, //201 SPELL_EFFECT_ENABLE_BATTLE_PETS &Spell::EffectNULL, //202 SPELL_EFFECT_202 &Spell::EffectNULL, //203 SPELL_EFFECT_203 - &Spell::EffectNULL, //204 SPELL_EFFECT_204 - &Spell::EffectNULL, //205 SPELL_EFFECT_205 + &Spell::EffectNULL, //204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY + &Spell::EffectNULL, //205 SPELL_EFFECT_LAUNCH_QUEST_CHOICE &Spell::EffectNULL, //206 SPELL_EFFECT_206 - &Spell::EffectNULL, //207 SPELL_EFFECT_207 + &Spell::EffectNULL, //207 SPELL_EFFECT_LAUNCH_QUEST_TASK &Spell::EffectNULL, //208 SPELL_EFFECT_208 &Spell::EffectNULL, //209 SPELL_EFFECT_209 - &Spell::EffectNULL, //210 SPELL_EFFECT_210 - &Spell::EffectNULL, //211 SPELL_EFFECT_211 + &Spell::EffectLearnGarrisonBuilding, //210 SPELL_EFFECT_LEARN_GARRISON_BUILDING + &Spell::EffectNULL, //211 SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION &Spell::EffectNULL, //212 SPELL_EFFECT_212 &Spell::EffectNULL, //213 SPELL_EFFECT_213 - &Spell::EffectNULL, //214 SPELL_EFFECT_214 - &Spell::EffectNULL, //215 SPELL_EFFECT_215 - &Spell::EffectNULL, //216 SPELL_EFFECT_216 - &Spell::EffectNULL, //217 SPELL_EFFECT_217 + &Spell::EffectCreateGarrison, //214 SPELL_EFFECT_CREATE_GARRISON + &Spell::EffectNULL, //215 SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS + &Spell::EffectNULL, //216 SPELL_EFFECT_CREATE_SHIPMENT + &Spell::EffectNULL, //217 SPELL_EFFECT_UPGRADE_GARRISON &Spell::EffectNULL, //218 SPELL_EFFECT_218 &Spell::EffectNULL, //219 SPELL_EFFECT_219 - &Spell::EffectNULL, //220 SPELL_EFFECT_220 + &Spell::EffectNULL, //220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER &Spell::EffectNULL, //221 SPELL_EFFECT_221 - &Spell::EffectNULL, //222 SPELL_EFFECT_222 - &Spell::EffectNULL, //223 SPELL_EFFECT_223 - &Spell::EffectNULL, //224 SPELL_EFFECT_224 - &Spell::EffectNULL, //225 SPELL_EFFECT_225 + &Spell::EffectNULL, //222 SPELL_EFFECT_CREATE_HEIRLOOM_ITEM + &Spell::EffectNULL, //223 SPELL_EFFECT_CHANGE_ITEM_BONUSES + &Spell::EffectNULL, //224 SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING + &Spell::EffectNULL, //225 SPELL_EFFECT_GRANT_BATTLEPET_LEVEL &Spell::EffectNULL, //226 SPELL_EFFECT_226 &Spell::EffectNULL, //227 SPELL_EFFECT_227 &Spell::EffectNULL, //228 SPELL_EFFECT_228 - &Spell::EffectNULL, //229 SPELL_EFFECT_229 - &Spell::EffectNULL, //230 SPELL_EFFECT_230 - &Spell::EffectNULL, //231 SPELL_EFFECT_231 - &Spell::EffectNULL, //232 SPELL_EFFECT_232 - &Spell::EffectNULL, //233 SPELL_EFFECT_233 + &Spell::EffectNULL, //229 SPELL_EFFECT_SET_FOLLOWER_QUALITY + &Spell::EffectNULL, //230 SPELL_EFFECT_INCREASE_FOLLOWER_ITEM_LEVEL + &Spell::EffectNULL, //231 SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE + &Spell::EffectNULL, //232 SPELL_EFFECT_REMOVE_PHASE + &Spell::EffectNULL, //233 SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES &Spell::EffectNULL, //234 SPELL_EFFECT_234 &Spell::EffectNULL, //235 SPELL_EFFECT_235 - &Spell::EffectNULL, //236 SPELL_EFFECT_236 - &Spell::EffectNULL, //237 SPELL_EFFECT_237 - &Spell::EffectNULL, //238 SPELL_EFFECT_238 - &Spell::EffectNULL, //239 SPELL_EFFECT_239 + &Spell::EffectNULL, //236 SPELL_EFFECT_GIVE_EXPERIENCE + &Spell::EffectNULL, //237 SPELL_EFFECT_GIVE_RESTED_EXPERIENCE_BONUS + &Spell::EffectNULL, //238 SPELL_EFFECT_INCREASE_SKILL + &Spell::EffectNULL, //239 SPELL_EFFECT_END_GARRISON_BUILDING_CONSTRUCTION &Spell::EffectNULL, //240 SPELL_EFFECT_240 &Spell::EffectNULL, //241 SPELL_EFFECT_241 &Spell::EffectNULL, //242 SPELL_EFFECT_242 - &Spell::EffectNULL, //243 SPELL_EFFECT_243 - &Spell::EffectNULL, //244 SPELL_EFFECT_244 - &Spell::EffectNULL, //244 SPELL_EFFECT_245 - &Spell::EffectNULL, //244 SPELL_EFFECT_246 - &Spell::EffectNULL, //244 SPELL_EFFECT_247 - &Spell::EffectNULL, //244 SPELL_EFFECT_248 - &Spell::EffectNULL, //244 SPELL_EFFECT_249 - &Spell::EffectNULL, //244 SPELL_EFFECT_250 + &Spell::EffectNULL, //243 SPELL_EFFECT_APPLY_ENCHANT_ILLUSION + &Spell::EffectNULL, //244 SPELL_EFFECT_LEARN_FOLLOWER_ABILITY + &Spell::EffectNULL, //245 SPELL_EFFECT_UPGRADE_HEIRLOOM + &Spell::EffectNULL, //246 SPELL_EFFECT_FINISH_GARRISON_MISSION + &Spell::EffectNULL, //247 SPELL_EFFECT_ADD_GARRISON_MISSION + &Spell::EffectNULL, //248 SPELL_EFFECT_FINISH_SHIPMENT + &Spell::EffectNULL, //249 SPELL_EFFECT_249 + &Spell::EffectNULL, //250 SPELL_EFFECT_TAKE_SCREENSHOT }; void Spell::EffectNULL(SpellEffIndex /*effIndex*/) @@ -431,7 +432,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) { // Consumption case 28865: - damage = (((InstanceMap*)m_caster->GetMap())->GetDifficultyID() == DIFFICULTY_NONE ? 2750 : 4250); + damage = (m_caster->GetMap()->GetDifficultyID() == DIFFICULTY_NONE ? 2750 : 4250); break; // percent from health with min case 25599: // Thundercrash @@ -483,7 +484,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) // Check aura state for speed but aura state set not only for Immolate spell if (unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE)) { - if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x4, 0, 0)) + if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, flag128(0x4, 0, 0))) damage += damage / 6; } } @@ -516,7 +517,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) if (uint32 combo = player->GetComboPoints()) { // Lookup for Deadly poison (only attacker applied) - if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00010000, 0, 0, m_caster->GetGUID())) + if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, flag128(0x00010000, 0, 0), m_caster->GetGUID())) { // count consumed deadly poison doses at target uint32 spellId = aurEff->GetId(); @@ -561,7 +562,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) // Blood Boil - bonus for diseased targets if (m_spellInfo->SpellFamilyFlags[0] & 0x00040000) { - if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0, 0x00000002, m_caster->GetGUID())) + if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, flag128(0, 0, 0x00000002), m_caster->GetGUID())) { damage += m_damage / 2; damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.035f); @@ -1511,7 +1512,7 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype) // send info to the client player->SendNewItem(pItem, num_to_add, true, bgType == 0); - if (pItem->GetQuality() > ITEM_QUALITY_EPIC || (pItem->GetQuality() == ITEM_QUALITY_EPIC && pItem->GetItemLevel() >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) + if (pItem->GetQuality() > ITEM_QUALITY_EPIC || (pItem->GetQuality() == ITEM_QUALITY_EPIC && pItem->GetItemLevel(player) >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) if (Guild* guild = player->GetGuild()) guild->AddGuildNews(GUILD_NEWS_ITEM_CRAFTED, player->GetGUID(), 0, pProto->GetId()); @@ -1604,7 +1605,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex) if (!caster->IsInWorld()) return; DynamicObject* dynObj = new DynamicObject(false); - if (!dynObj->CreateDynamicObject(sObjectMgr->GetGenerator<HighGuid::DynamicObject>()->Generate(), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL)) + if (!dynObj->CreateDynamicObject(caster->GetMap()->GenerateLowGuid<HighGuid::DynamicObject>(), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL)) { delete dynObj; return; @@ -1808,7 +1809,7 @@ void Spell::SendLoot(ObjectGuid guid, LootType loottype) /// @todo possible must be moved to loot release (in different from linked triggering) if (gameObjTarget->GetGOInfo()->chest.triggeredEvent) { - TC_LOG_DEBUG("spells", "Chest ScriptStart id %u for GO " UI64FMTD, gameObjTarget->GetGOInfo()->chest.triggeredEvent, gameObjTarget->GetDBTableGUIDLow()); + TC_LOG_DEBUG("spells", "Chest ScriptStart id %u for GO " UI64FMTD, gameObjTarget->GetGOInfo()->chest.triggeredEvent, gameObjTarget->GetSpawnId()); player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.triggeredEvent, player, gameObjTarget); } @@ -1877,7 +1878,7 @@ void Spell::EffectOpenLock(SpellEffIndex effIndex) /// @todo Add script for spell 41920 - Filling, becouse server it freze when use this spell // handle outdoor pvp object opening, return true if go was registered for handling // these objects must have been spawned by outdoorpvp! - else if (gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr->HandleOpenGo(player, gameObjTarget->GetGUID())) + else if (gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr->HandleOpenGo(player, gameObjTarget)) return; lockId = goInfo->GetLockId(); guid = gameObjTarget->GetGUID(); @@ -1907,7 +1908,7 @@ void Spell::EffectOpenLock(SpellEffIndex effIndex) if (gameObjTarget) SendLoot(guid, LOOT_SKINNING); else if (itemTarget) - itemTarget->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED); + itemTarget->SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_UNLOCKED); // not allow use skill grow at item base open if (!m_CastItem && skillId != SKILL_NONE) @@ -2166,7 +2167,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) return; summon->SelectLevel(); // some summoned creaters have different from 1 DB data for level/hp - summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureTemplate()->npcflag); + summon->SetUInt64Value(UNIT_NPC_FLAGS, summon->GetCreatureTemplate()->npcflag); summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); @@ -2426,7 +2427,7 @@ void Spell::EffectAddFarsight(SpellEffIndex /*effIndex*/) return; DynamicObject* dynObj = new DynamicObject(true); - if (!dynObj->CreateDynamicObject(sObjectMgr->GetGenerator<HighGuid::DynamicObject>()->Generate(), m_caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS)) + if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid<HighGuid::DynamicObject>(), m_caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS)) { delete dynObj; return; @@ -2544,7 +2545,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) else { // do not increase skill if vellum used - if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_TRIGGERED_CAST)) + if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_TRIGGERED_CAST)) player->UpdateCraftSkill(m_spellInfo->Id); uint32 enchant_id = effectInfo->MiscValue; @@ -3212,7 +3213,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) Map* map = target->GetMap(); - if (!pGameObj->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), gameobject_id, map, + if (!pGameObj->Create(map->GenerateLowGuid<HighGuid::GameObject>(), gameobject_id, map, m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { delete pGameObj; @@ -3239,7 +3240,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry()) { GameObject* linkedGO = new GameObject; - if (linkedGO->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), linkedEntry, map, + if (linkedGO->Create(map->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, map, m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { linkedGO->CopyPhaseFrom(m_caster); @@ -3278,7 +3279,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) case 63975: { // search our Rupture aura on target - if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00100000, 0, 0, m_caster->GetGUID())) + if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, flag128(0x00100000, 0, 0), m_caster->GetGUID())) { uint32 countMin = aurEff->GetBase()->GetMaxDuration(); uint32 countMax = 12000; // this can be wrong, duration should be based on combo-points @@ -3865,7 +3866,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex) uint32 gameobject_id = effectInfo->MiscValue; Map* map = m_caster->GetMap(); - if (!pGameObj->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), gameobject_id, + if (!pGameObj->Create(map->GenerateLowGuid<HighGuid::GameObject>(), gameobject_id, map, 0, m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2, m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2, @@ -4244,7 +4245,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); Map* map = m_caster->GetMap(); - if (!go->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), go_id, map, + if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), go_id, map, 0, x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete go; @@ -4881,7 +4882,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) GameObject* pGameObj = new GameObject; - if (!pGameObj->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), name_id, cMap, + if (!pGameObj->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), name_id, cMap, 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { delete pGameObj; @@ -4949,7 +4950,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry()) { GameObject* linkedGO = new GameObject; - if (linkedGO->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), linkedEntry, cMap, + if (linkedGO->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, cMap, 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { linkedGO->CopyPhaseFrom(m_caster); @@ -4981,7 +4982,7 @@ void Spell::EffectProspecting(SpellEffIndex /*effIndex*/) if (!player) return; - if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_PROSPECTABLE)) + if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_FLAG_PROSPECTABLE)) return; if (itemTarget->GetCount() < 5) @@ -5006,7 +5007,7 @@ void Spell::EffectMilling(SpellEffIndex /*effIndex*/) if (!player) return; - if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_MILLABLE)) + if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_FLAG_MILLABLE)) return; if (itemTarget->GetCount() < 5) @@ -5766,7 +5767,7 @@ void Spell::EffectCreateAreaTrigger(SpellEffIndex /*effIndex*/) uint32 triggerEntry = effectInfo->MiscValue; AreaTrigger * areaTrigger = new AreaTrigger; - if (!areaTrigger->CreateAreaTrigger(sObjectMgr->GetGenerator<HighGuid::AreaTrigger>()->Generate(), triggerEntry, GetCaster(), GetSpellInfo(), pos)) + if (!areaTrigger->CreateAreaTrigger(GetCaster()->GetMap()->GenerateLowGuid<HighGuid::AreaTrigger>(), triggerEntry, GetCaster(), GetSpellInfo(), pos)) delete areaTrigger; } @@ -5801,3 +5802,26 @@ void Spell::EffectDestroyItem(SpellEffIndex effIndex) if (Item* item = player->GetItemByEntry(itemId)) player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); } + +void Spell::EffectLearnGarrisonBuilding(SpellEffIndex effIndex) +{ + if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) + return; + + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + if (Garrison* garrison = unitTarget->ToPlayer()->GetGarrison()) + garrison->LearnBlueprint(GetEffect(effIndex)->MiscValue); +} + +void Spell::EffectCreateGarrison(SpellEffIndex effIndex) +{ + if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) + return; + + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + unitTarget->ToPlayer()->CreateGarrison(GetEffect(effIndex)->MiscValue); +} diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 1334f5840ab..4db7091f971 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1061,7 +1061,7 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntryMap const& ef // SpellClassOptionsEntry SpellClassOptionsEntry const* _class = GetSpellClassOptions(); SpellFamilyName = _class ? _class->SpellClassSet : 0; - SpellFamilyFlags = _class ? _class->SpellClassMask : flag128(0); + SpellFamilyFlags = _class ? _class->SpellClassMask : flag128(); // SpellCooldownsEntry SpellCooldownsEntry const* _cooldowns = GetSpellCooldowns(); @@ -2363,7 +2363,7 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const return SPELL_SPECIFIC_STING; // only hunter aspects have this (but not all aspects in hunter family) - if (SpellFamilyFlags & flag96(0x00380000, 0x00440000, 0x00001010)) + if (SpellFamilyFlags & flag128(0x00200000, 0x00000000, 0x00001010, 0x00000000)) return SPELL_SPECIFIC_ASPECT; break; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index b31090496ee..2f74218ba7b 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3087,19 +3087,12 @@ void SpellMgr::LoadSpellInfoCorrections() const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENEMY); break; case 63320: // Glyph of Life Tap - case 53228: // Rapid Killing (Rank 1) - case 53232: // Rapid Killing (Rank 2) // Entries were not updated after spell effect change, we have to do that manually :/ spellInfo->AttributesEx3 |= SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED; break; case 5308: // Execute spellInfo->AttributesEx3 |= SPELL_ATTR3_CANT_TRIGGER_PROC; break; - case 59725: // Improved Spell Reflection - aoe aura - // Target entry seems to be wrong for this spell :/ - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER_AREA_PARTY); - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS_2); - break; case 31347: // Doom case 36327: // Shoot Arcane Explosion Arrow case 39365: // Thundering Storm @@ -3140,8 +3133,6 @@ void SpellMgr::LoadSpellInfoCorrections() case 41376: // Spite case 45248: // Shadow Blades case 46771: // Flame Sear - case 54171: // Divine Storm - case 54172: // Divine Storm (heal) case 66588: // Flaming Spear spellInfo->MaxAffectedTargets = 3; break; @@ -3177,10 +3168,8 @@ void SpellMgr::LoadSpellInfoCorrections() case 17941: // Shadow Trance case 22008: // Netherwind Focus case 34477: // Misdirection - case 34936: // Backlash case 48108: // Hot Streak case 51124: // Killing Machine - case 54741: // Firestarter case 57761: // Fireball! case 64823: // Item - Druid T8 Balance 4P Bonus case 88819: // Daybreak @@ -3189,21 +3178,9 @@ void SpellMgr::LoadSpellInfoCorrections() case 44544: // Fingers of Frost const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(685904631, 1151048, 0, 0); break; - case 74396: // Fingers of Frost visual buff - spellInfo->ProcCharges = 2; - spellInfo->StackAmount = 0; - break; case 28200: // Ascendance (Talisman of Ascendance trinket) spellInfo->ProcCharges = 6; break; - case 47201: // Everlasting Affliction (1) - case 47202: // Everlasting Affliction (2) - case 47203: // Everlasting Affliction (3) - case 47204: // Everlasting Affliction (4) - case 47205: // Everlasting Affliction (5) - // add corruption to affected spells - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->SpellClassMask[0] |= 2; - break; case 37408: // Oscillation Field spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS; break; @@ -3213,32 +3190,6 @@ void SpellMgr::LoadSpellInfoCorrections() case 51912: // Crafty's Ultra-Advanced Proto-Typical Shortening Blaster const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraPeriod = 3000; break; - // Master Shapeshifter: missing stance data for forms other than bear - bear version has correct data - // To prevent aura staying on target after talent unlearned - case 48420: // Master Shapeshifter - case 24900: // Heart of the Wild - Cat Effect - spellInfo->Stances = 1 << (FORM_CAT - 1); - break; - case 24899: // Heart of the Wild - Bear Effect - spellInfo->Stances = 1 << (FORM_BEAR - 1); - break; - case 48421: // Master Shapeshifter - spellInfo->Stances = 1 << (FORM_MOONKIN - 1); - break; - case 51466: // Elemental Oath (Rank 1) - case 51470: // Elemental Oath (Rank 2) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->Effect = SPELL_EFFECT_APPLY_AURA; - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->MiscValue = SPELLMOD_EFFECT2; - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->SpellClassMask = flag128(0x00000000, 0x00004000, 0x00000000, 0x00000000); - break; - case 47569: // Improved Shadowform (Rank 1) - // with this spell atrribute aura can be stacked several times - spellInfo->Attributes &= ~SPELL_ATTR0_NOT_SHAPESHIFT; - break; - case 64904: // Hymn of Hope - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->ApplyAuraName = SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT; - break; case 30421: // Nether Portal - Perseverence const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_2))->BasePoints += 30000; break; @@ -3260,20 +3211,10 @@ void SpellMgr::LoadSpellInfoCorrections() const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY); const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY); break; - case 63675: // Improved Devouring Plague - spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS; - break; - case 12721: // Deep Wounds shouldnt ignore resillience or damage taken auras because its damage is not based off a spell. - spellInfo->AttributesEx4 = 0; - break; case 8145: // Tremor Totem (instant pulse) case 6474: // Earthbind Totem (instant pulse) spellInfo->AttributesEx5 |= SPELL_ATTR5_START_PERIODIC_AT_APPLY; break; - case 53241: // Marked for Death (Rank 1) - case 53243: // Marked for Death (Rank 2) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x00067801, 0x10820001, 0x00000801, 0x00000000); - break; case 5176: // Wrath case 2912: // Starfire //case 78674: // Starsurge 6.x effect 1 is no more @@ -3285,32 +3226,6 @@ void SpellMgr::LoadSpellInfoCorrections() const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_PET); break; - case 70893: // Culling The Herd (needs target selection script) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_MASTER); - break; - case 54800: // Sigil of the Frozen Conscience - change class mask to custom extended flags of Icy Touch - // this is done because another spell also uses the same SpellFamilyFlags as Icy Touch - // SpellFamilyFlags[0] & 0x00000040 in SPELLFAMILY_DEATHKNIGHT is currently unused (3.3.5a) - // this needs research on modifier applying rules, does not seem to be in Attributes fields - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x00000040, 0x00000000, 0x00000000, 0x00000000); - break; - case 64949: // Idol of the Flourishing Life - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x00000000, 0x02000000, 0x00000000, 0x00000000); - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; - break; - case 34231: // Libram of the Lightbringer - case 60792: // Libram of Tolerance - case 64956: // Libram of the Resolute - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x80000000, 0x00000000, 0x00000000, 0x00000000); - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; - break; - case 28851: // Libram of Light - case 28853: // Libram of Divinity - case 32403: // Blessed Book of Nagrand - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x40000000, 0x00000000, 0x00000000, 0x00000000); - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; - break; case 45602: // Ride Carpet const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->BasePoints = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)" break; @@ -3321,9 +3236,6 @@ void SpellMgr::LoadSpellInfoCorrections() case 71839: // Drain Life - Bryntroll Heroic spellInfo->AttributesEx2 |= SPELL_ATTR2_CANT_CRIT; break; - case 34471: // The Beast Within - spellInfo->AttributesEx5 |= SPELL_ATTR5_USABLE_WHILE_CONFUSED | SPELL_ATTR5_USABLE_WHILE_FEARED | SPELL_ATTR5_USABLE_WHILE_STUNNED; - break; case 56606: // Ride Jokkum case 61791: // Ride Vehicle (Yogg-Saron) /// @todo: remove this when basepoints of all Ride Vehicle auras are calculated correctly @@ -3348,7 +3260,6 @@ void SpellMgr::LoadSpellInfoCorrections() case 63342: // Focused Eyebeam Summon Trigger (Kologarn) spellInfo->MaxAffectedTargets = 1; break; - case 62716: // Growth of Nature (Freya) case 65584: // Growth of Nature (Freya) case 64381: // Strength of the Pack (Auriaya) spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS; @@ -3420,29 +3331,13 @@ void SpellMgr::LoadSpellInfoCorrections() // // TRIAL OF THE CRUSADER SPELLS // - case 66258: // Infernal Eruption (10N) - case 67901: // Infernal Eruption (25N) + case 66258: // Infernal Eruption // increase duration from 15 to 18 seconds because caster is already // unsummoned when spell missile hits the ground so nothing happen in result spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(85); break; // ENDOF TRIAL OF THE CRUSADER SPELLS // - // HALLS OF REFLECTION SPELLS - // - case 72435: // Defiling Horror - case 72452: // Defiling Horror - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd - break; - case 72830: // Achievement Check - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - break; - case 72900: // Start Halls of Reflection Quest AE - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - break; - // ENDOF HALLS OF REFLECTION SPELLS - // // ICECROWN CITADEL SPELLS // // THESE SPELLS ARE WORKING CORRECTLY EVEN WITHOUT THIS HACK @@ -3457,39 +3352,12 @@ void SpellMgr::LoadSpellInfoCorrections() case 70861: // Sindragosa's Lair Teleport const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB); break; - case 69075: // Bone Storm (Lord Marrowgar) - case 70834: // Bone Storm (Lord Marrowgar) - case 70835: // Bone Storm (Lord Marrowgar) - case 70836: // Bone Storm (Lord Marrowgar) - case 72864: // Death Plague (Rotting Frost Giant) - case 71160: // Plague Stench (Stinky) - case 71161: // Plague Stench (Stinky) - case 71123: // Decimate (Stinky & Precious) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd - break; case 71169: // Shadow's Fate spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS; break; case 72347: // Lock Players and Tap Chest spellInfo->AttributesEx3 &= ~SPELL_ATTR3_NO_INITIAL_AGGRO; break; - case 73843: // Award Reputation - Boss Kill - case 73844: // Award Reputation - Boss Kill - case 73845: // Award Reputation - Boss Kill - case 73846: // Award Reputation - Boss Kill - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - break; - case 72378: // Blood Nova (Deathbringer Saurfang) - case 73058: // Blood Nova (Deathbringer Saurfang) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); - break; - case 72769: // Scent of Blood (Deathbringer Saurfang) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); - // no break - case 72771: // Scent of Blood (Deathbringer Saurfang) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); - break; case 72723: // Resistant Skin (Deathbringer Saurfang adds) // this spell initially granted Shadow damage immunity, however it was removed but the data was left in client const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_2))->Effect = 0; @@ -3509,36 +3377,15 @@ void SpellMgr::LoadSpellInfoCorrections() break; // THIS IS HERE BECAUSE COOLDOWN ON CREATURE PROCS IS NOT IMPLEMENTED case 71604: // Mutated Strength (Professor Putricide) - case 72673: // Mutated Strength (Professor Putricide) - case 72674: // Mutated Strength (Professor Putricide) - case 72675: // Mutated Strength (Professor Putricide) const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->Effect = 0; break; - case 72454: // Mutated Plague (Professor Putricide) - case 72464: // Mutated Plague (Professor Putricide) - case 72506: // Mutated Plague (Professor Putricide) - case 72507: // Mutated Plague (Professor Putricide) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - break; case 70911: // Unbound Plague (Professor Putricide) (needs target selection script) - case 72854: // Unbound Plague (Professor Putricide) (needs target selection script) - case 72855: // Unbound Plague (Professor Putricide) (needs target selection script) - case 72856: // Unbound Plague (Professor Putricide) (needs target selection script) const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY); break; - case 71518: // Unholy Infusion Quest Credit (Professor Putricide) - case 72934: // Blood Infusion Quest Credit (Blood-Queen Lana'thel) - case 72289: // Frost Infusion Quest Credit (Sindragosa) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // another missing radius - break; case 71708: // Empowered Flare (Blood Prince Council) - case 72785: // Empowered Flare (Blood Prince Council) - case 72786: // Empowered Flare (Blood Prince Council) - case 72787: // Empowered Flare (Blood Prince Council) spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS; break; case 71266: // Swarming Shadows - case 72890: // Swarming Shadows spellInfo->RequiredAreasID = 0; // originally, these require area 4522, which is... outside of Icecrown Citadel break; case 70602: // Corruption @@ -3551,18 +3398,10 @@ void SpellMgr::LoadSpellInfoCorrections() case 71085: // Mana Void (periodic aura) spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(9); // 30 seconds (missing) break; - case 72015: // Frostbolt Volley (only heroic) - case 72016: // Frostbolt Volley (only heroic) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_2))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_40_YARDS); - break; case 70936: // Summon Suppressor (needs target selection script) const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(); break; - case 72706: // Achievement Check (Valithria Dreamwalker) - case 71357: // Order Whelp - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - break; case 70598: // Sindragosa's Fury const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DEST); break; @@ -3579,27 +3418,12 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(22); // 45 seconds break; case 72754: // Defile - case 73708: // Defile - case 73709: // Defile - case 73710: // Defile - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - break; - case 69030: // Val'kyr Target Search const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; case 69198: // Raging Spirit Visual spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13); // 50000yd break; - case 73654: // Harvest Souls - case 74295: // Harvest Souls - case 74296: // Harvest Souls - case 74297: // Harvest Souls - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_2))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - break; case 73655: // Harvest Soul spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS; break; @@ -3609,47 +3433,14 @@ void SpellMgr::LoadSpellInfoCorrections() case 73530: // Shadow Trap (visual) spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(28); // 5 seconds break; - case 73529: // Shadow Trap - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS); // 10yd - break; - case 74282: // Shadow Trap (searcher) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); // 3yd - break; - case 72595: // Restore Soul - case 73650: // Restore Soul - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - break; - case 74086: // Destroy Soul - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - break; case 74302: // Summon Spirit Bomb - case 74342: // Summon Spirit Bomb - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - spellInfo->MaxAffectedTargets = 1; - break; - case 74341: // Summon Spirit Bomb - case 74343: // Summon Spirit Bomb - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - spellInfo->MaxAffectedTargets = 3; + spellInfo->MaxAffectedTargets = 2; break; case 73579: // Summon Spirit Bomb const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd break; - case 72350: // Fury of Frostmourne - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - break; - case 75127: // Kill Frostmourne Players - case 72351: // Fury of Frostmourne - case 72431: // Jump (removes Fury of Frostmourne debuff) - case 72429: // Mass Resurrection - case 73159: // Play Movie - case 73582: // Trigger Vile Spirit (Inside, Heroic) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - break; case 72376: // Raise Dead spellInfo->MaxAffectedTargets = 3; - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 71809: // Jump spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(3); // 20yd @@ -3665,18 +3456,11 @@ void SpellMgr::LoadSpellInfoCorrections() case 74799: // Soul Consumption const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_12_YARDS); break; - case 74769: // Twilight Cutter - case 77844: // Twilight Cutter - case 77845: // Twilight Cutter - case 77846: // Twilight Cutter - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd - break; case 75509: // Twilight Mending spellInfo->AttributesEx6 |= SPELL_ATTR6_CAN_TARGET_INVISIBLE; spellInfo->AttributesEx2 |= SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS; break; case 75888: // Awaken Flames - case 75889: // Awaken Flames spellInfo->AttributesEx |= SPELL_ATTR1_CANT_TARGET_SELF; break; // ENDOF RUBY SANCTUM SPELLS @@ -3737,7 +3521,6 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AttributesEx4 &= ~SPELL_ATTR4_CAN_CAST_WHILE_CASTING; break; case 96942: // Gaze of Occu'thar - case 101009: // Gaze of Occu'thar spellInfo->AttributesEx &= ~SPELL_ATTR1_CHANNELED_1; break; case 75610: // Evolution @@ -3756,20 +3539,6 @@ void SpellMgr::LoadSpellInfoCorrections() default: break; } - - switch (spellInfo->SpellFamilyName) - { - case SPELLFAMILY_PALADIN: - // Seals of the Pure should affect Seal of Righteousness - if (spellInfo->SpellIconID == 25 && spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE)) - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask[1] |= 0x20000000; - break; - case SPELLFAMILY_DEATHKNIGHT: - // Icy Touch - extend FamilyFlags (unused value) for Sigil of the Frozen Conscience to use - if (spellInfo->SpellIconID == 2721 && spellInfo->SpellFamilyFlags[0] & 0x2) - spellInfo->SpellFamilyFlags[0] |= 0x40; - break; - } } if (SummonPropertiesEntry* properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(121))) diff --git a/src/server/game/Support/SupportMgr.cpp b/src/server/game/Support/SupportMgr.cpp index 43be35de7e2..90afcfd1511 100644 --- a/src/server/game/Support/SupportMgr.cpp +++ b/src/server/game/Support/SupportMgr.cpp @@ -50,36 +50,29 @@ std::string Ticket::FormatViewMessageString(ChatHandler& handler, char const* cl return ss.str(); } -GmTicket::GmTicket() : _lastModifiedTime(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needResponse(false), _needMoreHelp(false) { } +GmTicket::GmTicket() : _lastModifiedTime(0), _completed(false), _assignedToStatus(GMTICKET_ASSIGNEDTOGM_STATUS_NOT_ASSIGNED), +_openedByGmStatus(GMTICKET_OPENEDBYGM_STATUS_NOT_OPENED), _needResponse(false), _needMoreHelp(false) { } -GmTicket::GmTicket(Player* player) : Ticket(player), _lastModifiedTime(time(nullptr)), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), -_viewed(false), _needResponse(false), _needMoreHelp(false) +GmTicket::GmTicket(Player* player) : Ticket(player), _lastModifiedTime(time(nullptr)), _completed(false), _assignedToStatus(GMTICKET_ASSIGNEDTOGM_STATUS_NOT_ASSIGNED), +_openedByGmStatus(GMTICKET_OPENEDBYGM_STATUS_NOT_OPENED), _needResponse(false), _needMoreHelp(false) { _id = sSupportMgr->GenerateGmTicketId(); } GmTicket::~GmTicket() { } -void GmTicket::SetGmAction(uint32 needResponse, bool needMoreHelp) +void GmTicket::SetGmAction(bool needResponse, bool needMoreHelp) { - _needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default) + _needResponse = needResponse; // Requires GM response. 17 = true, 1 = false (17 is default) _needMoreHelp = needMoreHelp; // Requests further GM interaction on a ticket to which a GM has already responded. Basically means "has a new ticket" } void GmTicket::SetUnassigned() { + if (_assignedToStatus != GMTICKET_ASSIGNEDTOGM_STATUS_ESCALATED) + _assignedToStatus = GMTICKET_ASSIGNEDTOGM_STATUS_NOT_ASSIGNED; + _assignedTo.Clear(); - switch (_escalatedStatus) - { - case TICKET_ASSIGNED: _escalatedStatus = TICKET_UNASSIGNED; - break; - case TICKET_ESCALATED_ASSIGNED: _escalatedStatus = TICKET_IN_ESCALATION_QUEUE; - break; - case TICKET_UNASSIGNED: - case TICKET_IN_ESCALATION_QUEUE: - default: - break; - } } void GmTicket::SetChatLog(std::list<uint32> time, std::string const& log) @@ -137,8 +130,8 @@ void GmTicket::LoadFromDB(Field* fields) _comment = fields[++idx].GetString(); _response = fields[++idx].GetString(); _completed = fields[++idx].GetBool(); - _escalatedStatus = GMTicketEscalationStatus(fields[++idx].GetUInt8()); - _viewed = fields[++idx].GetBool(); + _assignedToStatus = GMTicketAssignedToGMStatus(fields[++idx].GetUInt8()); + _openedByGmStatus = GMTicketOpenedByGMStatus(fields[++idx].GetUInt8()); _needMoreHelp = fields[++idx].GetBool(); } @@ -160,8 +153,8 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const stmt->setString(++idx, _comment); stmt->setString(++idx, _response); stmt->setBool(++idx, _completed); - stmt->setUInt8(++idx, uint8(_escalatedStatus)); - stmt->setBool(++idx, _viewed); + stmt->setUInt8(++idx, uint8(_assignedToStatus)); + stmt->setUInt8(++idx, _openedByGmStatus); stmt->setBool(++idx, _needMoreHelp); CharacterDatabase.ExecuteOrAppend(trans, stmt); @@ -329,7 +322,7 @@ void ComplaintTicket::LoadFromDB(Field* fields) _complaintType = GMSupportComplaintType(fields[++idx].GetUInt8()); int32 reportLineIndex = fields[++idx].GetInt32(); if (reportLineIndex != -1) - _chatLog.ReportLineIndex.Set(reportLineIndex); + _chatLog.ReportLineIndex = reportLineIndex; int64 closedBy = fields[++idx].GetInt64(); if (closedBy == 0) @@ -371,8 +364,8 @@ void ComplaintTicket::SaveToDB(SQLTransaction& trans) const stmt->setFloat(++idx, _facing); stmt->setUInt64(++idx, _targetCharacterGuid.GetCounter()); stmt->setUInt8(++idx, _complaintType); - if (_chatLog.ReportLineIndex.HasValue) - stmt->setInt32(++idx, _chatLog.ReportLineIndex.Value); + if (_chatLog.ReportLineIndex) + stmt->setInt32(++idx, *_chatLog.ReportLineIndex); else stmt->setInt32(++idx, -1); // empty ReportLineIndex stmt->setInt64(++idx, _closedBy.GetCounter()); @@ -1052,7 +1045,7 @@ void SupportMgr::ShowGmEscalatedList(ChatHandler& handler) const { handler.SendSysMessage(LANG_COMMAND_TICKETSHOWESCALATEDLIST); for (GmTicketList::const_iterator itr = _gmTicketList.begin(); itr != _gmTicketList.end(); ++itr) - if (!itr->second->IsClosed() && itr->second->GetEscalatedStatus() == TICKET_IN_ESCALATION_QUEUE) + if (!itr->second->IsClosed() && itr->second->GetAssigendToStatus() == GMTICKET_ASSIGNEDTOGM_STATUS_ESCALATED) handler.SendSysMessage(itr->second->FormatViewMessageString(handler).c_str()); } @@ -1063,18 +1056,18 @@ void SupportMgr::SendGmTicket(WorldSession* session, GmTicket* ticket) const if (ticket) { response.Result = GMTICKET_STATUS_HASTEXT; - response.Info.HasValue = true; - - response.Info.Value.TicketID = ticket->GetId(); - response.Info.Value.TicketDescription = ticket->GetDescription(); - response.Info.Value.Category = ticket->GetEscalatedStatus(); - response.Info.Value.TicketOpenTime = GetAge(ticket->GetLastModifiedTime()); - response.Info.Value.OldestTicketTime = sSupportMgr->GetOldestOpenTicket() ? GetAge(sSupportMgr->GetOldestOpenTicket()->GetLastModifiedTime()) : float(0); - response.Info.Value.UpdateTime = GetAge(sSupportMgr->GetLastChange()); - response.Info.Value.AssignedToGM = ticket->IsAssigned(); - response.Info.Value.OpenedByGM = ticket->IsViewed(); - response.Info.Value.WaitTimeOverrideMessage = ""; - response.Info.Value.WaitTimeOverrideMinutes = 0; + response.Info = boost::in_place(); + + response.Info->TicketID = ticket->GetId(); + response.Info->TicketDescription = ticket->GetDescription(); + response.Info->Category = 1; + response.Info->TicketOpenTime = GetAge(ticket->GetLastModifiedTime()); + response.Info->OldestTicketTime = sSupportMgr->GetOldestOpenTicket() ? GetAge(sSupportMgr->GetOldestOpenTicket()->GetLastModifiedTime()) : float(0); + response.Info->UpdateTime = GetAge(sSupportMgr->GetLastChange()); + response.Info->AssignedToGM = ticket->GetAssigendToStatus(); + response.Info->OpenedByGM = ticket->GetOpenedByGmStatus(); + response.Info->WaitTimeOverrideMessage = ""; + response.Info->WaitTimeOverrideMinutes = 0; } else response.Result = GMTICKET_STATUS_DEFAULT; diff --git a/src/server/game/Support/SupportMgr.h b/src/server/game/Support/SupportMgr.h index b3a7b2e24f0..e0adb411aa0 100644 --- a/src/server/game/Support/SupportMgr.h +++ b/src/server/game/Support/SupportMgr.h @@ -59,12 +59,11 @@ enum GMTicketOpenedByGMStatus // GMTICKET_ASSIGNEDTOGM_STATUS_ASSIGNED = 1; -- ticket is assigned to a normal gm // GMTICKET_ASSIGNEDTOGM_STATUS_ESCALATED = 2; -- ticket is in the escalation queue // 3 is a custom value and should never actually be sent -enum GMTicketEscalationStatus +enum GMTicketAssignedToGMStatus { - TICKET_UNASSIGNED = 0, - TICKET_ASSIGNED = 1, - TICKET_IN_ESCALATION_QUEUE = 2, - TICKET_ESCALATED_ASSIGNED = 3 + GMTICKET_ASSIGNEDTOGM_STATUS_NOT_ASSIGNED = 0, + GMTICKET_ASSIGNEDTOGM_STATUS_ASSIGNED = 1, + GMTICKET_ASSIGNEDTOGM_STATUS_ESCALATED = 2 }; enum GMSupportComplaintType @@ -107,8 +106,7 @@ public: } std::string const& GetComment() { return _comment; } - virtual void SetAssignedTo(ObjectGuid guid) { _assignedTo = guid; } - virtual void SetAssignedTo(ObjectGuid /*guid*/, bool /*isAdmin*/) { } + virtual void SetAssignedTo(ObjectGuid guid, bool /*isAdmin*/ = false) { _assignedTo = guid; } virtual void SetUnassigned() { _assignedTo.Clear(); } void SetClosedBy(ObjectGuid value) { _closedBy = value; } void SetComment(std::string const& comment) { _comment = comment; } @@ -147,31 +145,32 @@ public: ~GmTicket(); bool IsCompleted() const { return _completed; } - bool IsViewed() const { return _viewed; } + GMTicketOpenedByGMStatus GetOpenedByGmStatus() const { return _openedByGmStatus; } bool GetNeedMoreHelp() const { return _needMoreHelp; } std::string const& GetDescription() const { return _description; } uint64 GetLastModifiedTime() const { return _lastModifiedTime; } - GMTicketEscalationStatus GetEscalatedStatus() const { return _escalatedStatus; } + uint8 GetCategory() const { return _category; } + GMTicketAssignedToGMStatus GetAssigendToStatus() const { return _assignedToStatus; } std::string const& GetResponse() const { return _response; } - void SetAssignedTo(ObjectGuid guid, bool isAdmin) override + void SetAssignedTo(ObjectGuid guid, bool isAdmin = false) override { _assignedTo = guid; - if (isAdmin && _escalatedStatus == TICKET_IN_ESCALATION_QUEUE) - _escalatedStatus = TICKET_ESCALATED_ASSIGNED; - else if (_escalatedStatus == TICKET_UNASSIGNED) - _escalatedStatus = TICKET_ASSIGNED; + if (isAdmin) + _assignedToStatus = GMTICKET_ASSIGNEDTOGM_STATUS_ESCALATED; + else if (_assignedToStatus == GMTICKET_ASSIGNEDTOGM_STATUS_NOT_ASSIGNED) + _assignedToStatus = GMTICKET_ASSIGNEDTOGM_STATUS_ASSIGNED; } - void SetEscalatedStatus(GMTicketEscalationStatus escalatedStatus) { _escalatedStatus = escalatedStatus; } + void SetAssignedToStatus(GMTicketAssignedToGMStatus assignedToStatus) { _assignedToStatus = assignedToStatus; } void SetCompleted() { _completed = true; } void SetDescription(std::string const& description) { _description = description; _lastModifiedTime = uint64(time(NULL)); } - void SetViewed() { _viewed = true; } - void SetGmAction(uint32 needResponse, bool needMoreHelp); + void SetViewed() { _openedByGmStatus = GMTICKET_OPENEDBYGM_STATUS_OPENED; } + void SetGmAction(bool needResponse, bool needMoreHelp); void SetUnassigned() override; void AppendResponse(std::string const& response) { _response += response; } @@ -192,9 +191,10 @@ private: std::string _description; uint64 _lastModifiedTime; bool _completed; - GMTicketEscalationStatus _escalatedStatus; - bool _viewed; - bool _needResponse; /// @todo find out the use of this, and then store it in DB + uint8 _category; + GMTicketAssignedToGMStatus _assignedToStatus; + GMTicketOpenedByGMStatus _openedByGmStatus; + bool _needResponse; ///< true if we want a GM to contact us when we open a new ticket (Note: This flag is always true right now) bool _needMoreHelp; std::string _response; std::string _chatLog; // No need to store in db, will be refreshed every session client side diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index 5497f4cc0e3..71719c19b3a 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -417,19 +417,19 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; - if (guid && guid < sObjectMgr->GetGenerator<HighGuid::Player>()->GetNextAfterMaxUsed()) + if (guid && guid < sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed()) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_GUID); stmt->setUInt64(0, guid); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) - guid = sObjectMgr->GetGenerator<HighGuid::Player>()->GetNextAfterMaxUsed(); // use first free if exists + guid = sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed(); // use first free if exists else incHighest = false; } else - guid = sObjectMgr->GetGenerator<HighGuid::Player>()->GetNextAfterMaxUsed(); + guid = sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed(); // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) @@ -464,7 +464,7 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s uint8 playerClass = 0; uint8 level = 1; - ObjectGuid::LowType itemLowGuidOffset = sObjectMgr->GetGenerator<HighGuid::Item>()->GetNextAfterMaxUsed(); + ObjectGuid::LowType itemLowGuidOffset = sObjectMgr->GetGenerator<HighGuid::Item>().GetNextAfterMaxUsed(); SQLTransaction trans = CharacterDatabase.BeginTransaction(); while (!feof(fin)) @@ -683,11 +683,11 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s // in case of name conflict player has to rename at login anyway sWorld->AddCharacterInfo(ObjectGuid::Create<HighGuid::Player>(guid), name, gender, race, playerClass, level, false); - sObjectMgr->GetGenerator<HighGuid::Item>()->Set(sObjectMgr->GetGenerator<HighGuid::Item>()->GetNextAfterMaxUsed() + items.size()); + sObjectMgr->GetGenerator<HighGuid::Item>().Set(sObjectMgr->GetGenerator<HighGuid::Item>().GetNextAfterMaxUsed() + items.size()); sObjectMgr->_mailId += mails.size(); if (incHighest) - sObjectMgr->GetGenerator<HighGuid::Player>()->Generate(); + sObjectMgr->GetGenerator<HighGuid::Player>().Generate(); fclose(fin); diff --git a/src/server/game/Warden/Warden.h b/src/server/game/Warden/Warden.h index 4d46773adcd..695c6730b27 100644 --- a/src/server/game/Warden/Warden.h +++ b/src/server/game/Warden/Warden.h @@ -57,11 +57,7 @@ enum WardenCheckType MODULE_CHECK = 0xD9 // 217: uint Seed + byte[20] SHA1 (check to ensure module isn't injected) }; -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif struct WardenModuleUse { @@ -84,11 +80,7 @@ struct WardenHashRequest uint8 Seed[16]; }; -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif struct ClientWardenModule { diff --git a/src/server/game/Warden/WardenWin.h b/src/server/game/Warden/WardenWin.h index 31d28b22e23..ab6ef7c8c65 100644 --- a/src/server/game/Warden/WardenWin.h +++ b/src/server/game/Warden/WardenWin.h @@ -25,11 +25,7 @@ #include "ByteBuffer.h" #include "Warden.h" -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif struct WardenInitModuleRequest { @@ -61,11 +57,7 @@ struct WardenInitModuleRequest uint8 Function3_set; }; -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif class WorldSession; class Warden; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index cdbb15bf539..9b8c63000fc 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -38,6 +38,7 @@ #include "DatabaseEnv.h" #include "DisableMgr.h" #include "GameEventMgr.h" +#include "GarrisonMgr.h" #include "GridNotifiersImpl.h" #include "GroupMgr.h" #include "GuildFinderMgr.h" @@ -66,6 +67,7 @@ #include "WeatherMgr.h" #include "WorldSession.h" #include "ChatPackets.h" +#include "WorldSocket.h" #include <boost/algorithm/string.hpp> @@ -223,6 +225,11 @@ void World::AddSession(WorldSession* s) addSessQueue.add(s); } +void World::AddInstanceSocket(std::shared_ptr<WorldSocket> sock, uint32 sessionAccountId) +{ + _linkSocketQueue.add(std::make_pair(sock, sessionAccountId)); +} + void World::AddSession_(WorldSession* s) { ASSERT(s); @@ -296,6 +303,21 @@ void World::AddSession_(WorldSession* s) } } +void World::ProcessLinkInstanceSocket(std::pair<std::shared_ptr<WorldSocket>, uint32> linkInfo) +{ + WorldSession* session = FindSession(linkInfo.second); + if (!session) + { + linkInfo.first->SendAuthResponseError(AUTH_SESSION_EXPIRED); + linkInfo.first->DelayedCloseSocket(); + return; + } + + linkInfo.first->SetWorldSession(session); + session->AddInstanceConnection(linkInfo.first); + session->HandleContinuePlayerLogin(); +} + bool World::HasRecentlyDisconnected(WorldSession* session) { if (!session) @@ -1455,15 +1477,6 @@ void World::SetInitialWorldSettings() LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmHandle.Index); // One-time query - ///- Remove the bones (they should not exist in DB though) and old corpses after a restart - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_CORPSES); - stmt->setUInt32(0, 3 * DAY); - CharacterDatabase.Execute(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_CORPSE_PHASES); - stmt->setUInt32(0, 3 * DAY); - CharacterDatabase.Execute(stmt); - ///- Load the DBC files TC_LOG_INFO("server.loading", "Initialize data stores..."); LoadDBCStores(m_dataPath); @@ -1508,7 +1521,6 @@ void World::SetInitialWorldSettings() sObjectMgr->LoadGameObjectLocales(); sObjectMgr->LoadQuestTemplateLocale(); sObjectMgr->LoadQuestObjectivesLocale(); - sObjectMgr->LoadQuestGreetings(); sObjectMgr->LoadPageTextLocales(); sObjectMgr->LoadGossipMenuItemsLocales(); sObjectMgr->LoadPointOfInterestLocales(); @@ -1648,6 +1660,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Quests Starters and Enders..."); sObjectMgr->LoadQuestStartersAndEnders(); // must be after quest load + TC_LOG_INFO("server.loading", "Loading Quest Greetings..."); + sObjectMgr->LoadQuestGreetings(); + TC_LOG_INFO("server.loading", "Loading Objects Pooling Data..."); sPoolMgr->LoadFromDB(); @@ -1722,9 +1737,6 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading pet level stats..."); sObjectMgr->LoadPetLevelInfo(); - TC_LOG_INFO("server.loading", "Loading Player Corpses..."); - sObjectMgr->LoadCorpses(); - TC_LOG_INFO("server.loading", "Loading Player level dependent mail rewards..."); sObjectMgr->LoadMailLevelRewards(); @@ -1860,6 +1872,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading client addons..."); AddonMgr::LoadFromDB(); + TC_LOG_INFO("server.loading", "Loading garrison info..."); + sGarrisonMgr.Initialize(); + ///- Handle outdated emails (delete/return) TC_LOG_INFO("server.loading", "Returning old mails..."); sObjectMgr->ReturnOrDeleteOldMails(false); @@ -2007,6 +2022,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading race and class expansion requirements..."); sObjectMgr->LoadRaceAndClassExpansionRequirements(); + TC_LOG_INFO("server.loading", "Loading character templates..."); + sObjectMgr->LoadCharacterTemplates(); + TC_LOG_INFO("server.loading", "Loading realm names..."); sObjectMgr->LoadRealmNames(); @@ -2109,7 +2127,7 @@ void World::Update(uint32 diff) /// Handle daily quests reset time if (m_gameTime > m_NextDailyQuestReset) { - ResetDailyQuests(); + DailyReset(); m_NextDailyQuestReset += DAY; } @@ -2735,7 +2753,7 @@ void World::ShutdownMsg(bool show, Player* player, const std::string& reason) ServerMessageType msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_TIME : SERVER_MSG_SHUTDOWN_TIME; - SendServerMessage(msgid, str.c_str(), player); + SendServerMessage(msgid, str, player); TC_LOG_DEBUG("misc", "Server is %s in %s", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"), str.c_str()); } } @@ -2760,21 +2778,25 @@ void World::ShutdownCancel() } /// Send a server message to the user(s) -void World::SendServerMessage(ServerMessageType type, const char *text, Player* player) +void World::SendServerMessage(ServerMessageType messageID, std::string stringParam /*= ""*/, Player* player /*= NULL*/) { - WorldPacket data(SMSG_CHAT_SERVER_MESSAGE, 50); // guess size - data << uint32(type); - if (type <= SERVER_MSG_STRING) - data << text; + WorldPackets::Chat::ChatServerMessage chatServerMessage; + chatServerMessage.MessageID = int32(messageID); + if (messageID <= SERVER_MSG_STRING) + chatServerMessage.StringParam = stringParam; if (player) - player->GetSession()->SendPacket(&data); + player->GetSession()->SendPacket(chatServerMessage.Write()); else - SendGlobalMessage(&data); + SendGlobalMessage(chatServerMessage.Write()); } void World::UpdateSessions(uint32 diff) { + std::pair<std::shared_ptr<WorldSocket>, uint32> linkInfo; + while (_linkSocketQueue.next(linkInfo)) + ProcessLinkInstanceSocket(std::move(linkInfo)); + ///- Add new sessions WorldSession* sess = NULL; while (addSessQueue.next(sess)) @@ -3034,16 +3056,20 @@ void World::InitCurrencyResetTime() sWorld->setWorldState(WS_CURRENCY_RESET_TIME, uint64(m_NextCurrencyReset)); } -void World::ResetDailyQuests() +void World::DailyReset() { TC_LOG_INFO("misc", "Daily quests reset for all characters."); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY); CharacterDatabase.Execute(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS); + stmt->setUInt32(0, 1); + CharacterDatabase.Execute(stmt); + for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) if (itr->second->GetPlayer()) - itr->second->GetPlayer()->ResetDailyQuestStatus(); + itr->second->GetPlayer()->DailyReset(); // change available dailies sPoolMgr->ChangeDailyQuests(); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 78243b19374..b169431f2fd 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -575,6 +575,7 @@ class World WorldSession* FindSession(uint32 id) const; void AddSession(WorldSession* s); + void AddInstanceSocket(std::shared_ptr<WorldSocket> sock, uint32 sessionAccountId); void SendAutoBroadcast(); bool RemoveSession(uint32 id); /// Get the number of current active sessions @@ -670,7 +671,7 @@ class World void SendWorldText(uint32 string_id, ...); void SendGlobalText(const char* text, WorldSession* self); void SendGMText(uint32 string_id, ...); - void SendServerMessage(ServerMessageType type, const char *text = "", Player* player = NULL); + void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = NULL); void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0); void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0); bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0); @@ -804,7 +805,7 @@ class World void InitRandomBGResetTime(); void InitGuildResetTime(); void InitCurrencyResetTime(); - void ResetDailyQuests(); + void DailyReset(); void ResetWeeklyQuests(); void ResetMonthlyQuests(); void ResetRandomBG(); @@ -883,6 +884,9 @@ class World void AddSession_(WorldSession* s); LockedQueue<WorldSession*> addSessQueue; + void ProcessLinkInstanceSocket(std::pair<std::shared_ptr<WorldSocket>, uint32> linkInfo); + LockedQueue<std::pair<std::shared_ptr<WorldSocket>, uint32>> _linkSocketQueue; + // used versions std::string m_DBVersion; diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index bfc61ad9f78..ecd98595723 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -504,7 +504,7 @@ public: return false; handler->PSendSysMessage("Loot recipient for creature %s (%s, DB GUID " UI64FMTD ") is %s", - target->GetName().c_str(), target->GetGUID().ToString().c_str(), target->GetDBTableGUIDLow(), + target->GetName().c_str(), target->GetGUID().ToString().c_str(), target->GetSpawnId(), target->hasLootRecipient() ? (target->GetLootRecipient() ? target->GetLootRecipient()->GetName().c_str() : "offline") : "no loot recipient"); return true; } @@ -931,7 +931,7 @@ public: Map* map = handler->GetSession()->GetPlayer()->GetMap(); - if (!v->Create(sObjectMgr->GetGenerator<HighGuid::Vehicle>()->Generate(), map, handler->GetSession()->GetPlayer()->GetPhaseMask(), entry, x, y, z, o, nullptr, id)) + if (!v->Create(map->GenerateLowGuid<HighGuid::Vehicle>(), map, handler->GetSession()->GetPlayer()->GetPhaseMask(), entry, x, y, z, o, nullptr, id)) { delete v; return false; diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index cae6765ad3e..53522736718 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -44,6 +44,7 @@ public: { "graveyard", rbac::RBAC_PERM_COMMAND_GO_GRAVEYARD, false, &HandleGoGraveyardCommand, "", NULL }, { "grid", rbac::RBAC_PERM_COMMAND_GO_GRID, false, &HandleGoGridCommand, "", NULL }, { "object", rbac::RBAC_PERM_COMMAND_GO_OBJECT, false, &HandleGoObjectCommand, "", NULL }, + { "quest", rbac::RBAC_PERM_COMMAND_GO_QUEST, false, &HandleGoQuestCommand, "", NULL }, { "taxinode", rbac::RBAC_PERM_COMMAND_GO_TAXINODE, false, &HandleGoTaxinodeCommand, "", NULL }, { "trigger", rbac::RBAC_PERM_COMMAND_GO_TRIGGER, false, &HandleGoTriggerCommand, "", NULL }, { "zonexy", rbac::RBAC_PERM_COMMAND_GO_ZONEXY, false, &HandleGoZoneXYCommand, "", NULL }, @@ -143,16 +144,6 @@ public: Transport* transport = NULL; - if (Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid::Create<HighGuid::Creature>(mapId, id, guid), (Creature*)NULL)) - { - x = creature->GetPositionX(); - y = creature->GetPositionY(); - z = creature->GetPositionZ(); - o = creature->GetOrientation(); - mapId = creature->GetMapId(); - transport = creature->GetTransport(); - } - if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId)) { handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId); @@ -325,6 +316,71 @@ public: return true; } + static bool HandleGoQuestCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* player = handler->GetSession()->GetPlayer(); + + char* id = handler->extractKeyFromLink((char*)args, "Hquest"); + if (!id) + return false; + + uint32 questID = atoi(id); + if (!questID) + return false; + + if (!sObjectMgr->GetQuestTemplate(questID)) + { + handler->PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, questID); + handler->SetSentErrorMessage(true); + return false; + } + + float x, y, z; + uint32 mapId; + + if (QuestPOIVector const* poiData = sObjectMgr->GetQuestPOIVector(questID)) + { + auto data = poiData->front(); + + mapId = data.MapID; + + x = data.points.front().X; + y = data.points.front().Y; + } + else + { + handler->PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, questID); + handler->SetSentErrorMessage(true); + return false; + } + + if (!MapManager::IsValidMapCoord(mapId, x, y) || sObjectMgr->IsTransportMap(mapId)) + { + handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId); + handler->SetSentErrorMessage(true); + return false; + } + + // stop flight if need + if (player->IsInFlight()) + { + player->GetMotionMaster()->MovementExpired(); + player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + player->SaveRecallPosition(); + + Map const* map = sMapMgr->CreateBaseMap(mapId); + z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + + player->TeleportTo(mapId, x, y, z, 0.0f); + return true; + } + static bool HandleGoTaxinodeCommand(ChatHandler* handler, char const* args) { Player* player = handler->GetSession()->GetPlayer(); @@ -458,7 +514,7 @@ public: if (map->Instanceable()) { - handler->PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->ZoneName, map->GetId(), map->GetMapName()); + handler->PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->AreaName_lang, map->GetId(), map->GetMapName()); handler->SetSentErrorMessage(true); return false; } diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 7d356949d48..ef52f6ebd95 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -150,7 +150,7 @@ public: Map* map = player->GetMap(); GameObject* object = new GameObject; - ObjectGuid::LowType guidLow = sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(); + ObjectGuid::LowType guidLow = map->GenerateLowGuid<HighGuid::GameObject>(); if (!object->Create(guidLow, objectInfo->entry, map, 0, x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index ae7b2039e81..5e5694ba23a 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -354,7 +354,7 @@ public: { AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID); if (zone) - zoneName = zone->ZoneName; + zoneName = zone->AreaName_lang; } } else diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index d8f98e90275..4d1d484cb2f 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -106,7 +106,7 @@ public: AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(areaflag); if (areaEntry) { - std::string name = areaEntry->ZoneName; + std::string name = areaEntry->AreaName_lang; if (name.empty()) continue; diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index 519ae1e1f97..be3a027277c 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -134,9 +134,9 @@ public: if (!*args) return false; - char buff[2048]; - sprintf(buff, handler->GetTrinityString(LANG_SYSTEMMESSAGE), args); - sWorld->SendServerMessage(SERVER_MSG_STRING, buff); + std::string str = handler->PGetParseString(LANG_SYSTEMMESSAGE, args); + + sWorld->SendServerMessage(SERVER_MSG_STRING, str); return true; } // announce to logged in GMs diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 9e537e42d20..61df922452f 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -236,8 +236,8 @@ public: handler->PSendSysMessage(LANG_MAP_POSITION, mapId, (mapEntry ? mapEntry->MapName_lang : unknown), - zoneId, (zoneEntry ? zoneEntry->ZoneName : unknown), - areaId, (areaEntry ? areaEntry->ZoneName : unknown), + zoneId, (zoneEntry ? zoneEntry->AreaName_lang : unknown), + areaId, (areaEntry ? areaEntry->AreaName_lang : unknown), object->GetPhaseMask(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation()); handler->PSendSysMessage(LANG_GRID_POSITION, @@ -1762,11 +1762,11 @@ public: AreaTableEntry const* area = GetAreaEntryByAreaID(areaId); if (area) { - areaName = area->ZoneName; + areaName = area->AreaName_lang; AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID); if (zone) - zoneName = zone->ZoneName; + zoneName = zone->AreaName_lang; } if (target) diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index 48a514fd0db..3bcb6862b7f 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -313,7 +313,7 @@ public: { uint32 factionid = target->getFaction(); uint32 flag = target->GetUInt32Value(UNIT_FIELD_FLAGS); - uint32 npcflag = target->GetUInt32Value(UNIT_NPC_FLAGS); + uint64 npcflag = target->GetUInt64Value(UNIT_NPC_FLAGS); uint32 dyflag = target->GetUInt32Value(OBJECT_DYNAMIC_FLAGS); handler->PSendSysMessage(LANG_CURRENT_FACTION, target->GetGUID().ToString().c_str(), factionid, flag, npcflag, dyflag); return true; @@ -330,11 +330,11 @@ public: char* pnpcflag = strtok(NULL, " "); - uint32 npcflag; + uint64 npcflag; if (!pnpcflag) - npcflag = target->GetUInt32Value(UNIT_NPC_FLAGS); + npcflag = target->GetUInt64Value(UNIT_NPC_FLAGS); else - npcflag = atoi(pnpcflag); + npcflag = std::strtoull(pnpcflag, nullptr, 10); char* pdyflag = strtok(NULL, " "); @@ -355,7 +355,7 @@ public: target->setFaction(factionid); target->SetUInt32Value(UNIT_FIELD_FLAGS, flag); - target->SetUInt32Value(UNIT_NPC_FLAGS, npcflag); + target->SetUInt64Value(UNIT_NPC_FLAGS, npcflag); target->SetUInt32Value(OBJECT_DYNAMIC_FLAGS, dyflag); return true; diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 9ee32d0c6e5..81cad2db188 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -262,7 +262,7 @@ public: if (Transport* trans = chr->GetTransport()) { - ObjectGuid::LowType guid = sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(); + ObjectGuid::LowType guid = map->GenerateLowGuid<HighGuid::Creature>(); CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid); data.id = id; data.phaseMask = chr->GetPhaseMask(); @@ -280,7 +280,7 @@ public: } Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), map, chr->GetPhaseMask(), id, x, y, z, o)) + if (!creature->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, chr->GetPhaseMask(), id, x, y, z, o)) { delete creature; return false; @@ -288,7 +288,7 @@ public: creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); - ObjectGuid::LowType db_guid = creature->GetDBTableGUIDLow(); + ObjectGuid::LowType db_guid = creature->GetSpawnId(); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells() // current "creature" variable is deleted and created fresh new, otherwise old values might trigger asserts or cause undefined behavior @@ -395,7 +395,7 @@ public: else { // obtain real GUID for DB operations - lowGuid = creature->GetDBTableGUIDLow(); + lowGuid = creature->GetSpawnId(); } int wait = waitStr ? atoi(waitStr) : 0; @@ -634,7 +634,7 @@ public: if (!*args) return false; - uint32 npcFlags = (uint32) atoi((char*)args); + uint64 npcFlags = std::strtoull(args, nullptr, 10); Creature* creature = handler->getSelectedCreature(); @@ -645,11 +645,11 @@ public: return false; } - creature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags); + creature->SetUInt64Value(UNIT_NPC_FLAGS, npcFlags); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_NPCFLAG); - stmt->setUInt32(0, npcFlags); + stmt->setUInt64(0, npcFlags); stmt->setUInt32(1, creature->GetEntry()); WorldDatabase.Execute(stmt); @@ -726,7 +726,7 @@ public: CreatureTemplate const* cInfo = target->GetCreatureTemplate(); uint32 faction = target->getFaction(); - uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS); + uint64 npcflags = target->GetUInt64Value(UNIT_NPC_FLAGS); uint32 mechanicImmuneMask = cInfo->MechanicImmuneMask; uint32 displayid = target->GetDisplayId(); uint32 nativeid = target->GetNativeDisplayId(); @@ -738,7 +738,7 @@ public: std::string curRespawnDelayStr = secsToTimeString(uint64(curRespawnDelay), true); std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(), true); - handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), target->GetGUID().ToString().c_str(), faction, npcflags, Entry, displayid, nativeid); + handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetSpawnId(), target->GetGUID().ToString().c_str(), faction, npcflags, Entry, displayid, nativeid); handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); handler->PSendSysMessage(LANG_NPCINFO_EQUIPMENT, target->GetCurrentEquipmentId(), target->GetOriginalEquipmentId()); handler->PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); @@ -863,12 +863,12 @@ public: } else { - lowguid = creature->GetDBTableGUIDLow(); + lowguid = creature->GetSpawnId(); } } else { - lowguid = creature->GetDBTableGUIDLow(); + lowguid = creature->GetSpawnId(); } float x = handler->GetSession()->GetPlayer()->GetPositionX(); @@ -878,7 +878,7 @@ public: if (creature) { - if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetSpawnId())) { const_cast<CreatureData*>(data)->posX = x; const_cast<CreatureData*>(data)->posY = y; @@ -1022,7 +1022,7 @@ public: creature = handler->getSelectedCreature(); if (!creature || creature->IsPet()) return false; - lowguid = creature->GetDBTableGUIDLow(); + lowguid = creature->GetSpawnId(); } else // case .setmovetype #creature_guid $move_type (with selected creature) { @@ -1046,7 +1046,7 @@ public: } else { - lowguid = creature->GetDBTableGUIDLow(); + lowguid = creature->GetSpawnId(); } } @@ -1174,7 +1174,7 @@ public: ObjectGuid::LowType guidLow = UI64LIT(0); if (creature) - guidLow = creature->GetDBTableGUIDLow(); + guidLow = creature->GetSpawnId(); else return false; @@ -1223,7 +1223,7 @@ public: ObjectGuid::LowType guidLow = UI64LIT(0); if (creature) - guidLow = creature->GetDBTableGUIDLow(); + guidLow = creature->GetSpawnId(); else return false; @@ -1487,14 +1487,14 @@ public: ObjectGuid::LowType leaderGUID = strtoull(args, nullptr, 10); Creature* creature = handler->getSelectedCreature(); - if (!creature || !creature->GetDBTableGUIDLow()) + if (!creature || !creature->GetSpawnId()) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } - ObjectGuid::LowType lowguid = creature->GetDBTableGUIDLow(); + ObjectGuid::LowType lowguid = creature->GetSpawnId(); if (creature->GetFormation()) { handler->PSendSysMessage("Selected creature is already member of group " UI64FMTD, creature->GetFormation()->GetId()); @@ -1547,21 +1547,21 @@ public: return false; } - if (!creature->GetDBTableGUIDLow()) + if (!creature->GetSpawnId()) { handler->PSendSysMessage("Selected %s isn't in creature table", creature->GetGUID().ToString().c_str()); handler->SetSentErrorMessage(true); return false; } - if (!sObjectMgr->SetCreatureLinkedRespawn(creature->GetDBTableGUIDLow(), linkguid)) + if (!sObjectMgr->SetCreatureLinkedRespawn(creature->GetSpawnId(), linkguid)) { handler->PSendSysMessage("Selected creature can't link with guid '" UI64FMTD "'", linkguid); handler->SetSentErrorMessage(true); return false; } - handler->PSendSysMessage("LinkGUID '" UI64FMTD "' added to creature with DBTableGUID: '" UI64FMTD "'", linkguid, creature->GetDBTableGUIDLow()); + handler->PSendSysMessage("LinkGUID '" UI64FMTD "' added to creature with DBTableGUID: '" UI64FMTD "'", linkguid, creature->GetSpawnId()); return true; } diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index c8066ee92e9..556589e281d 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -76,6 +76,7 @@ public: { "areatrigger_teleport", rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TELEPORT, true, &HandleReloadAreaTriggerTeleportCommand, "", NULL }, { "autobroadcast", rbac::RBAC_PERM_COMMAND_RELOAD_AUTOBROADCAST, true, &HandleReloadAutobroadcastCommand, "", NULL }, { "battleground_template", rbac::RBAC_PERM_COMMAND_RELOAD_BATTLEGROUND_TEMPLATE, true, &HandleReloadBattlegroundTemplate, "", NULL }, + { "character_template", rbac::RBAC_PERM_COMMAND_RELOAD_CHARACTER_TEMPLATE, true, &HandleReloadCharacterTemplate, "", NULL }, { "command", rbac::RBAC_PERM_COMMAND_RELOAD_COMMAND, true, &HandleReloadCommandCommand, "", NULL }, { "conditions", rbac::RBAC_PERM_COMMAND_RELOAD_CONDITIONS, true, &HandleReloadConditions, "", NULL }, { "config", rbac::RBAC_PERM_COMMAND_RELOAD_CONFIG, true, &HandleReloadConfigCommand, "", NULL }, @@ -202,6 +203,7 @@ public: HandleReloadAutobroadcastCommand(handler, ""); HandleReloadBattlegroundTemplate(handler, ""); + HandleReloadCharacterTemplate(handler, ""); return true; } @@ -383,6 +385,14 @@ public: return true; } + static bool HandleReloadCharacterTemplate(ChatHandler* handler, char const* /*args*/) + { + TC_LOG_INFO("misc", "Re-Loading Character Templates..."); + sObjectMgr->LoadCharacterTemplates(); + handler->SendGlobalGMSysMessage("DB table `character_template` and `character_template_class` reloaded."); + return true; + } + static bool HandleReloadCommandCommand(ChatHandler* handler, const char* /*args*/) { handler->SetLoadCommandTable(true); diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index b97c2657d30..3847a74bc34 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -97,13 +97,15 @@ public: uint32 ticketId = atoi(args); GmTicket* ticket = sSupportMgr->GetTicket<GmTicket>(ticketId); - if (!ticket || ticket->IsClosed() || ticket->IsCompleted() || ticket->GetEscalatedStatus() != TICKET_UNASSIGNED) + if (!ticket || ticket->IsClosed() || ticket->IsCompleted() || ticket->GetAssigendToStatus() != GMTICKET_ASSIGNEDTOGM_STATUS_NOT_ASSIGNED) { handler->SendSysMessage(LANG_COMMAND_TICKETNOTEXIST); return true; } - ticket->SetEscalatedStatus(TICKET_IN_ESCALATION_QUEUE); + SQLTransaction trans = SQLTransaction(NULL); + ticket->SetAssignedToStatus(GMTICKET_ASSIGNEDTOGM_STATUS_ESCALATED); + ticket->SaveToDB(trans); if (Player* player = ticket->GetPlayer()) sSupportMgr->SendGmTicket(player->GetSession(), ticket); @@ -192,6 +194,9 @@ public: ticket->SetViewed(); ticket->SaveToDB(trans); + if (Player* player = ticket->GetPlayer()) + sSupportMgr->SendGmTicket(player->GetSession(), ticket); + handler->SendSysMessage(ticket->FormatViewMessageString(*handler, true).c_str()); return true; } @@ -677,6 +682,9 @@ bool ticket_commandscript::HandleTicketUnAssignCommand<GmTicket>(ChatHandler* ha ticket->SaveToDB(trans); sSupportMgr->UpdateLastChange(); + if (Player* player = ticket->GetPlayer()) + sSupportMgr->SendGmTicket(player->GetSession(), ticket); + std::string msg = ticket->FormatViewMessageString(*handler, NULL, assignedTo.c_str(), handler->GetSession() ? handler->GetSession()->GetPlayer()->GetName().c_str() : "Console", NULL, NULL); handler->SendGlobalGMSysMessage(msg.c_str()); @@ -719,6 +727,9 @@ bool ticket_commandscript::HandleTicketGetByIdCommand<GmTicket>(ChatHandler* han ticket->SetViewed(); ticket->SaveToDB(trans); + if (Player* player = ticket->GetPlayer()) + sSupportMgr->SendGmTicket(player->GetSession(), ticket); + handler->SendSysMessage(ticket->FormatViewMessageString(*handler, true).c_str()); return true; } diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index a4e0ce3af61..358b6fff085 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -179,7 +179,7 @@ public: return true; } - guidLow = target->GetDBTableGUIDLow(); + guidLow = target->GetSpawnId(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_ADDON_BY_GUID); @@ -246,7 +246,7 @@ public: return true; } - ObjectGuid::LowType guidLow = target->GetDBTableGUIDLow(); + ObjectGuid::LowType guidLow = target->GetSpawnId(); if (!guidLow) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "Target is not saved to DB."); @@ -674,7 +674,7 @@ public: } // re-create Creature* wpCreature2 = new Creature(); - if (!wpCreature2->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), map, chr->GetPhaseMask(), VISUAL_WAYPOINT, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) + if (!wpCreature2->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, chr->GetPhaseMask(), VISUAL_WAYPOINT, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; @@ -687,7 +687,7 @@ public: wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); /// @todo Should we first use "Create" then use "LoadFromDB"? - if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetDBTableGUIDLow(), map)) + if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetSpawnId(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; @@ -894,7 +894,7 @@ public: float o = chr->GetOrientation(); Creature* wpCreature = new Creature(); - if (!wpCreature->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), map, chr->GetPhaseMask(), id, x, y, z, o)) + if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, chr->GetPhaseMask(), id, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; @@ -912,7 +912,7 @@ public: wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - if (!wpCreature->LoadCreatureFromDB(wpCreature->GetDBTableGUIDLow(), map)) + if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; @@ -958,7 +958,7 @@ public: Map* map = chr->GetMap(); Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), map, chr->GetPhaseMask(), id, x, y, z, o)) + if (!creature->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, chr->GetPhaseMask(), id, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; @@ -968,7 +968,7 @@ public: creature->CopyPhaseFrom(chr); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); - if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) + if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; @@ -1009,7 +1009,7 @@ public: Map* map = chr->GetMap(); Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GetGenerator<HighGuid::Creature>()->Generate(), map, chr->GetPhaseMask(), id, x, y, z, o)) + if (!creature->Create(map->GenerateLowGuid<HighGuid::Creature>(), map, chr->GetPhaseMask(), id, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; @@ -1019,7 +1019,7 @@ public: creature->CopyPhaseFrom(chr); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); - if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) + if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp index 0311ed61c6a..ecda065fda9 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp @@ -32,8 +32,7 @@ enum Spells SPELL_CURSE_OF_EXERTION = 52772, SPELL_TIME_WARP = 52766, //Time slows down, reducing attack, casting and movement speed by 70% for 6 sec. SPELL_TIME_STOP = 58848, //Stops time in a 50 yard sphere for 2 sec. - SPELL_WOUNDING_STRIKE = 52771, //Used only on the tank - H_SPELL_WOUNDING_STRIKE = 58830 + SPELL_WOUNDING_STRIKE = 52771 //Used only on the tank }; enum Yells @@ -45,109 +44,78 @@ enum Yells SAY_DEATH = 4 }; -class boss_epoch : public CreatureScript +enum Events { -public: - boss_epoch() : CreatureScript("boss_epoch") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_epochAI>(creature); - } - - struct boss_epochAI : public ScriptedAI - { - boss_epochAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - uiStep = 1; - uiStepTimer = 26000; - uiCurseOfExertionTimer = 9300; - uiTimeWarpTimer = 25300; - uiTimeStopTimer = 21300; - uiWoundingStrikeTimer = 5300; - } - - uint8 uiStep; - - uint32 uiStepTimer; - uint32 uiWoundingStrikeTimer; - uint32 uiTimeWarpTimer; - uint32 uiTimeStopTimer; - uint32 uiCurseOfExertionTimer; - - InstanceScript* instance; - - void Reset() override - { - Initialize(); - - instance->SetBossState(DATA_EPOCH, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); + EVENT_CURSE_OF_EXERTION = 1, + EVENT_TIME_WARP, + EVENT_TIME_STOP, + EVENT_WOUNDING_STRIKE +}; - instance->SetBossState(DATA_EPOCH, IN_PROGRESS); - } +class boss_epoch : public CreatureScript +{ + public: + boss_epoch() : CreatureScript("boss_epoch") { } - void UpdateAI(uint32 diff) override + struct boss_epochAI : public BossAI { - //Return since we have no target - if (!UpdateVictim()) - return; + boss_epochAI(Creature* creature) : BossAI(creature, DATA_EPOCH) { } - if (uiCurseOfExertionTimer < diff) + void EnterCombat(Unit* /*who*/) override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_CURSE_OF_EXERTION); - uiCurseOfExertionTimer = 9300; - } else uiCurseOfExertionTimer -= diff; + Talk(SAY_AGGRO); + _EnterCombat(); - if (uiWoundingStrikeTimer < diff) - { - DoCastVictim(SPELL_WOUNDING_STRIKE); - uiWoundingStrikeTimer = 5300; - } else uiWoundingStrikeTimer -= diff; + events.ScheduleEvent(EVENT_CURSE_OF_EXERTION, 9300); + events.ScheduleEvent(EVENT_TIME_WARP, 25300); + events.ScheduleEvent(EVENT_TIME_STOP, 21300); + events.ScheduleEvent(EVENT_WOUNDING_STRIKE, 5300); + } - if (uiTimeStopTimer < diff) + void ExecuteEvent(uint32 eventId) override { - DoCastAOE(SPELL_TIME_STOP); - uiTimeStopTimer = 21300; - } else uiTimeStopTimer -= diff; - - if (uiTimeWarpTimer < diff) + switch (eventId) + { + case EVENT_CURSE_OF_EXERTION: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_CURSE_OF_EXERTION); + events.ScheduleEvent(EVENT_CURSE_OF_EXERTION, 9300); + break; + case EVENT_TIME_WARP: + Talk(SAY_TIME_WARP); + DoCastAOE(SPELL_TIME_WARP); + events.ScheduleEvent(EVENT_TIME_WARP, 25300); + break; + case EVENT_TIME_STOP: + DoCastAOE(SPELL_TIME_STOP); + events.ScheduleEvent(EVENT_TIME_STOP, 21300); + break; + case EVENT_WOUNDING_STRIKE: + DoCastVictim(SPELL_WOUNDING_STRIKE); + events.ScheduleEvent(EVENT_WOUNDING_STRIKE, 5300); + break; + default: + break; + } + } + + void JustDied(Unit* /*killer*/) override { - Talk(SAY_TIME_WARP); - DoCastAOE(SPELL_TIME_WARP); - uiTimeWarpTimer = 25300; - } else uiTimeWarpTimer -= diff; + Talk(SAY_DEATH); + _JustDied(); + } - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - - instance->SetBossState(DATA_EPOCH, DONE); - } + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + }; - void KilledUnit(Unit* victim) override + CreatureAI* GetAI(Creature* creature) const override { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - Talk(SAY_SLAY); + return GetInstanceAI<boss_epochAI>(creature); } - }; - }; void AddSC_boss_epoch() diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp index fe6c7504637..b7996a2bcaa 100644 --- a/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp +++ b/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp @@ -116,6 +116,7 @@ class boss_slabhide : public CreatureScript me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->SetReactState(REACT_PASSIVE); instance->SetData(DATA_SLABHIDE_INTRO, NOT_STARTED); + _isFlying = false; } void Reset() override @@ -130,6 +131,7 @@ class boss_slabhide : public CreatureScript me->SetDisableGravity(false); me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->SetReactState(REACT_AGGRESSIVE); + _isFlying = false; } void EnterCombat(Unit* /*victim*/) override @@ -142,6 +144,12 @@ class boss_slabhide : public CreatureScript events.ScheduleEvent(EVENT_AIR_PHASE, 10000); } + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (_isFlying && damage >= me->GetHealth()) + damage = me->GetHealth() - 1; // Let creature health fall to 1 hp but prevent it from dying during air phase. + } + void JustDied(Unit* /*killer*/) override { _JustDied(); @@ -193,12 +201,14 @@ class boss_slabhide : public CreatureScript instance->SetData(DATA_SLABHIDE_INTRO, DONE); break; case POINT_SLABHIDE_MIDDLE: + _isFlying = true; events.ScheduleEvent(EVENT_TAKEOFF, 100); break; case POINT_SLABHIDE_IN_AIR: events.ScheduleEvent(EVENT_STALACTITE, 400); break; case POINT_SLABHIDE_LAND: + _isFlying = false; //DoCast(me, SPELL_COOLDOWN_5S); // unknown purpose events.ScheduleEvent(EVENT_ATTACK, 1200); break; @@ -297,7 +307,7 @@ class boss_slabhide : public CreatureScript (*itr)->Delete(); } - EventMap events; + bool _isFlying; }; CreatureAI* GetAI(Creature* creature) const override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index 21214b62345..6e1c15ca909 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -376,7 +376,7 @@ class boss_prince_keleseth_icc : public CreatureScript void InitializeAI() override { - if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetSpawnId())) if (data->curhealth) _spawnHealth = data->curhealth; @@ -591,7 +591,7 @@ class boss_prince_taldaram_icc : public CreatureScript void InitializeAI() override { - if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetSpawnId())) if (data->curhealth) _spawnHealth = data->curhealth; @@ -815,7 +815,7 @@ class boss_prince_valanar_icc : public CreatureScript void InitializeAI() override { - if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetSpawnId())) if (data->curhealth) _spawnHealth = data->curhealth; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index 432a61b6279..816895684f1 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -492,7 +492,7 @@ public: _caster->CastSpell(_caster, _spellId, true); _caster->GetTransport()->AddObjectToRemoveList(); - if (GameObject* go = HashMapHolder<GameObject>::Find(_otherTransport)) + if (Transport* go = HashMapHolder<Transport>::Find(_otherTransport)) go->AddObjectToRemoveList(); return true; @@ -764,9 +764,8 @@ class npc_gunship : public CreatureScript if (isVictory) { - if (GameObject* go = HashMapHolder<GameObject>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - if (Transport* otherTransport = go->ToTransport()) - otherTransport->EnableMovement(true); + if (Transport* otherTransport = HashMapHolder<Transport>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + otherTransport->EnableMovement(true); me->GetTransport()->EnableMovement(true); @@ -1029,9 +1028,8 @@ class npc_high_overlord_saurfang_igb : public CreatureScript if (Transport* orgrimsHammer = me->GetTransport()) orgrimsHammer->SummonPassenger(NPC_TELEPORT_PORTAL, OrgrimsHammerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, NULL, 21000); - if (GameObject* go = HashMapHolder<GameObject>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - if (Transport* skybreaker = go->ToTransport()) - skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); + if (Transport* skybreaker = HashMapHolder<Transport>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000); _events.ScheduleEvent(EVENT_ADDS, 60000); @@ -1302,9 +1300,8 @@ class npc_muradin_bronzebeard_igb : public CreatureScript if (Transport* skybreaker = me->GetTransport()) skybreaker->SummonPassenger(NPC_TELEPORT_PORTAL, SkybreakerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, NULL, 21000); - if (GameObject* go = HashMapHolder<GameObject>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - if (Transport* orgrimsHammer = go->ToTransport()) - orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); + if (Transport* orgrimsHammer = HashMapHolder<Transport>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000); _events.ScheduleEvent(EVENT_ADDS, 60000); @@ -1448,9 +1445,8 @@ struct npc_gunship_boarding_addAI : public gunship_npc_AI if (!myTransport) return; - if (GameObject* go = HashMapHolder<GameObject>::Find(Instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - if (Transport* destTransport = go->ToTransport()) - destTransport->CalculatePassengerPosition(x, y, z, &o); + if (Transport* destTransport = HashMapHolder<Transport>::Find(Instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + destTransport->CalculatePassengerPosition(x, y, z, &o); float angle = frand(0, float(M_PI) * 2.0f); x += 2.0f * std::cos(angle); @@ -2346,7 +2342,7 @@ class spell_igb_gunship_fall_teleport : public SpellScriptLoader void SelectTransport(WorldObject*& target) { if (InstanceScript* instance = target->GetInstanceScript()) - target = HashMapHolder<GameObject>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)); + target = HashMapHolder<Transport>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)); } void RelocateDest(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 5a2376b8266..7bd1dee15ca 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -647,7 +647,7 @@ class npc_spinestalker : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetDBTableGUIDLow())); // this cannot be in Reset because reset also happens on evade + _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -670,7 +670,7 @@ class npc_spinestalker : public CreatureScript void JustRespawned() override { ScriptedAI::JustRespawned(); - _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetDBTableGUIDLow())); // this cannot be in Reset because reset also happens on evade + _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) override @@ -783,7 +783,7 @@ class npc_rimefang : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetDBTableGUIDLow())); // this cannot be in Reset because reset also happens on evade + _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -806,7 +806,7 @@ class npc_rimefang : public CreatureScript void JustRespawned() override { ScriptedAI::JustRespawned(); - _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetDBTableGUIDLow())); // this cannot be in Reset because reset also happens on evade + _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) override @@ -950,7 +950,7 @@ class npc_sindragosa_trash : public CreatureScript if (!me->isDead()) { if (me->GetEntry() == NPC_FROSTWING_WHELP) - _instance->SetGuidData(_frostwyrmId, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetDBTableGUIDLow())); // this cannot be in Reset because reset also happens on evade + _instance->SetGuidData(_frostwyrmId, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -973,7 +973,7 @@ class npc_sindragosa_trash : public CreatureScript // Increase add count if (me->GetEntry() == NPC_FROSTWING_WHELP) - _instance->SetGuidData(_frostwyrmId, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetDBTableGUIDLow())); // this cannot be in Reset because reset also happens on evade + _instance->SetGuidData(_frostwyrmId, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade } void SetData(uint32 type, uint32 data) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index b8f2c9c5a4f..c04d53079c5 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -156,7 +156,7 @@ class RisenArchmageCheck bool operator()(Creature* creature) { return creature->IsAlive() && creature->GetEntry() == NPC_RISEN_ARCHMAGE && - creature->GetDBTableGUIDLow() && !creature->IsInCombat(); + creature->GetSpawnId() && !creature->IsInCombat(); } }; @@ -244,7 +244,7 @@ class ValithriaDespawner : public BasicEvent creature->DespawnOrUnsummon(); return; case NPC_RISEN_ARCHMAGE: - if (!creature->GetDBTableGUIDLow()) + if (!creature->GetSpawnId()) { creature->DespawnOrUnsummon(); return; @@ -297,7 +297,7 @@ class boss_valithria_dreamwalker : public CreatureScript void InitializeAI() override { - if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetSpawnId())) if (data->curhealth) _spawnHealth = data->curhealth; @@ -712,7 +712,7 @@ class npc_risen_archmage : public CreatureScript void EnterCombat(Unit* /*target*/) override { me->FinishSpell(CURRENT_CHANNELED_SPELL, false); - if (me->GetDBTableGUIDLow() && _canCallEnterCombat) + if (me->GetSpawnId() && _canCallEnterCombat) { std::list<Creature*> archmages; RisenArchmageCheck check; @@ -750,7 +750,7 @@ class npc_risen_archmage : public CreatureScript void UpdateAI(uint32 diff) override { if (!me->IsInCombat()) - if (me->GetDBTableGUIDLow()) + if (me->GetSpawnId()) if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) DoCast(me, SPELL_CORRUPTION); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 91702f3a0da..30b797bf98d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -545,7 +545,7 @@ class npc_highlord_tirion_fordring_lh : public CreatureScript case EVENT_MURADIN_RUN: case EVENT_SAURFANG_RUN: if (Creature* factionNPC = ObjectAccessor::GetCreature(*me, _factionNPC)) - factionNPC->GetMotionMaster()->MovePath(factionNPC->GetDBTableGUIDLow() * 10, false); + factionNPC->GetMotionMaster()->MovePath(factionNPC->GetSpawnId() * 10, false); me->setActive(false); _damnedKills = 3; break; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 594ac140094..aee14edd0c3 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -419,14 +419,14 @@ class instance_icecrown_citadel : public InstanceMapScript if (creature->AI()->GetData(1/*DATA_FROSTWYRM_OWNER*/) == DATA_SPINESTALKER) { - SpinestalkerTrash.erase(creature->GetDBTableGUIDLow()); + SpinestalkerTrash.erase(creature->GetSpawnId()); if (SpinestalkerTrash.empty()) if (Creature* spinestalk = instance->GetCreature(SpinestalkerGUID)) spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); } else { - RimefangTrash.erase(creature->GetDBTableGUIDLow()); + RimefangTrash.erase(creature->GetSpawnId()); if (RimefangTrash.empty()) if (Creature* spinestalk = instance->GetCreature(RimefangGUID)) spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); @@ -441,7 +441,7 @@ class instance_icecrown_citadel : public InstanceMapScript if (GetBossState(DATA_SINDRAGOSA) == DONE) return; - FrostwyrmGUIDs.erase(creature->GetDBTableGUIDLow()); + FrostwyrmGUIDs.erase(creature->GetSpawnId()); if (FrostwyrmGUIDs.empty()) { instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 0c79b42f20c..b939c40cabb 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -128,7 +128,6 @@ enum Spells SPELL_ARCANE_BARRAGE_DAMAGE = 63934, // the actual damage - cast by affected player by script spell // Transition /II-III/ - SPELL_SUMMOM_RED_DRAGON_BUDYY = 56070, SPELL_RIDE_RED_DRAGON_BUDDY = 56071, SPELL_SUMMON_RED_DRAGON_BUDDY_F_CAST = 58846, // After implicitly hit player targets they will force cast 56070 on self SPELL_DESTROY_PLATFORM_CHANNEL = 58842, diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h index b6a0d3f9b62..d9b921b38a1 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h @@ -80,7 +80,8 @@ enum InstanceSpells SPELL_VORTEX_5 = 56263, // damage | used to enter to the vehicle SPELL_PORTAL_OPENED = 61236, SPELL_RIDE_RED_DRAGON_TRIGGERED = 56072, - SPELL_IRIS_OPENED = 61012 // visual when starting encounter + SPELL_IRIS_OPENED = 61012, // visual when starting encounter + SPELL_SUMMOM_RED_DRAGON_BUDDY = 56070 }; #endif diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index 46fb538d576..11d19d76d80 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -39,6 +39,12 @@ public: SetBossNumber(MAX_ENCOUNTER); } + void OnPlayerEnter(Player* player) override + { + if (GetBossState(DATA_MALYGOS_EVENT) == DONE) + player->CastSpell(player, SPELL_SUMMOM_RED_DRAGON_BUDDY, true); + } + bool SetBossState(uint32 type, EncounterState state) override { if (!InstanceScript::SetBossState(type, state)) @@ -74,7 +80,7 @@ public: void SpawnGameObject(uint32 entry, Position& pos) { GameObject* go = new GameObject; - if (!go->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), entry, instance, + if (!go->Create(instance->GenerateLowGuid<HighGuid::GameObject>(), entry, instance, PHASEMASK_NORMAL, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0, 0, 0, 0, 120, GO_STATE_READY)) { diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp index 1e2ca666378..6233c7e8953 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp @@ -330,7 +330,7 @@ public: DespawnDwarf(); - instance->SetBossState(DATA_BRANN_EVENT, NOT_STARTED); + instance->SetBossState(DATA_TRIBUNAL_OF_AGES, NOT_STARTED); } } @@ -362,8 +362,10 @@ public: break; case 13: Talk(SAY_EVENT_INTRO_1); + instance->SetBossState(DATA_TRIBUNAL_OF_AGES, IN_PROGRESS); SetEscortPaused(true); JumpToNextStep(20000); + // @todo: There should be a pause here and a gossip should start the next step. break; case 17: Talk(SAY_EVENT_INTRO_2); @@ -421,9 +423,9 @@ public: Start(); } - void DamageTaken(Unit* /*done_by*/, uint32 & /*damage*/) override + void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/) override { - if (brannSparklinNews) + if (instance->GetBossState(DATA_TRIBUNAL_OF_AGES) == IN_PROGRESS) brannSparklinNews = false; } @@ -442,9 +444,8 @@ public: switch (uiStep) { case 1: - if (instance->GetBossState(DATA_BRANN_EVENT) != NOT_STARTED) + if (instance->GetBossState(DATA_TRIBUNAL_OF_AGES) != NOT_STARTED) return; - instance->SetBossState(DATA_BRANN_EVENT, IN_PROGRESS); bIsBattle = false; Talk(SAY_ESCORT_START); SetRun(true); @@ -582,7 +583,7 @@ public: break; case 29: Talk(SAY_EVENT_END_02); - instance->SetBossState(DATA_BRANN_EVENT, DONE); + instance->SetBossState(DATA_TRIBUNAL_OF_AGES, DONE); me->CastSpell(me, SPELL_REWARD_ACHIEVEMENT, true); JumpToNextStep(5500); break; @@ -715,9 +716,7 @@ public: class achievement_brann_spankin_new : public AchievementCriteriaScript { public: - achievement_brann_spankin_new() : AchievementCriteriaScript("achievement_brann_spankin_new") - { - } + achievement_brann_spankin_new() : AchievementCriteriaScript("achievement_brann_spankin_new") { } bool OnCheck(Player* /*player*/, Unit* target) override { diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h index 2ed47b42bbc..df56aadfe22 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h @@ -28,7 +28,7 @@ enum DataTypes // Encounter States/Boss GUIDs DATA_KRYSTALLUS = 0, DATA_MAIDEN_OF_GRIEF = 1, - DATA_BRANN_EVENT = 2, + DATA_TRIBUNAL_OF_AGES = 2, DATA_SJONNIR = 3, // Additional data diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp index a70d1ff3a0d..c67e31c4cc0 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp @@ -23,8 +23,8 @@ DoorData const doorData[] = { - { GO_SJONNIR_DOOR, DATA_BRANN_EVENT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, - { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END + { GO_SJONNIR_DOOR, DATA_TRIBUNAL_OF_AGES, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END }; class instance_halls_of_stone : public InstanceMapScript @@ -90,7 +90,7 @@ class instance_halls_of_stone : public InstanceMapScript case GO_TRIBUNAL_CHEST: case GO_TRIBUNAL_CHEST_HERO: TribunalChestGUID = go->GetGUID(); - if (GetBossState(DATA_BRANN_EVENT) == DONE) + if (GetBossState(DATA_TRIBUNAL_OF_AGES) == DONE) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); break; case GO_TRIBUNAL_SKY_FLOOR: @@ -156,7 +156,7 @@ class instance_halls_of_stone : public InstanceMapScript switch (type) { - case DATA_BRANN_EVENT: + case DATA_TRIBUNAL_OF_AGES: if (state == DONE) { if (GameObject* go = instance->GetGameObject(TribunalChestGUID)) @@ -178,7 +178,7 @@ class instance_halls_of_stone : public InstanceMapScript switch (bossId) { case DATA_SJONNIR: - if (GetBossState(DATA_BRANN_EVENT) != DONE) + if (GetBossState(DATA_TRIBUNAL_OF_AGES) != DONE) return false; break; default: diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 9ca88f4fdfa..525ecacd39a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -482,40 +482,47 @@ class boss_flame_leviathan : public CreatureScript if (action && action <= 4) // Tower destruction, debuff leviathan loot and reduce active tower count { if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2 | LOOT_MODE_HARD_MODE_3 | LOOT_MODE_HARD_MODE_4) && ActiveTowersCount == 4) - { me->RemoveLootMode(LOOT_MODE_HARD_MODE_4); - --ActiveTowersCount; - } + if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2 | LOOT_MODE_HARD_MODE_3) && ActiveTowersCount == 3) - { me->RemoveLootMode(LOOT_MODE_HARD_MODE_3); - --ActiveTowersCount; - } + if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2) && ActiveTowersCount == 2) - { me->RemoveLootMode(LOOT_MODE_HARD_MODE_2); - --ActiveTowersCount; - } + if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1) && ActiveTowersCount == 1) - { me->RemoveLootMode(LOOT_MODE_HARD_MODE_1); - --ActiveTowersCount; - } } switch (action) { case ACTION_TOWER_OF_STORM_DESTROYED: - towerOfStorms = false; + if (towerOfStorms) + { + towerOfStorms = false; + --ActiveTowersCount; + } break; case ACTION_TOWER_OF_FROST_DESTROYED: - towerOfFrost = false; + if (towerOfFrost) + { + towerOfFrost = false; + --ActiveTowersCount; + } break; case ACTION_TOWER_OF_FLAMES_DESTROYED: - towerOfFlames = false; + if (towerOfFlames) + { + towerOfFlames = false; + --ActiveTowersCount; + } break; case ACTION_TOWER_OF_LIFE_DESTROYED: - towerOfLife = false; + if (towerOfLife) + { + towerOfLife = false; + --ActiveTowersCount; + } break; case ACTION_START_HARD_MODE: // Activate hard-mode enable all towers, apply buffs on leviathan ActiveTowers = true; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 385a208b5ad..a8cad32333b 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -777,8 +777,8 @@ class instance_ulduar : public InstanceMapScript if (Player* player = itr->GetSource()) for (uint8 slot = EQUIPMENT_SLOT_MAINHAND; slot <= EQUIPMENT_SLOT_RANGED; ++slot) if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) - if (item->GetItemLevel() > _maxWeaponItemLevel) - _maxWeaponItemLevel = item->GetItemLevel(); + if (item->GetItemLevel(player) > _maxWeaponItemLevel) + _maxWeaponItemLevel = item->GetItemLevel(player); } else if (state == IN_PROGRESS) { @@ -797,11 +797,11 @@ class instance_ulduar : public InstanceMapScript { if (slot >= EQUIPMENT_SLOT_MAINHAND && slot <= EQUIPMENT_SLOT_RANGED) { - if (item->GetItemLevel() > _maxWeaponItemLevel) - _maxWeaponItemLevel = item->GetItemLevel(); + if (item->GetItemLevel(player) > _maxWeaponItemLevel) + _maxWeaponItemLevel = item->GetItemLevel(player); } - else if (item->GetItemLevel() > _maxArmorItemLevel) - _maxArmorItemLevel = item->GetItemLevel(); + else if (item->GetItemLevel(player) > _maxArmorItemLevel) + _maxArmorItemLevel = item->GetItemLevel(player); } } } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp index 438ac9b67ec..f0be400f9c6 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPHP.h" #include "OutdoorPvP.h" @@ -64,6 +65,8 @@ bool OutdoorPvPHP::SetupOutdoorPvP() { m_AllianceTowersControlled = 0; m_HordeTowersControlled = 0; + SetMapFromZone(OutdoorPvPHPBuffZones[0]); + // add the zones affected by the pvp buff for (int i = 0; i < OutdoorPvPHPBuffZonesNum; ++i) RegisterZone(OutdoorPvPHPBuffZones[i]); @@ -238,16 +241,14 @@ void OPvPCapturePointHP::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[m_TowerType]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit2); - } + Map* map = sMapMgr->FindMap(530, 0); + auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); + + bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_Objects[m_TowerType]); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit2); // send world state update if (field) diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp index 258ff9ef631..1fb5a218f88 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPNA.h" #include "Player.h" @@ -43,7 +44,7 @@ void OutdoorPvPNA::HandleKillImpl(Player* player, Unit* killed) uint32 OPvPCapturePointNA::GetAliveGuardsCount() { uint32 cnt = 0; - for (std::map<uint32, ObjectGuid>::iterator itr = m_Creatures.begin(); itr != m_Creatures.end(); ++itr) + for (std::map<uint32, ObjectGuid::LowType>::iterator itr = m_Creatures.begin(); itr != m_Creatures.end(); ++itr) { switch (itr->first) { @@ -62,10 +63,13 @@ uint32 OPvPCapturePointNA::GetAliveGuardsCount() case NA_NPC_GUARD_13: case NA_NPC_GUARD_14: case NA_NPC_GUARD_15: - if (Creature const* const cr = HashMapHolder<Creature>::Find(itr->second)) - if (cr->IsAlive()) + { + auto bounds = m_PvP->GetMap()->GetCreatureBySpawnIdStore().equal_range(itr->second); + for (auto itr2 = bounds.first; itr2 != bounds.second; ++itr2) + if (itr2->second->IsAlive()) ++cnt; break; + } default: break; } @@ -186,6 +190,7 @@ bool OutdoorPvPNA::SetupOutdoorPvP() { // m_TypeId = OUTDOOR_PVP_NA; _MUST_ be set in ctor, because of spawns cleanup // add the zones affected by the pvp buff + SetMapFromZone(NA_BUFF_ZONE); RegisterZone(NA_BUFF_ZONE); // halaa @@ -372,9 +377,9 @@ bool OPvPCapturePointNA::HandleCustomSpell(Player* player, uint32 spellId, GameO return false; } -int32 OPvPCapturePointNA::HandleOpenGo(Player* player, ObjectGuid guid) +int32 OPvPCapturePointNA::HandleOpenGo(Player* player, GameObject* go) { - int32 retval = OPvPCapturePoint::HandleOpenGo(player, guid); + int32 retval = OPvPCapturePoint::HandleOpenGo(player, go); if (retval >= 0) { const go_type * gos = NULL; @@ -567,11 +572,9 @@ void OPvPCapturePointNA::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - if (flag) - { - flag->SetGoArtKit(artkit); - } + auto bounds = sMapMgr->FindMap(530, 0)->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); UpdateHalaaWorldState(); } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h index a3c254ea6a5..c2dd71ce7cf 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h @@ -269,7 +269,7 @@ class OPvPCapturePointNA : public OPvPCapturePoint bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go); - int32 HandleOpenGo(Player* player, ObjectGuid guid) override; + int32 HandleOpenGo(Player* player, GameObject* go) override; uint32 GetAliveGuardsCount(); uint32 GetControllingFaction() const; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp index 6496b54dd82..233f1151b4e 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp @@ -58,6 +58,8 @@ void OutdoorPvPSI::UpdateWorldState() bool OutdoorPvPSI::SetupOutdoorPvP() { + SetMapFromZone(OutdoorPvPSIBuffZones[0]); + for (uint8 i = 0; i < OutdoorPvPSIBuffZonesNum; ++i) RegisterZone(OutdoorPvPSIBuffZones[i]); return true; @@ -166,7 +168,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId) return true; } - if (!go->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), SI_SILITHYST_MOUND, map, player->GetPhaseMask(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) + if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), SI_SILITHYST_MOUND, map, player->GetPhaseMask(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) { delete go; return true; @@ -202,7 +204,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId) return true; } - if (!go->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), SI_SILITHYST_MOUND, map, player->GetPhaseMask(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) + if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), SI_SILITHYST_MOUND, map, player->GetPhaseMask(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) { delete go; return true; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp index af0c824006a..12c77ad556e 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPTF.h" #include "OutdoorPvPMgr.h" @@ -224,6 +225,8 @@ bool OutdoorPvPTF::SetupOutdoorPvP() second_digit = 0; first_digit = 0; + SetMapFromZone(OutdoorPvPTFBuffZones[0]); + // add the zones affected by the pvp buff for (uint8 i = 0; i < OutdoorPvPTFBuffZonesNum; ++i) RegisterZone(OutdoorPvPTFBuffZones[i]); @@ -307,9 +310,9 @@ void OPvPCapturePointTF::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - if (flag) - flag->SetGoArtKit(artkit); + auto bounds = sMapMgr->FindMap(530, 0)->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); UpdateTowerState(); } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp index c1b2712d29d..6ac1362d9d8 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPZM.h" #include "ObjectMgr.h" @@ -151,6 +152,8 @@ bool OutdoorPvPZM::SetupOutdoorPvP() m_AllianceTowersControlled = 0; m_HordeTowersControlled = 0; + SetMapFromZone(OutdoorPvPZMBuffZones[0]); + // add the zones affected by the pvp buff for (uint8 i = 0; i < OutdoorPvPZMBuffZonesNum; ++i) RegisterZone(OutdoorPvPZMBuffZones[i]); @@ -181,9 +184,9 @@ bool OPvPCapturePointZM_GraveYard::Update(uint32 /*diff*/) return retval; } -int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, ObjectGuid guid) +int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) { - int32 retval = OPvPCapturePoint::HandleOpenGo(player, guid); + int32 retval = OPvPCapturePoint::HandleOpenGo(player, go); if (retval >= 0) { if (player->HasAura(ZM_BATTLE_STANDARD_A) && m_GraveYardState != ZM_GRAVEYARD_A) @@ -297,8 +300,7 @@ void OPvPCapturePointZM_GraveYard::SetBeaconState(uint32 controlling_faction) bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player* player, Creature* c, GossipMenuItems const& /*gso*/) { - ObjectGuid guid = c->GetGUID(); - std::map<ObjectGuid, uint32>::iterator itr = m_CreatureTypes.find(guid); + std::map<ObjectGuid::LowType, uint32>::iterator itr = m_CreatureTypes.find(c->GetSpawnId()); if (itr != m_CreatureTypes.end()) { if (itr->second == ZM_ALLIANCE_FIELD_SCOUT && player->GetTeam() == ALLIANCE && m_BothControllingFaction == ALLIANCE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_A) @@ -309,25 +311,22 @@ bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player* player, Creature* c, Gossip return false; } -bool OPvPCapturePointZM_GraveYard::HandleGossipOption(Player* player, ObjectGuid guid, uint32 /*gossipid*/) +bool OPvPCapturePointZM_GraveYard::HandleGossipOption(Player* player, Creature* creature, uint32 /*gossipid*/) { - std::map<ObjectGuid, uint32>::iterator itr = m_CreatureTypes.find(guid); + std::map<ObjectGuid::LowType, uint32>::iterator itr = m_CreatureTypes.find(creature->GetSpawnId()); if (itr != m_CreatureTypes.end()) { - Creature* cr = HashMapHolder<Creature>::Find(guid); - if (!cr) - return true; // if the flag is already taken, then return if (!m_FlagCarrierGUID.IsEmpty()) return true; if (itr->second == ZM_ALLIANCE_FIELD_SCOUT) { - cr->CastSpell(player, ZM_BATTLE_STANDARD_A, true); + creature->CastSpell(player, ZM_BATTLE_STANDARD_A, true); m_FlagCarrierGUID = player->GetGUID(); } else if (itr->second == ZM_HORDE_FIELD_SCOUT) { - cr->CastSpell(player, ZM_BATTLE_STANDARD_H, true); + creature->CastSpell(player, ZM_BATTLE_STANDARD_H, true); m_FlagCarrierGUID = player->GetGUID(); } UpdateTowerState(); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h index 76e4cc71d1f..d8863b026d9 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h @@ -192,11 +192,11 @@ class OPvPCapturePointZM_GraveYard : public OPvPCapturePoint void UpdateTowerState(); - int32 HandleOpenGo(Player* player, ObjectGuid guid) override; + int32 HandleOpenGo(Player* player, GameObject* go) override; void SetBeaconState(uint32 controlling_team); // not good atm - bool HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid) override; + bool HandleGossipOption(Player* player, Creature* creature, uint32 gossipid) override; bool HandleDropFlag(Player* player, uint32 spellId) override; diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 84a6fab9318..4ea0695983a 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -344,7 +344,7 @@ class spell_dru_glyph_of_starfire : public SpellScriptLoader { Unit* caster = GetCaster(); if (Unit* unitTarget = GetHitUnit()) - if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x2, 0, 0, caster->GetGUID())) + if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, flag128(0x2, 0, 0), caster->GetGUID())) { Aura* aura = aurEff->GetBase(); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 451dc933d86..d01883a019b 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -38,6 +38,7 @@ #include "SpellAuraEffects.h" #include "SpellHistory.h" #include "Vehicle.h" +#include "NPCPackets.h" class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader { @@ -117,7 +118,7 @@ class spell_gen_adaptive_warding : public SpellScriptLoader return false; // find Mage Armor - if (!GetTarget()->GetAuraEffect(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, 0x10000000, 0x0, 0x0)) + if (!GetTarget()->GetAuraEffect(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, flag128(0x10000000, 0x0, 0x0))) return false; switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask())) @@ -3052,9 +3053,9 @@ class spell_gen_spirit_healer_res : public SpellScriptLoader Player* originalCaster = GetOriginalCaster()->ToPlayer(); if (Unit* target = GetHitUnit()) { - WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8); - data << target->GetGUID(); - originalCaster->GetSession()->SendPacket(&data); + WorldPackets::NPC::SpiritHealerConfirm spiritHealerConfirm; + spiritHealerConfirm.Unit = target->GetGUID(); + originalCaster->GetSession()->SendPacket(spiritHealerConfirm.Write()); } } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 00732f1198b..ed76d87cf83 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -748,7 +748,7 @@ class spell_pri_pain_and_suffering_proc : public SpellScriptLoader Unit* caster = GetCaster(); // Refresh Shadow Word: Pain on target if (Unit* target = GetHitUnit()) - if (AuraEffect* aur = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, caster->GetGUID())) + if (AuraEffect* aur = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, flag128(0x8000, 0, 0), caster->GetGUID())) { uint32 damage = std::max(aur->GetAmount(), 0); sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index b70ae177928..537c57fb51f 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -280,7 +280,7 @@ class spell_rog_deadly_poison : public SpellScriptLoader { if (Unit* target = GetHitUnit()) // Deadly Poison - if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x10000, 0x80000, 0, GetCaster()->GetGUID())) + if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, flag128(0x10000, 0x80000, 0), GetCaster()->GetGUID())) _stackAmount = aurEff->GetBase()->GetStackAmount(); } @@ -326,7 +326,7 @@ class spell_rog_deadly_poison : public SpellScriptLoader continue; // Do not reproc deadly - if (spellInfo->SpellFamilyFlags == flag96(0x10000, 0x80000, 0)) + if (spellInfo->SpellFamilyFlags == flag128(0x10000, 0x80000, 0, 0)) continue; if (spellInfo->IsPositive()) diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index af4ff1f4485..14b305a591a 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -236,7 +236,7 @@ class spell_sha_chain_heal : public SpellScriptLoader if (firstHeal) { // Check if the target has Riptide - if (AuraEffect* aurEff = GetHitUnit()->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, GetCaster()->GetGUID())) + if (AuraEffect* aurEff = GetHitUnit()->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, flag128(0, 0, 0x10), GetCaster()->GetGUID())) { riptide = true; amount = aurEff->GetSpellInfo()->GetEffect(DIFFICULTY_NONE, EFFECT_2)->CalcValue(); @@ -880,7 +880,7 @@ class spell_sha_lava_lash : public SpellScriptLoader if (caster->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) { // Damage is increased by 25% if your off-hand weapon is enchanted with Flametongue. - if (caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0x200000, 0, 0)) + if (caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, flag128(0x200000, 0, 0))) AddPct(hitDamage, damage); SetHitDamage(hitDamage); } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index cac3178c320..a93d23fa233 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -154,7 +154,7 @@ class spell_warl_banish : public SpellScriptLoader /// Check if the target already has Banish, if so, do nothing. if (Unit* target = GetHitUnit()) { - if (target->GetAuraEffect(SPELL_AURA_SCHOOL_IMMUNITY, SPELLFAMILY_WARLOCK, 0, 0x08000000, 0)) + if (target->GetAuraEffect(SPELL_AURA_SCHOOL_IMMUNITY, SPELLFAMILY_WARLOCK, flag128(0, 0x08000000, 0))) { // No need to remove old aura since its removed due to not stack by current Banish aura PreventHitDefaultEffect(EFFECT_0); @@ -590,7 +590,7 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader Unit* caster = GetCaster(); if (Unit* target = GetHitUnit()) // Refresh corruption on target - if (AuraEffect* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, caster->GetGUID())) + if (AuraEffect* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, flag128(0x2, 0, 0), caster->GetGUID())) { uint32 damage = std::max(aurEff->GetAmount(), 0); sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h index 11c9ad3b27f..dc9e948966d 100644 --- a/src/server/shared/Common.h +++ b/src/server/shared/Common.h @@ -39,6 +39,9 @@ #include <sstream> #include <algorithm> +#include <boost/optional.hpp> +#include <boost/utility/in_place_factory.hpp> + #include "Debugging/Errors.h" #include "Threading/LockedQueue.h" @@ -133,22 +136,14 @@ LocaleConstant GetLocaleByName(const std::string& name); typedef std::vector<std::string> StringVector; -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif struct LocalizedString { char const* Str[TOTAL_LOCALES]; }; -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif // we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms) #ifdef max @@ -165,4 +160,8 @@ struct LocalizedString #define MAX_QUERY_LEN 32*1024 +//! Optional helper class to wrap optional values within. +template <typename T> +using Optional = boost::optional<T>; + #endif diff --git a/src/server/shared/Containers.h b/src/server/shared/Containers.h index 5dee18cb752..685acea05e3 100644 --- a/src/server/shared/Containers.h +++ b/src/server/shared/Containers.h @@ -92,6 +92,19 @@ namespace Trinity return false; } + + template<class K, class V, template<class, class, class...> class M, class... Rest> + void MultimapErasePair(M<K, V, Rest...>& multimap, K const& key, V const& value) + { + auto range = multimap.equal_range(key); + for (auto itr = range.first; itr != range.second;) + { + if (itr->second == value) + itr = multimap.erase(itr); + else + ++itr; + } + } } //! namespace Containers } diff --git a/src/server/shared/DataStores/DB2Store.h b/src/server/shared/DataStores/DB2Store.h index 4ce77c1cd28..c541a6651a3 100644 --- a/src/server/shared/DataStores/DB2Store.h +++ b/src/server/shared/DataStores/DB2Store.h @@ -112,6 +112,8 @@ public: void EraseRecord(uint32 id) override { if (id < _indexTableSize) _indexTable.AsT[id] = nullptr; } T const* LookupEntry(uint32 id) const { return (id >= _indexTableSize) ? nullptr : _indexTable.AsT[id]; } + T const* AssertEntry(uint32 id) const { return ASSERT_NOTNULL(LookupEntry(id)); } + std::string const& GetFileName() const { return _fileName; } uint32 GetNumRows() const { return _indexTableSize; } char const* GetFormat() const { return _format; } diff --git a/src/server/shared/Database/Field.h b/src/server/shared/Database/Field.h index c25e987808e..65d1c131e32 100644 --- a/src/server/shared/Database/Field.h +++ b/src/server/shared/Database/Field.h @@ -267,11 +267,7 @@ class Field Field(); ~Field(); - #if defined(__GNUC__) - #pragma pack(1) - #else #pragma pack(push, 1) - #endif struct { uint32 length; // Length (prepared strings only) @@ -279,11 +275,7 @@ class Field enum_field_types type; // Field type bool raw; // Raw bytes? (Prepared statement or ad hoc) } data; - #if defined(__GNUC__) - #pragma pack() - #else #pragma pack(pop) - #endif void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length); void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index cf871ab79a4..e9ce253d1cf 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -68,6 +68,8 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHAR_ZONE, "SELECT zone FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHARACTER_TEMPLATES, "SELECT id, name, description, level FROM character_template", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHARACTER_TEMPLATE_CLASSES, "SELECT factionGroup, class FROM character_template_class WHERE templateId = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM_ALL, "DELETE FROM character_battleground_random", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random WHERE guid = ?", CONNECTION_ASYNC); @@ -336,16 +338,13 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_PLAYER_HOMEBIND, "DELETE FROM character_homebind WHERE guid = ?", CONNECTION_ASYNC); // Corpse - PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, corpseGuid, guid FROM corpse WHERE corpseType <> 0", CONNECTION_SYNCH); - PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (corpseGuid, guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_DEL_CORPSE, "DELETE FROM corpse WHERE corpseGuid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_DEL_PLAYER_CORPSES, "DELETE FROM corpse WHERE guid = ? AND corpseType <> 0", CONNECTION_ASYNC); - PrepareStatement(CHAR_DEL_OLD_CORPSES, "DELETE FROM corpse WHERE corpseType = 0 OR time < (UNIX_TIMESTAMP(NOW()) - ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CORPSE_PHASES, "SELECT Guid, PhaseId FROM corpse_phases", CONNECTION_SYNCH); - PrepareStatement(CHAR_DEL_CORPSE_PHASES, "DELETE FROM corpse_phases WHERE Guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_DEL_PLAYER_CORPSES_PHASES, "DELETE FROM corpse_phases WHERE OwnerGuid = ? AND CorpseType <> 0", CONNECTION_ASYNC); - PrepareStatement(CHAR_DEL_OLD_CORPSE_PHASES, "DELETE FROM corpse_phases WHERE CorpseType = 0 OR Time < (UNIX_TIMESTAMP(NOW()) - ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_INS_CORPSE_PHASES, "INSERT INTO corpse_phases (Guid, PhaseId, OwnerGuid, Time, CorpseType) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CORPSE, "DELETE FROM corpse WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CORPSES_FROM_MAP, "DELETE cp, c FROM corpse_phases cp INNER JOIN corpse c ON cp.OwnerGuid = c.guid WHERE c.mapId = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CORPSE_PHASES, "SELECT cp.OwnerGuid, cp.PhaseId FROM corpse_phases cp LEFT JOIN corpse c ON cp.OwnerGuid = c.guid WHERE c.mapId = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_INS_CORPSE_PHASES, "INSERT INTO corpse_phases (OwnerGuid, PhaseId) VALUES (?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CORPSE_PHASES, "DELETE FROM corpse_phases WHERE OwnerGuid = ?", CONNECTION_ASYNC); // Creature respawn PrepareStatement(CHAR_SEL_CREATURE_RESPAWNS, "SELECT guid, respawnTime FROM creature_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH); @@ -682,4 +681,16 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_UPD_QUEST_TRACK_GM_COMPLETE, "UPDATE quest_tracker SET completed_by_gm = 1 WHERE id = ? AND character_guid = ? ORDER BY quest_accept_time DESC LIMIT 1", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_QUEST_TRACK_COMPLETE_TIME, "UPDATE quest_tracker SET quest_complete_time = NOW() WHERE id = ? AND character_guid = ? ORDER BY quest_accept_time DESC LIMIT 1", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_QUEST_TRACK_ABANDON_TIME, "UPDATE quest_tracker SET quest_abandon_time = NOW() WHERE id = ? AND character_guid = ? ORDER BY quest_accept_time DESC LIMIT 1", CONNECTION_ASYNC); + + // Garrison + PrepareStatement(CHAR_SEL_CHARACTER_GARRISON, "SELECT siteLevelId, followerActivationsRemainingToday FROM character_garrison WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_CHARACTER_GARRISON, "INSERT INTO character_garrison (guid, siteLevelId, followerActivationsRemainingToday) VALUES (?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CHARACTER_GARRISON, "DELETE FROM character_garrison WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS, "UPDATE character_garrison SET followerActivationsRemainingToday = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS, "SELECT buildingId FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS, "INSERT INTO character_garrison_blueprints (guid, buildingId) VALUES (?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS, "DELETE FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, "SELECT plotInstanceId, buildingId, timeBuilt, active FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS, "INSERT INTO character_garrison_buildings (guid, plotInstanceId, buildingId, timeBuilt, active) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS, "DELETE FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC); } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index e6c0a0db48c..53c42a0b852 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -71,6 +71,8 @@ enum CharacterDatabaseStatements CHAR_SEL_CHAR_ZONE, CHAR_SEL_CHAR_POSITION_XYZ, CHAR_SEL_CHAR_POSITION, + CHAR_SEL_CHARACTER_TEMPLATES, + CHAR_SEL_CHARACTER_TEMPLATE_CLASSES, CHAR_DEL_BATTLEGROUND_RANDOM_ALL, CHAR_DEL_BATTLEGROUND_RANDOM, @@ -292,13 +294,10 @@ enum CharacterDatabaseStatements CHAR_SEL_CORPSES, CHAR_INS_CORPSE, CHAR_DEL_CORPSE, - CHAR_DEL_PLAYER_CORPSES, - CHAR_DEL_OLD_CORPSES, + CHAR_DEL_CORPSES_FROM_MAP, CHAR_SEL_CORPSE_PHASES, - CHAR_DEL_CORPSE_PHASES, - CHAR_DEL_PLAYER_CORPSES_PHASES, - CHAR_DEL_OLD_CORPSE_PHASES, CHAR_INS_CORPSE_PHASES, + CHAR_DEL_CORPSE_PHASES, CHAR_SEL_CREATURE_RESPAWNS, CHAR_REP_CREATURE_RESPAWN, @@ -599,6 +598,17 @@ enum CharacterDatabaseStatements CHAR_UPD_QUEST_TRACK_COMPLETE_TIME, CHAR_UPD_QUEST_TRACK_ABANDON_TIME, + CHAR_SEL_CHARACTER_GARRISON, + CHAR_INS_CHARACTER_GARRISON, + CHAR_DEL_CHARACTER_GARRISON, + CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS, + CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS, + CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS, + CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS, + CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, + CHAR_INS_CHARACTER_GARRISON_BUILDINGS, + CHAR_DEL_CHARACTER_GARRISON_BUILDINGS, + MAX_CHARACTERDATABASE_STATEMENTS }; diff --git a/src/server/shared/Database/Implementation/HotfixDatabase.cpp b/src/server/shared/Database/Implementation/HotfixDatabase.cpp index e13863d9326..1afb118a06e 100644 --- a/src/server/shared/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/shared/Database/Implementation/HotfixDatabase.cpp @@ -39,12 +39,51 @@ void HotfixDatabaseConnection::DoPrepareStatements() PREPARE_LOCALE_STMT(HOTFIX_SEL_BROADCAST_TEXT, "SELECT ID, MaleText_lang, FemaleText_lang FROM broadcast_text_locale WHERE locale = ?", CONNECTION_SYNCH); // CurrencyTypes.db2 - PrepareStatement(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, CategoryID, Name, InventoryIcon1, InventoryIcon2, SpellWeight, SpellCategory, MaxQty, MaxEarnablePerWeek, Flags, Quality, Description FROM currency_types ORDER BY ID DESC", CONNECTION_SYNCH); - PREPARE_LOCALE_STMT(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, Name_lang, InventoryIcon1_lang, InventoryIcon2_lang, Description_lang FROM currency_types_locale WHERE locale = ?", CONNECTION_SYNCH); + PrepareStatement(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, CategoryID, Name, InventoryIcon1, InventoryIcon2, SpellWeight, SpellCategory, " + "MaxQty, MaxEarnablePerWeek, Flags, Quality, Description FROM currency_types ORDER BY ID DESC", CONNECTION_SYNCH); + PREPARE_LOCALE_STMT(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, Name_lang, InventoryIcon1_lang, InventoryIcon2_lang, " + "Description_lang FROM currency_types_locale WHERE locale = ?", CONNECTION_SYNCH); // CurvePoint.db2 PrepareStatement(HOTFIX_SEL_CURVE_POINT, "SELECT ID, CurveID, `Index`, X, Y FROM curve_point ORDER BY ID DESC", CONNECTION_SYNCH); + // GameObjects.db2 + PrepareStatement(HOTFIX_SEL_GAMEOBJECTS, "SELECT ID, MapID, DisplayID, PositionX, PositionY, PositionZ, RotationX, RotationY, RotationZ, RotationW, Size, " + "PhaseUseFlags, PhaseID, PhaseGroupID, Type, Data0, Data1, Data2, Data3, Data4, Data5, Data6, Data7, Name FROM gameobjects ORDER BY ID DESC", CONNECTION_SYNCH); + PREPARE_LOCALE_STMT(HOTFIX_SEL_GAMEOBJECTS, "SELECT ID, Name_lang FROM gameobjects_locale WHERE locale = ?", CONNECTION_SYNCH); + + // GarrBuilding.db2 + PrepareStatement(HOTFIX_SEL_GARR_BUILDING, "SELECT ID, HordeGameObjectID, AllianceGameObjectID, Unknown, Type, Level, NameAlliance, NameHorde, Description, " + "Tooltip, BuildDuration, CostCurrencyID, CostCurrencyAmount, HordeTexPrefixKitID, AllianceTexPrefixKitID, IconFileDataID, BonusAmount, Flags, " + "AllianceActivationScenePackageID, HordeActivationScenePackageID, MaxShipments, FollowerRequiredGarrAbilityID, FollowerGarrAbilityEffectID, CostMoney " + "FROM garr_building ORDER BY ID DESC", CONNECTION_SYNCH); + PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_BUILDING, "SELECT ID, NameAlliance_lang, NameHorde_lang, Description_lang, Tooltip_lang " + "FROM garr_building_locale WHERE locale = ?", CONNECTION_SYNCH); + + // GarrBuildingPlotInst.db2 + PrepareStatement(HOTFIX_SEL_GARR_BUILDING_PLOT_INST, "SELECT ID, GarrBuildingID, UiTextureAtlasMemberID, GarrSiteLevelPlotInstID, " + "LandmarkOffsetX, LandmarkOffsetY FROM garr_building_plot_inst ORDER BY ID DESC", CONNECTION_SYNCH); + + // GarrPlot.db2 + PrepareStatement(HOTFIX_SEL_GARR_PLOT, "SELECT ID, GarrPlotUICategoryID, PlotType, Flags, Name, MinCount, MaxCount, " + "AllianceConstructionGameObjectID, HordeConstructionGameObjectID FROM garr_plot ORDER BY ID DESC", CONNECTION_SYNCH); + PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_PLOT, "SELECT ID, Name_lang FROM garr_plot_locale WHERE locale = ?", CONNECTION_SYNCH); + + // GarrPlotBuilding.db2 + PrepareStatement(HOTFIX_SEL_GARR_PLOT_BUILDING, "SELECT ID, GarrPlotID, GarrBuildingID FROM garr_plot_building ORDER BY ID DESC", CONNECTION_SYNCH); + + // GarrPlotInstance.db2 + PrepareStatement(HOTFIX_SEL_GARR_PLOT_INSTANCE, "SELECT ID, GarrPlotID, Name FROM garr_plot_instance ORDER BY ID DESC", CONNECTION_SYNCH); + PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_PLOT_INSTANCE, "SELECT ID, Name_lang FROM garr_plot_instance_locale WHERE locale = ?", CONNECTION_SYNCH); + + // GarrSiteLevel.db2 + PrepareStatement(HOTFIX_SEL_GARR_SITE_LEVEL, "SELECT ID, Level, MapID, SiteID, UITextureKitID, TownHallX, TownHallY, MovieID, Level2, " + "UpgradeResourceCost, UpgradeMoneyCost FROM garr_site_level ORDER BY ID DESC", CONNECTION_SYNCH); + + // GarrSiteLevelPlotInst.db2 + PrepareStatement(HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST, "SELECT ID, GarrSiteLevelID, GarrPlotInstanceID, LandmarkX, LandmarkY, " + "Unknown FROM garr_site_level_plot_inst ORDER BY ID DESC", CONNECTION_SYNCH); + // Holidays.db2 PrepareStatement(HOTFIX_SEL_HOLIDAYS, "SELECT ID, Duration1, Duration2, Duration3, Duration4, Duration5, Duration6, Duration7, Duration8, Duration9, Duration10, " "Date1, Date2, Date3, Date4, Date5, Date6, Date7, Date8, Date9, Date10, Date11, Date12, Date13, Date14, Date15, Date16, Region, Looping, " diff --git a/src/server/shared/Database/Implementation/HotfixDatabase.h b/src/server/shared/Database/Implementation/HotfixDatabase.h index 3d8e528cd98..5d5f00dbf9e 100644 --- a/src/server/shared/Database/Implementation/HotfixDatabase.h +++ b/src/server/shared/Database/Implementation/HotfixDatabase.h @@ -54,6 +54,26 @@ enum HotfixDatabaseStatements HOTFIX_SEL_CURVE_POINT, + HOTFIX_SEL_GAMEOBJECTS, + HOTFIX_SEL_GAMEOBJECTS_LOCALE, + + HOTFIX_SEL_GARR_BUILDING, + HOTFIX_SEL_GARR_BUILDING_LOCALE, + + HOTFIX_SEL_GARR_BUILDING_PLOT_INST, + + HOTFIX_SEL_GARR_PLOT, + HOTFIX_SEL_GARR_PLOT_LOCALE, + + HOTFIX_SEL_GARR_PLOT_BUILDING, + + HOTFIX_SEL_GARR_PLOT_INSTANCE, + HOTFIX_SEL_GARR_PLOT_INSTANCE_LOCALE, + + HOTFIX_SEL_GARR_SITE_LEVEL, + + HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST, + HOTFIX_SEL_HOLIDAYS, HOTFIX_SEL_HOLIDAYS_LOCALE, @@ -86,7 +106,7 @@ enum HotfixDatabaseStatements HOTFIX_SEL_OVERRIDE_SPELL_DATA, HOTFIX_SEL_PHASE_GROUP, - + HOTFIX_SEL_QUEST_PACKAGE_ITEM, HOTFIX_SEL_SOUND_ENTRIES, diff --git a/src/server/shared/Dynamic/TypeContainer.h b/src/server/shared/Dynamic/TypeContainer.h index 2165945d119..9b264fdea7f 100644 --- a/src/server/shared/Dynamic/TypeContainer.h +++ b/src/server/shared/Dynamic/TypeContainer.h @@ -25,6 +25,7 @@ */ #include <map> +#include <unordered_map> #include <vector> #include "Define.h" #include "Dynamic/TypeList.h" @@ -35,54 +36,41 @@ * By itself its meaningless but collaborate along with TypeContainers, * it become the most powerfully container in the whole system. */ -template<class OBJECT> struct ContainerMapList +template<class OBJECT> +struct ContainerMapList { //std::map<OBJECT_HANDLE, OBJECT *> _element; GridRefManager<OBJECT> _element; }; -template<> struct ContainerMapList<TypeNull> /* nothing is in type null */ +template<> +struct ContainerMapList<TypeNull> /* nothing is in type null */ { }; -template<class H, class T> struct ContainerMapList<TypeList<H, T> > + +template<class H, class T> +struct ContainerMapList<TypeList<H, T> > { ContainerMapList<H> _elements; ContainerMapList<T> _TailElements; }; -/* - * @class ContaierArrayList is a multi-type container for - * array of elements. - */ -template<class OBJECT> struct ContainerArrayList +template<class OBJECT, class KEY_TYPE> +struct ContainerUnorderedMap { - std::vector<OBJECT> _element; + std::unordered_map<KEY_TYPE, OBJECT*> _element; }; -// termination condition -template<> struct ContainerArrayList<TypeNull> { }; -// recursion -template<class H, class T> struct ContainerArrayList<TypeList<H, T> > +template<class KEY_TYPE> +struct ContainerUnorderedMap<TypeNull, KEY_TYPE> { - ContainerArrayList<H> _elements; - ContainerArrayList<T> _TailElements; }; -/* - * @class ContainerList is a simple list of different types of elements - * - */ -template<class OBJECT> struct ContainerList +template<class H, class T, class KEY_TYPE> +struct ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE> { - OBJECT _element; -}; - -/* TypeNull is underfined */ -template<> struct ContainerList<TypeNull> { }; -template<class H, class T> struct ContainerList<TypeList<H, T> > -{ - ContainerList<H> _elements; - ContainerMapList<T> _TailElements; + ContainerUnorderedMap<H, KEY_TYPE> _elements; + ContainerUnorderedMap<T, KEY_TYPE> _TailElements; }; #include "TypeContainerFunctions.h" @@ -101,14 +89,16 @@ class TypeMapContainer template<class SPECIFIC_TYPE> size_t Count() const { return Trinity::Count(i_elements, (SPECIFIC_TYPE*)NULL); } /// inserts a specific object into the container - template<class SPECIFIC_TYPE> bool insert(SPECIFIC_TYPE *obj) + template<class SPECIFIC_TYPE> + bool insert(SPECIFIC_TYPE *obj) { SPECIFIC_TYPE* t = Trinity::Insert(i_elements, obj); return (t != NULL); } /// Removes the object from the container, and returns the removed object - //template<class SPECIFIC_TYPE> bool remove(SPECIFIC_TYPE* obj) + //template<class SPECIFIC_TYPE> + //bool remove(SPECIFIC_TYPE* obj) //{ // SPECIFIC_TYPE* t = Trinity::Remove(i_elements, obj); // return (t != NULL); @@ -120,5 +110,34 @@ class TypeMapContainer private: ContainerMapList<OBJECT_TYPES> i_elements; }; -#endif +template<class OBJECT_TYPES, class KEY_TYPE> +class TypeUnorderedMapContainer +{ +public: + template<class SPECIFIC_TYPE> + bool Insert(KEY_TYPE const& handle, SPECIFIC_TYPE* obj) + { + return Trinity::Insert(_elements, handle, obj); + } + + template<class SPECIFIC_TYPE> + bool Remove(KEY_TYPE const& handle) + { + return Trinity::Remove(_elements, handle, (SPECIFIC_TYPE*)NULL); + } + + template<class SPECIFIC_TYPE> + SPECIFIC_TYPE* Find(KEY_TYPE const& handle) + { + return Trinity::Find(_elements, handle, (SPECIFIC_TYPE*)NULL); + } + + ContainerUnorderedMap<OBJECT_TYPES, KEY_TYPE>& GetElements() { return _elements; } + ContainerUnorderedMap<OBJECT_TYPES, KEY_TYPE> const& GetElements() const { return _elements; } + +private: + ContainerUnorderedMap<OBJECT_TYPES, KEY_TYPE> _elements; +}; + +#endif diff --git a/src/server/shared/Dynamic/TypeContainerFunctions.h b/src/server/shared/Dynamic/TypeContainerFunctions.h index a89f5bd10d4..4a841cfda56 100644 --- a/src/server/shared/Dynamic/TypeContainerFunctions.h +++ b/src/server/shared/Dynamic/TypeContainerFunctions.h @@ -28,60 +28,164 @@ #include "Define.h" #include "Dynamic/TypeList.h" #include <map> +#include <unordered_map> namespace Trinity { + // Helpers + // Insert helpers + template<class SPECIFIC_TYPE, class KEY_TYPE> + bool Insert(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE>& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* obj) + { + auto i = elements._element.find(handle); + if (i == elements._element.end()) + { + elements._element[handle] = obj; + return true; + } + else + { + ASSERT(i->second == obj, "Object with certain key already in but objects are different!"); + return false; + } + } + + template<class SPECIFIC_TYPE, class KEY_TYPE> + bool Insert(ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) + { + return false; + } + + template<class SPECIFIC_TYPE, class KEY_TYPE, class T> + bool Insert(ContainerUnorderedMap<T, KEY_TYPE>& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) + { + return false; + } + + template<class SPECIFIC_TYPE, class KEY_TYPE, class H, class T> + bool Insert(ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE>& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* obj) + { + bool ret = Insert(elements._elements, handle, obj); + return ret ? ret : Insert(elements._TailElements, handle, obj); + } + + // Find helpers + template<class SPECIFIC_TYPE, class KEY_TYPE> + SPECIFIC_TYPE* Find(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE> const& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* /*obj*/) + { + auto i = elements._element.find(handle); + if (i == elements._element.end()) + return nullptr; + else + return i->second; + } + + template<class SPECIFIC_TYPE, class KEY_TYPE> + SPECIFIC_TYPE* Find(ContainerUnorderedMap<TypeNull, KEY_TYPE> const& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) + { + return nullptr; + } + + template<class SPECIFIC_TYPE, class KEY_TYPE, class T> + SPECIFIC_TYPE* Find(ContainerUnorderedMap<T, KEY_TYPE> const& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) + { + return nullptr; + } + + template<class SPECIFIC_TYPE, class KEY_TYPE, class H, class T> + SPECIFIC_TYPE* Find(ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE> const& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* /*obj*/) + { + SPECIFIC_TYPE* ret = Find(elements._elements, handle, (SPECIFIC_TYPE*)nullptr); + return ret ? ret : Find(elements._TailElements, handle, (SPECIFIC_TYPE*)nullptr); + } + + // Erase helpers + template<class SPECIFIC_TYPE, class KEY_TYPE> + bool Remove(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE>& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* /*obj*/) + { + elements._element.erase(handle); + return true; + } + + template<class SPECIFIC_TYPE, class KEY_TYPE> + bool Remove(ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) + { + return false; + } + + template<class SPECIFIC_TYPE, class KEY_TYPE, class T> + bool Remove(ContainerUnorderedMap<T, KEY_TYPE>& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) + { + return false; + } + + template<class SPECIFIC_TYPE, class KEY_TYPE, class H, class T> + bool Remove(ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE>& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* /*obj*/) + { + bool ret = Remove(elements._elements, handle, (SPECIFIC_TYPE*)nullptr); + return ret ? ret : Remove(elements._TailElements, handle, (SPECIFIC_TYPE*)nullptr); + } + /* ContainerMapList Helpers */ // count functions - template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<SPECIFIC_TYPE> &elements, SPECIFIC_TYPE* /*fake*/) + template<class SPECIFIC_TYPE> + size_t Count(ContainerMapList<SPECIFIC_TYPE> const& elements, SPECIFIC_TYPE* /*fake*/) { return elements._element.getSize(); } - template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE* /*fake*/) + template<class SPECIFIC_TYPE> + size_t Count(ContainerMapList<TypeNull> const& /*elements*/, SPECIFIC_TYPE* /*fake*/) { return 0; } - template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE* /*fake*/) + template<class SPECIFIC_TYPE, class T> + size_t Count(ContainerMapList<T> const& /*elements*/, SPECIFIC_TYPE* /*fake*/) { return 0; } - template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<TypeList<SPECIFIC_TYPE, T> >&elements, SPECIFIC_TYPE* fake) + template<class SPECIFIC_TYPE, class T> + size_t Count(ContainerMapList<TypeList<SPECIFIC_TYPE, T>> const& elements, SPECIFIC_TYPE* fake) { return Count(elements._elements, fake); } - template<class SPECIFIC_TYPE, class H, class T> size_t Count(const ContainerMapList<TypeList<H, T> >&elements, SPECIFIC_TYPE* fake) + template<class SPECIFIC_TYPE, class H, class T> + size_t Count(ContainerMapList<TypeList<H, T>> const& elements, SPECIFIC_TYPE* fake) { return Count(elements._TailElements, fake); } // non-const insert functions - template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE> &elements, SPECIFIC_TYPE *obj) + template<class SPECIFIC_TYPE> + SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE>& elements, SPECIFIC_TYPE* obj) { //elements._element[hdl] = obj; obj->AddToGrid(elements._element); return obj; } - template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE * /*obj*/) + template<class SPECIFIC_TYPE> + SPECIFIC_TYPE* Insert(ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*obj*/) { - return NULL; + return nullptr; } // this is a missed - template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Insert(ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE * /*obj*/) + template<class SPECIFIC_TYPE, class T> + SPECIFIC_TYPE* Insert(ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*obj*/) { - return NULL; // a missed + return nullptr; // a missed } // Recursion - template<class SPECIFIC_TYPE, class H, class T> SPECIFIC_TYPE* Insert(ContainerMapList<TypeList<H, T> >&elements, SPECIFIC_TYPE *obj) + template<class SPECIFIC_TYPE, class H, class T> + SPECIFIC_TYPE* Insert(ContainerMapList<TypeList<H, T>>& elements, SPECIFIC_TYPE* obj) { - SPECIFIC_TYPE* t= Insert(elements._elements, obj); - return (t != NULL ? t : Insert(elements._TailElements, obj)); + SPECIFIC_TYPE* t = Insert(elements._elements, obj); + return (t != nullptr ? t : Insert(elements._TailElements, obj)); } //// non-const remove method @@ -93,20 +197,20 @@ namespace Trinity //template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Remove(ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE * /*obj*/) //{ - // return NULL; + // return nullptr; //} //// this is a missed //template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Remove(ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE * /*obj*/) //{ - // return NULL; // a missed + // return nullptr; // a missed //} //template<class SPECIFIC_TYPE, class T, class H> SPECIFIC_TYPE* Remove(ContainerMapList<TypeList<H, T> > &elements, SPECIFIC_TYPE *obj) //{ // // The head element is bad // SPECIFIC_TYPE* t = Remove(elements._elements, obj); - // return ( t != NULL ? t : Remove(elements._TailElements, obj) ); + // return (t != nullptr ? t : Remove(elements._TailElements, obj)); //} } #endif diff --git a/src/server/shared/Dynamic/TypeContainerVisitor.h b/src/server/shared/Dynamic/TypeContainerVisitor.h index 514b52d3dfe..e10a2331e25 100644 --- a/src/server/shared/Dynamic/TypeContainerVisitor.h +++ b/src/server/shared/Dynamic/TypeContainerVisitor.h @@ -37,21 +37,6 @@ template<class VISITOR, class TYPE_CONTAINER> void VisitorHelper(VISITOR &v, TYP v.Visit(c); } -// terminate condition for container list -template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerList<TypeNull> &/*c*/) { } - -template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerList<T> &c) -{ - v.Visit(c._element); -} - -// recursion for container list -template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerList<TypeList<H, T> > &c) -{ - VisitorHelper(v, c._elements); - VisitorHelper(v, c._TailElements); -} - // terminate condition container map list template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerMapList<TypeNull> &/*c*/) { } @@ -67,23 +52,31 @@ template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, Contain VisitorHelper(v, c._TailElements); } -// array list -template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerArrayList<T> &c) +// for TypeMapContainer +template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR &v, TypeMapContainer<OBJECT_TYPES> &c) { - v.Visit(c._element); + VisitorHelper(v, c.GetElements()); } -template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerArrayList<TypeNull> &/*c*/) { } +// TypeUnorderedMapContainer +template<class VISITOR, class KEY_TYPE> +void VisitorHelper(VISITOR& /*v*/, ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*c*/) { } + +template<class VISITOR, class KEY_TYPE, class T> +void VisitorHelper(VISITOR& v, ContainerUnorderedMap<T, KEY_TYPE>& c) +{ + v.Visit(c._element); +} -// recursion -template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerArrayList<TypeList<H, T> > &c) +template<class VISITOR, class KEY_TYPE, class H, class T> +void VisitorHelper(VISITOR& v, ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE>& c) { VisitorHelper(v, c._elements); VisitorHelper(v, c._TailElements); } -// for TypeMapContainer -template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR &v, TypeMapContainer<OBJECT_TYPES> &c) +template<class VISITOR, class OBJECT_TYPES, class KEY_TYPE> +void VisitorHelper(VISITOR& v, TypeUnorderedMapContainer<OBJECT_TYPES, KEY_TYPE>& c) { VisitorHelper(v, c.GetElements()); } diff --git a/src/server/shared/Dynamic/TypeList.h b/src/server/shared/Dynamic/TypeList.h index f1ccca9b043..f0355929700 100644 --- a/src/server/shared/Dynamic/TypeList.h +++ b/src/server/shared/Dynamic/TypeList.h @@ -40,5 +40,6 @@ struct TypeList #define TYPELIST_3(T1, T2, T3) TypeList<T1, TYPELIST_2(T2, T3) > #define TYPELIST_4(T1, T2, T3, T4) TypeList<T1, TYPELIST_3(T2, T3, T4) > #define TYPELIST_5(T1, T2, T3, T4, T5) TypeList<T1, TYPELIST_4(T2, T3, T4, T5) > +#define TYPELIST_6(T1, T2, T3, T4, T5, T6) TypeList<T1, TYPELIST_5(T2, T3, T4, T5, T6) > #endif diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp index ba23d879ec2..31db3ae1b86 100644 --- a/src/server/shared/Logging/Appender.cpp +++ b/src/server/shared/Logging/Appender.cpp @@ -88,7 +88,7 @@ void Appender::write(LogMessage* message) if (flags & APPENDER_FLAGS_PREFIX_LOGFILTERTYPE) ss << '[' << message->type << "] "; - message->prefix = std::move(ss.str()); + message->prefix = ss.str(); _write(message); } diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp index 3892adbe3be..5a8d610a36b 100644 --- a/src/server/shared/Logging/AppenderFile.cpp +++ b/src/server/shared/Logging/AppenderFile.cpp @@ -55,7 +55,7 @@ void AppenderFile::_write(LogMessage const* message) FILE* file = OpenFile(namebuf, "a", backup || exceedMaxSize); if (!file) return; - fprintf(file, "%s%s", message->prefix.c_str(), message->text.c_str()); + fprintf(file, "%s%s\n", message->prefix.c_str(), message->text.c_str()); fflush(file); fileSize += uint64(message->Size()); fclose(file); diff --git a/src/server/shared/Networking/MessageBuffer.h b/src/server/shared/Networking/MessageBuffer.h index 802442b5c31..d0c65f05c3d 100644 --- a/src/server/shared/Networking/MessageBuffer.h +++ b/src/server/shared/Networking/MessageBuffer.h @@ -55,9 +55,9 @@ public: uint8* GetBasePointer() { return _storage.data(); } - uint8* GetReadPointer() { return &_storage[_rpos]; } + uint8* GetReadPointer() { return GetBasePointer() + _rpos; } - uint8* GetWritePointer() { return &_storage[_wpos]; } + uint8* GetWritePointer() { return GetBasePointer() + _wpos; } void ReadCompleted(size_type bytes) { _rpos += bytes; } diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index 0ac23a96224..d337e07ff52 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -50,6 +50,7 @@ public: virtual ~Socket() { + _closed = true; boost::system::error_code error; _socket.close(error); } @@ -97,26 +98,6 @@ public: std::bind(&Socket<T>::ReadHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } - void ReadData(std::size_t size) - { - if (!IsOpen()) - return; - - boost::system::error_code error; - - std::size_t bytesRead = boost::asio::read(_socket, boost::asio::buffer(_readBuffer.GetWritePointer(), size), error); - - _readBuffer.WriteCompleted(bytesRead); - - if (error || bytesRead != size) - { - TC_LOG_DEBUG("network", "Socket::ReadData: %s errored with: %i (%s)", GetRemoteIpAddress().to_string().c_str(), error.value(), - error.message().c_str()); - - CloseSocket(); - } - } - void QueuePacket(MessageBuffer&& buffer, std::unique_lock<std::mutex>& guard) { _writeQueue.push(std::move(buffer)); diff --git a/src/server/shared/Threading/ProducerConsumerQueue.h b/src/server/shared/Threading/ProducerConsumerQueue.h index 67150a20d80..3158e3deb24 100644 --- a/src/server/shared/Threading/ProducerConsumerQueue.h +++ b/src/server/shared/Threading/ProducerConsumerQueue.h @@ -70,7 +70,9 @@ public: { std::unique_lock<std::mutex> lock(_queueLock); - _condition.wait(lock, [this]() { return !_queue.empty() || _shutdown; }); + // we could be using .wait(lock, predicate) overload here but some threading error analysis tools produce false positives + while (_queue.empty() && !_shutdown) + _condition.wait(lock); if (_queue.empty() || _shutdown) return; diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp index 73873c59775..9806151b4c4 100644 --- a/src/server/shared/Updater/DBUpdater.cpp +++ b/src/server/shared/Updater/DBUpdater.cpp @@ -26,7 +26,6 @@ #include <iostream> #include <unordered_map> #include <boost/process.hpp> -#include <boost/process/mitigate.hpp> #include <boost/iostreams/device/file_descriptor.hpp> #include <boost/system/system_error.hpp> diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h index 9a8514ea5ca..9605efe18ec 100644 --- a/src/server/shared/Utilities/Util.h +++ b/src/server/shared/Utilities/Util.h @@ -30,27 +30,6 @@ #include <stdarg.h> #include <cstring> -template<typename T> -struct Optional -{ - Optional() : Value(), HasValue(false) { } - - T Value; - bool HasValue; - - inline void Set(T const& v) - { - HasValue = true; - Value = v; - } - - inline void Clear() - { - HasValue = false; - Value = T(); - } -}; - // Searcher for map of structs template<typename T, class S> struct Finder { @@ -404,32 +383,41 @@ class HookList } }; -template<uint8 T_size> -class flag +class flag128 { -protected: - uint32 part[T_size]; +private: + uint32 part[4]; public: - flag() + flag128(uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0, uint32 p4 = 0) { - memset(part, 0, sizeof(uint32)*T_size); + part[0] = p1; + part[1] = p2; + part[2] = p3; + part[3] = p4; } - flag(uint32 first, ...) + inline bool IsEqual(uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0, uint32 p4 = 0) const { - va_list ap; - part[0] = first; + return (part[0] == p1 && part[1] == p2 && part[2] == p3 && part[3] == p4); + } - va_start(ap, first); - for (int i = 1; i < T_size; ++i) - part[i] = va_arg(ap, uint32); - va_end(ap); + inline bool HasFlag(uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0, uint32 p4 = 0) const + { + return (part[0] & p1 || part[1] & p2 || part[2] & p3 || part[3] & p4); + } + + inline void Set(uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0, uint32 p4 = 0) + { + part[0] = p1; + part[1] = p2; + part[2] = p3; + part[3] = p4; } - inline bool operator <(const flag<T_size>& right) const + inline bool operator <(const flag128 &right) const { - for (uint8 i = T_size; i > 0; --i) + for (uint8 i = 4; i > 0; --i) { if (part[i - 1] < right.part[i - 1]) return true; @@ -439,85 +427,84 @@ public: return false; } - inline bool operator ==(const flag<T_size>& right) const + inline bool operator ==(const flag128 &right) const { - for (uint8 i = 0; i < T_size; ++i) - if (part[i] != right.part[i]) - return false; - return true; + return + ( + part[0] == right.part[0] && + part[1] == right.part[1] && + part[2] == right.part[2] && + part[3] == right.part[3] + ); } - inline bool operator !=(const flag<T_size>& right) const + inline bool operator !=(const flag128 &right) const { return !this->operator ==(right); } - inline flag<T_size>& operator =(const flag<T_size>& right) + inline flag128 & operator =(const flag128 &right) { - for (uint8 i = 0; i < T_size; ++i) - part[i] = right.part[i]; + part[0] = right.part[0]; + part[1] = right.part[1]; + part[2] = right.part[2]; + part[3] = right.part[3]; return *this; } - inline flag<T_size> operator &(const flag<T_size> &right) const + inline flag128 operator &(const flag128 &right) const { - flag<T_size> fl; - for (uint8 i = 0; i < T_size; ++i) - fl.part[i] = part[i] & right.part[i]; - return fl; + return flag128(part[0] & right.part[0], part[1] & right.part[1], + part[2] & right.part[2], part[3] & right.part[3]); } - inline flag<T_size>& operator &=(const flag<T_size> &right) + inline flag128 & operator &=(const flag128 &right) { - for (uint8 i = 0; i < T_size; ++i) - part[i] &= right.part[i]; + part[0] &= right.part[0]; + part[1] &= right.part[1]; + part[2] &= right.part[2]; + part[3] &= right.part[3]; return *this; } - inline flag<T_size> operator |(const flag<T_size> &right) const + inline flag128 operator |(const flag128 &right) const { - flag<T_size> fl; - for (uint8 i = 0; i < T_size; ++i) - fl.part[i] = part[i] | right.part[i]; - return fl; + return flag128(part[0] | right.part[0], part[1] | right.part[1], + part[2] | right.part[2], part[3] | right.part[3]); } - inline flag<T_size>& operator |=(const flag<T_size> &right) + inline flag128 & operator |=(const flag128 &right) { - for (uint8 i = 0; i < T_size; ++i) - part[i] |= right.part[i]; + part[0] |= right.part[0]; + part[1] |= right.part[1]; + part[2] |= right.part[2]; + part[3] |= right.part[3]; return *this; } - inline flag<T_size> operator ~() const + inline flag128 operator ~() const { - flag<T_size> fl; - for (uint8 i = 0; i < T_size; ++i) - fl.part[i] = ~part[i]; - return fl; + return flag128(~part[0], ~part[1], ~part[2], ~part[3]); } - inline flag<T_size> operator ^(const flag<T_size>& right) const + inline flag128 operator ^(const flag128 &right) const { - flag<T_size> fl; - for (uint8 i = 0; i < T_size; ++i) - fl.part[i] = part[i] ^ right.part[i]; - return fl; + return flag128(part[0] ^ right.part[0], part[1] ^ right.part[1], + part[2] ^ right.part[2], part[3] ^ right.part[3]); } - inline flag<T_size>& operator ^=(const flag<T_size>& right) + inline flag128 & operator ^=(const flag128 &right) { - for (uint8 i = 0; i < T_size; ++i) - part[i] ^= right.part[i]; + part[0] ^= right.part[0]; + part[1] ^= right.part[1]; + part[2] ^= right.part[2]; + part[3] ^= right.part[3]; return *this; } inline operator bool() const { - for (uint8 i = 0; i < T_size; ++i) - if (part[i] != 0) - return true; - return false; + return (part[0] != 0 || part[1] != 0 || part[2] != 0 || part[3] != 0); } inline bool operator !() const @@ -525,20 +512,17 @@ public: return !this->operator bool(); } - inline uint32& operator [](uint8 el) + inline uint32 & operator [](uint8 el) { return part[el]; } - inline const uint32& operator [](uint8 el) const + inline const uint32 & operator [](uint8 el) const { return part[el]; } }; -typedef flag<3> flag96; -typedef flag<4> flag128; - enum ComparisionType { COMP_TYPE_EQ = 0, diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index a1e8ba74514..d4a6915894d 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -272,10 +272,10 @@ extern int main(int argc, char** argv) sWorldSocketMgr.StopNetwork(); sInstanceSaveMgr->Unload(); + sOutdoorPvPMgr->Die(); // unload it before MapManager sMapMgr->UnloadAll(); // unload all grids (including locked in memory) sObjectAccessor->UnloadAll(); // unload 'i_player2corpse' storage and remove from world sScriptMgr->Unload(); - sOutdoorPvPMgr->Die(); // set server offline LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realmHandle.Index); diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index ab9774a3038..9059867dce4 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -402,7 +402,7 @@ void ReadLiquidTypeTableDBC() // Map file format data static char const* MAP_MAGIC = "MAPS"; -static char const* MAP_VERSION_MAGIC = "v1.4"; +static char const* MAP_VERSION_MAGIC = "v1.5"; static char const* MAP_AREA_MAGIC = "AREA"; static char const* MAP_HEIGHT_MAGIC = "MHGT"; static char const* MAP_LIQUID_MAGIC = "MLIQ"; @@ -1091,7 +1091,7 @@ void ExtractMaps(uint32 build) continue; sprintf(storagePath, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y); - sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x); + sprintf(output_filename, "%s/maps/%04u_%02u_%02u.map", output_path, map_ids[z].id, y, x); ConvertADT(storagePath, output_filename, y, x, build); sprintf(storagePath, "World\\Maps\\%s\\%s_%u_%u_obj0.adt", map_ids[z].name, map_ids[z].name, x, y); diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt index 48e30b1c3cf..4dfe106bd3e 100644 --- a/src/tools/mmaps_generator/CMakeLists.txt +++ b/src/tools/mmaps_generator/CMakeLists.txt @@ -12,7 +12,7 @@ file(GLOB_RECURSE mmap_gen_sources *.cpp *.h) set(mmap_gen_Includes ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/libmpq + ${CMAKE_SOURCE_DIR}/dep/cppformat ${CMAKE_SOURCE_DIR}/dep/zlib ${CMAKE_SOURCE_DIR}/dep/bzip2 ${CMAKE_SOURCE_DIR}/dep/g3dlite/include @@ -30,13 +30,6 @@ set(mmap_gen_Includes ${CMAKE_SOURCE_DIR}/src/server/collision/Models ) -if( WIN32 ) - set(mmap_gen_Includes - ${mmap_gen_Includes} - ${CMAKE_SOURCE_DIR}/dep/libmpq/win - ) -endif() - include_directories(${mmap_gen_Includes}) add_executable(mmaps_generator ${mmap_gen_sources}) @@ -46,6 +39,7 @@ target_link_libraries(mmaps_generator g3dlib Recast Detour + format ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 412ba7a0055..b3d495f8a7e 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -19,6 +19,7 @@ #include "PathCommon.h" #include "MapBuilder.h" +#include "StringFormat.h" #include "MapTree.h" #include "ModelInstance.h" @@ -28,7 +29,7 @@ #include "DetourCommon.h" #define MMAP_MAGIC 0x4d4d4150 // 'MMAP' -#define MMAP_VERSION 6 +#define MMAP_VERSION 7 struct MmapTileHeader { @@ -83,13 +84,12 @@ namespace MMAP { std::vector<std::string> files; uint32 mapID, tileX, tileY, tileID, count = 0; - char filter[12]; printf("Discovering maps... "); getDirContents(files, "maps"); for (uint32 i = 0; i < files.size(); ++i) { - mapID = uint32(atoi(files[i].substr(0,3).c_str())); + mapID = uint32(atoi(files[i].substr(0, 4).c_str())); if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end()) { m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>)); @@ -101,7 +101,7 @@ namespace MMAP getDirContents(files, "vmaps", "*.vmtree"); for (uint32 i = 0; i < files.size(); ++i) { - mapID = uint32(atoi(files[i].substr(0,3).c_str())); + mapID = uint32(atoi(files[i].substr(0, 4).c_str())); if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end()) { m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>)); @@ -117,26 +117,24 @@ namespace MMAP std::set<uint32>* tiles = (*itr).m_tiles; mapID = (*itr).m_mapId; - sprintf(filter, "%03u*.vmtile", mapID); files.clear(); - getDirContents(files, "vmaps", filter); + getDirContents(files, "vmaps", Trinity::StringFormat("%04u*.vmtile", mapID)); for (uint32 i = 0; i < files.size(); ++i) { - tileX = uint32(atoi(files[i].substr(7,2).c_str())); - tileY = uint32(atoi(files[i].substr(4,2).c_str())); + tileX = uint32(atoi(files[i].substr(8, 2).c_str())); + tileY = uint32(atoi(files[i].substr(5, 2).c_str())); tileID = StaticMapTree::packTileID(tileY, tileX); tiles->insert(tileID); count++; } - sprintf(filter, "%03u*", mapID); files.clear(); - getDirContents(files, "maps", filter); + getDirContents(files, "maps", Trinity::StringFormat("%04u*", mapID)); for (uint32 i = 0; i < files.size(); ++i) { - tileY = uint32(atoi(files[i].substr(3,2).c_str())); - tileX = uint32(atoi(files[i].substr(5,2).c_str())); + tileY = uint32(atoi(files[i].substr(5, 2).c_str())); + tileX = uint32(atoi(files[i].substr(8, 2).c_str())); tileID = StaticMapTree::packTileID(tileX, tileY); if (tiles->insert(tileID).second) @@ -386,12 +384,12 @@ namespace MMAP buildNavMesh(mapID, navMesh); if (!navMesh) { - printf("[Map %03i] Failed creating navmesh!\n", mapID); + printf("[Map %04i] Failed creating navmesh!\n", mapID); return; } // now start building mmtiles for each tile - printf("[Map %03i] We have %u tiles. \n", mapID, (unsigned int)tiles->size()); + printf("[Map %04i] We have %u tiles. \n", mapID, (unsigned int)tiles->size()); for (std::set<uint32>::iterator it = tiles->begin(); it != tiles->end(); ++it) { uint32 tileX, tileY; @@ -408,13 +406,13 @@ namespace MMAP dtFreeNavMesh(navMesh); } - printf("[Map %03i] Complete!\n", mapID); + printf("[Map %04u] Complete!\n", mapID); } /**************************************************************************/ void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh) { - printf("[Map %03i] Building tile [%02u,%02u]\n", mapID, tileX, tileY); + printf("[Map %04i] Building tile [%02u,%02u]\n", mapID, tileX, tileY); MeshData meshData; @@ -500,22 +498,22 @@ namespace MMAP navMeshParams.maxPolys = maxPolysPerTile; navMesh = dtAllocNavMesh(); - printf("[Map %03i] Creating navMesh...\n", mapID); + printf("[Map %04u] Creating navMesh...\n", mapID); if (!navMesh->init(&navMeshParams)) { - printf("[Map %03i] Failed creating navmesh! \n", mapID); + printf("[Map %04u] Failed creating navmesh! \n", mapID); return; } char fileName[25]; - sprintf(fileName, "mmaps/%03u.mmap", mapID); + sprintf(fileName, "mmaps/%04u.mmap", mapID); FILE* file = fopen(fileName, "wb"); if (!file) { dtFreeNavMesh(navMesh); char message[1024]; - sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName); + sprintf(message, "[Map %04u] Failed to open %s for writing!\n", mapID, fileName); perror(message); return; } @@ -531,9 +529,8 @@ namespace MMAP dtNavMesh* navMesh) { // console output - char tileString[20]; - sprintf(tileString, "[Map %03i] [%02i,%02i]: ", mapID, tileX, tileY); - printf("%s Building movemap tiles...\n", tileString); + std::string tileString = Trinity::StringFormat("[Map %04u] [%02i,%02i]: ", mapID, tileX, tileY); + printf("%s Building movemap tiles...\n", tileString.c_str()); IntermediateValues iv; @@ -614,7 +611,7 @@ namespace MMAP tile.solid = rcAllocHeightfield(); if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch)) { - printf("%s Failed building heightfield! \n", tileString); + printf("%s Failed building heightfield! \n", tileString.c_str()); continue; } @@ -635,33 +632,33 @@ namespace MMAP tile.chf = rcAllocCompactHeightfield(); if (!tile.chf || !rcBuildCompactHeightfield(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf)) { - printf("%s Failed compacting heightfield! \n", tileString); + printf("%s Failed compacting heightfield! \n", tileString.c_str()); continue; } // build polymesh intermediates if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *tile.chf)) { - printf("%s Failed eroding area! \n", tileString); + printf("%s Failed eroding area! \n", tileString.c_str()); continue; } if (!rcBuildDistanceField(m_rcContext, *tile.chf)) { - printf("%s Failed building distance field! \n", tileString); + printf("%s Failed building distance field! \n", tileString.c_str()); continue; } if (!rcBuildRegions(m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea)) { - printf("%s Failed building regions! \n", tileString); + printf("%s Failed building regions! \n", tileString.c_str()); continue; } tile.cset = rcAllocContourSet(); if (!tile.cset || !rcBuildContours(m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset)) { - printf("%s Failed building contours! \n", tileString); + printf("%s Failed building contours! \n", tileString.c_str()); continue; } @@ -669,14 +666,14 @@ namespace MMAP tile.pmesh = rcAllocPolyMesh(); if (!tile.pmesh || !rcBuildPolyMesh(m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh)) { - printf("%s Failed building polymesh! \n", tileString); + printf("%s Failed building polymesh! \n", tileString.c_str()); continue; } tile.dmesh = rcAllocPolyMeshDetail(); if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg.detailSampleMaxError, *tile.dmesh)) { - printf("%s Failed building polymesh detail! \n", tileString); + printf("%s Failed building polymesh detail! \n", tileString.c_str()); continue; } @@ -699,7 +696,7 @@ namespace MMAP iv.polyMesh = rcAllocPolyMesh(); if (!iv.polyMesh) { - printf("%s alloc iv.polyMesh FIALED!\n", tileString); + printf("%s alloc iv.polyMesh FAILED!\n", tileString.c_str()); delete[] pmmerge; delete[] dmmerge; delete[] tiles; @@ -710,7 +707,7 @@ namespace MMAP iv.polyMeshDetail = rcAllocPolyMeshDetail(); if (!iv.polyMeshDetail) { - printf("%s alloc m_dmesh FIALED!\n", tileString); + printf("%s alloc m_dmesh FAILED!\n", tileString.c_str()); delete[] pmmerge; delete[] dmmerge; delete[] tiles; @@ -774,12 +771,12 @@ namespace MMAP // so we have a clear error message if (params.nvp > DT_VERTS_PER_POLYGON) { - printf("%s Invalid verts-per-polygon value! \n", tileString); + printf("%s Invalid verts-per-polygon value! \n", tileString.c_str()); break; } if (params.vertCount >= 0xffff) { - printf("%s Too many vertices! \n", tileString); + printf("%s Too many vertices! \n", tileString.c_str()); break; } if (!params.vertCount || !params.verts) @@ -788,7 +785,7 @@ namespace MMAP // loaded but those models don't span into this tile // message is an annoyance - //printf("%sNo vertices to build tile! \n", tileString); + //printf("%sNo vertices to build tile! \n", tileString.c_str()); break; } if (!params.polyCount || !params.polys || @@ -797,47 +794,47 @@ namespace MMAP // we have flat tiles with no actual geometry - don't build those, its useless // keep in mind that we do output those into debug info // drop tiles with only exact count - some tiles may have geometry while having less tiles - printf("%s No polygons to build on tile! \n", tileString); + printf("%s No polygons to build on tile! \n", tileString.c_str()); break; } if (!params.detailMeshes || !params.detailVerts || !params.detailTris) { - printf("%s No detail mesh to build tile! \n", tileString); + printf("%s No detail mesh to build tile! \n", tileString.c_str()); break; } - printf("%s Building navmesh tile...\n", tileString); + printf("%s Building navmesh tile...\n", tileString.c_str()); if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) { - printf("%s Failed building navmesh tile! \n", tileString); + printf("%s Failed building navmesh tile! \n", tileString.c_str()); break; } dtTileRef tileRef = 0; - printf("%s Adding tile to navmesh...\n", tileString); + printf("%s Adding tile to navmesh...\n", tileString.c_str()); // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile // is removed via removeTile() dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef); if (!tileRef || dtResult != DT_SUCCESS) { - printf("%s Failed adding tile to navmesh! \n", tileString); + printf("%s Failed adding tile to navmesh! \n", tileString.c_str()); break; } // file output char fileName[255]; - sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX); + sprintf(fileName, "mmaps/%04u%02i%02i.mmtile", mapID, tileY, tileX); FILE* file = fopen(fileName, "wb"); if (!file) { char message[1024]; - sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName); + sprintf(message, "[Map %04u] Failed to open %s for writing!\n", mapID, fileName); perror(message); navMesh->removeTile(tileRef, NULL, NULL); break; } - printf("%s Writing to file...\n", tileString); + printf("%s Writing to file...\n", tileString.c_str()); // write header MmapTileHeader header; @@ -898,6 +895,8 @@ namespace MMAP case 1: case 530: case 571: + case 870: + case 1116: return true; default: break; @@ -916,6 +915,12 @@ namespace MMAP case 597: // CraigTest.wdt case 605: // development_nonweighted.wdt case 606: // QA_DVD.wdt + case 651: // ElevatorSpawnTest.wdt + case 1060: // LevelDesignLand-DevOnly.wdt + case 1181: // PattyMackTestGarrisonBldgMap.wdt + case 1264: // Propland-DevOnly.wdt + case 1270: // devland3.wdt + case 1427: // PattyMackTestGarrisonBldgMap2.wdt return true; default: if (isTransportMap(mapID)) @@ -926,13 +931,21 @@ namespace MMAP if (m_skipBattlegrounds) switch (mapID) { - case 30: // AV + case 30: // Alterac Valley case 37: // ? - case 489: // WSG - case 529: // AB - case 566: // EotS - case 607: // SotA - case 628: // IoC + case 489: // Warsong Gulch + case 529: // Arathi Basin + case 566: // Eye of the Storm + case 607: // Strand of the Ancients + case 628: // Isle of Conquest + case 726: // Twin Peaks + case 727: // Silvershard Mines + case 761: // The Battle for Gilneas + case 968: // Rated Eye of the Storm + case 998: // Temple of Kotmogu + case 1010: // CTF3 + case 1105: // Deepwind Gorge + case 1280: // Southshore vs. Tarren Mill return true; default: break; @@ -970,11 +983,35 @@ namespace MMAP case 641: case 642: case 647: + case 662: case 672: case 673: + case 674: case 712: case 713: case 718: + case 738: + case 739: + case 740: + case 741: + case 742: + case 743: + case 747: + case 748: + case 749: + case 750: + case 762: + case 763: + case 765: + case 766: + case 767: + case 1113: + case 1132: + case 1133: + case 1172: + case 1173: + case 1192: + case 1231: return true; default: return false; @@ -985,7 +1022,7 @@ namespace MMAP bool MapBuilder::shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY) { char fileName[255]; - sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX); + sprintf(fileName, "mmaps/%04u%02i%02i.mmtile", mapID, tileY, tileX); FILE* file = fopen(fileName, "rb"); if (!file) return false; diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index fb2cc0a20d0..9b01ecfb1df 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -72,7 +72,7 @@ bool preciseVectorData = false; //static const char * szWorkDirMaps = ".\\Maps"; const char* szWorkDirWmo = "./Buildings"; -const char* szRawVMAPMagic = "VMAP042"; +const char* szRawVMAPMagic = "VMAP043"; bool OpenCascStorage() { @@ -249,7 +249,7 @@ void ParsMapFiles() char id[10]; for (unsigned int i=0; i<map_count; ++i) { - sprintf(id,"%03u",map_ids[i].id); + sprintf(id, "%04u", map_ids[i].id); sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name); WDTFile WDT(fn,map_ids[i].name); if(WDT.init(id, map_ids[i].id)) @@ -355,7 +355,7 @@ bool processArgv(int argc, char ** argv, const char *versionString) int main(int argc, char ** argv) { bool success = true; - const char *versionString = "V4.00 2012_02"; + const char *versionString = "V4.03 2015_05"; // Use command line arguments, when some if (!processArgv(argc, argv, versionString)) |
