Merge pull request #14389 from streetrat/6.x

Core/Phases: Added new phasing system
This commit is contained in:
Rat
2015-03-29 19:31:28 +02:00
47 changed files with 1138 additions and 403 deletions
+12
View File
@@ -0,0 +1,12 @@
DELETE FROM `rbac_permissions` WHERE `id`=776;
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES (776, 'Command: debug phase');
DELETE FROM `rbac_linked_permissions` WHERE `id`=192 AND linkedId=776;
INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES (192, 776);
DELETE FROM `rbac_permissions` WHERE `id`=776;
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES (776, 'Command: debug phase');
DELETE FROM `rbac_linked_permissions` WHERE `id`=192 AND linkedId=776;
INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES (192, 776);
@@ -0,0 +1,11 @@
ALTER TABLE `corpse` DROP `phaseMask`;
DROP TABLE IF EXISTS `corpse_phases`;
CREATE TABLE `corpse_phases` (
`Guid` int(10) unsigned NOT NULL,
`PhaseId` int(10) unsigned NOT NULL,
`OwnerGuid` int(10) unsigned NOT NULL,
`Time` int(10) unsigned NOT NULL DEFAULT '0',
`CorpseType` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`Guid`,`PhaseId`)
);
+57
View File
@@ -0,0 +1,57 @@
DROP TABLE IF EXISTS `phase_definitions`;
DROP TABLE IF EXISTS `phase_info`;
DROP TABLE IF EXISTS `terrain_phase_info`;
DROP TABLE IF EXISTS `terrain_map_info`;
DROP TABLE IF EXISTS `terrain_swap_defaults`;
DROP TABLE IF EXISTS `terrain_worldmap`;
DROP TABLE IF EXISTS `phase_area`;
CREATE TABLE `terrain_phase_info`(
`Id` INT(10) unsigned NOT NULL,
`TerrainSwapMap` INT(10) unsigned NOT NULL,
`Comment` VARCHAR(255),
PRIMARY KEY (`Id`, `TerrainSwapMap`)
);
CREATE TABLE `terrain_swap_defaults`(
`MapId` INT(10) unsigned NOT NULL,
`TerrainSwapMap` INT(10) unsigned NOT NULL,
`Comment` VARCHAR(255),
PRIMARY KEY (`MapId`, `TerrainSwapMap`)
);
CREATE TABLE `terrain_worldmap`(
`TerrainSwapMap` INT(10) unsigned NOT NULL,
`WorldMapArea` INT(10) unsigned NOT NULL,
`Comment` VARCHAR(255),
PRIMARY KEY (`TerrainSwapMap`, `WorldMapArea`)
);
CREATE TABLE `phase_area` (
`AreaId` int(10) unsigned NOT NULL,
`PhaseId` int(10) unsigned NOT NULL,
`Comment` varchar(255) DEFAULT NULL,
PRIMARY KEY (`AreaId`,`PhaseId`)
);
INSERT INTO `terrain_phase_info` (Id, TerrainSwapMap, Comment) VALUES
(182, 655, 'Quest Zone-Specific 07'),
(186, 656, 'Quest Zone-Specific 11');
INSERT INTO `terrain_worldmap` (TerrainSwapMap, WorldMapArea, Comment) VALUES
(638, 545, 'Gilneas'),
(655, 678, 'Gilneas_terrain1'),
(719, 683, 'Hyjal_terrain1'),
(656, 679, 'Gilneas_terrain2');
INSERT INTO `terrain_swap_defaults` (MapId, TerrainSwapMap, Comment) VALUES
(1, 719, 'Mount Hyjal default terrain'),
(654, 638, 'Gilneas default terrain');
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=25 AND `SourceEntry`=719;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(25, 0, 719, 0, 0, 8, 0, 25372, 0, 0, 1, 0, 0, '', 'Hyjal terrain swap if Aessina''s Miracle quest is not rewarded');
ALTER TABLE `creature` DROP `phaseMask`;
ALTER TABLE `gameobject` DROP `phaseMask`;
+271 -15
View File
@@ -19,6 +19,8 @@
#include "MMapManager.h"
#include "Log.h"
#include "World.h"
#include "DBCStores.h"
#include "MMapFactory.h"
namespace MMAP
{
@@ -76,8 +78,7 @@ namespace MMAP
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId);
// store inside our map list
MMapData* mmap_data = new MMapData(mesh);
mmap_data->mmapLoadedTiles.clear();
MMapData* mmap_data = new MMapData(mesh, mapId);
loadedMMaps.insert(std::pair<uint32, MMapData*>(mapId, mmap_data));
return true;
@@ -100,7 +101,7 @@ namespace MMAP
// check if we already have this tile loaded
uint32 packedGridPos = packTileID(x, y);
if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end())
if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end())
return false;
// load this tile :: mmaps/MMMXXYY.mmtile
@@ -152,19 +153,120 @@ namespace MMAP
dtTileRef tileRef = 0;
// memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, NULL/*DT_TILE_FREE_DATA*/, 0, &tileRef)))
{
mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
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);
LoadPhaseTiles(mapId, x, y);
return true;
}
else
{
TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
dtFree(data);
return false;
}
TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
dtFree(data);
return false;
}
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");
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);
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",
mapId, x, y, pTile->fileHeader.mmapVersion, MMAP_VERSION);
fclose(file);
return NULL;
}
pTile->data = (unsigned char*)dtAlloc(pTile->fileHeader.size, DT_ALLOC_PERM);
ASSERT(pTile->data);
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);
fclose(file);
return NULL;
}
fclose(file);
return pTile;
}
void MMapManager::LoadPhaseTiles(uint32 mapId, int32 x, int32 y)
{
TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loading phased mmtiles for map %u, x: %i, y: %i", mapId, x, y);
uint32 packedGridPos = packTileID(x, y);
for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i)
{
if (const MapEntry* const map = sMapStore.LookupEntry(i))
{
if (map->ParentMapID == mapId)
{
PhasedTile* data = LoadTile(map->ID, x, y);
// 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);
_phaseTiles[map->ID][packedGridPos] = data;
}
}
}
}
}
void MMapManager::UnloadPhaseTile(uint32 mapId, int32 x, int32 y)
{
TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloading phased mmtile for map %u, x: %i, y: %i", mapId, x, y);
uint32 packedGridPos = packTileID(x, y);
const MapEntry* const map = sMapStore.LookupEntry(mapId); // map existence already checked when loading
uint32 rootMapId = map->ParentMapID;
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);
delete _phaseTiles[mapId][packedGridPos]->data;
delete _phaseTiles[mapId][packedGridPos];
_phaseTiles[mapId].erase(packedGridPos);
}
}
bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y)
{
// check if we have this map loaded
@@ -179,14 +281,14 @@ namespace MMAP
// check if we have this tile loaded
uint32 packedGridPos = packTileID(x, y);
if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end())
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);
return false;
}
dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos];
dtTileRef tileRef = mmap->loadedTileRefs[packedGridPos];
// unload, and mark as non loaded
if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, NULL, NULL)))
@@ -199,9 +301,11 @@ namespace MMAP
}
else
{
mmap->mmapLoadedTiles.erase(packedGridPos);
mmap->loadedTileRefs.erase(packedGridPos);
--loadedTiles;
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
UnloadPhaseTile(mapId, x, y);
return true;
}
@@ -219,7 +323,7 @@ namespace MMAP
// unload all tiles from given map
MMapData* mmap = loadedMMaps[mapId];
for (MMapTileSet::iterator i = mmap->mmapLoadedTiles.begin(); i != mmap->mmapLoadedTiles.end(); ++i)
for (MMapTileSet::iterator i = mmap->loadedTileRefs.begin(); i != mmap->loadedTileRefs.end(); ++i)
{
uint32 x = (i->first >> 16);
uint32 y = (i->first & 0x0000FFFF);
@@ -227,6 +331,7 @@ namespace MMAP
TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%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);
}
@@ -265,15 +370,15 @@ namespace MMAP
return true;
}
dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId)
dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId, TerrainSet swaps)
{
if (loadedMMaps.find(mapId) == loadedMMaps.end())
return NULL;
return loadedMMaps[mapId]->navMesh;
return loadedMMaps[mapId]->GetNavMesh(swaps);
}
dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId)
dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId, TerrainSet swaps)
{
if (loadedMMaps.find(mapId) == loadedMMaps.end())
return NULL;
@@ -284,7 +389,7 @@ namespace MMAP
// allocate mesh query
dtNavMeshQuery* query = dtAllocNavMeshQuery();
ASSERT(query);
if (dtStatusFailed(query->init(mmap->navMesh, 1024)))
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);
@@ -297,4 +402,155 @@ namespace MMAP
return mmap->navMeshQueries[instanceId];
}
MMapData::MMapData(dtNavMesh* mesh, uint32 mapId)
{
navMesh = mesh;
_mapId = mapId;
}
MMapData::~MMapData()
{
for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i)
dtFreeNavMeshQuery(i->second);
dtFreeNavMesh(navMesh);
for (PhaseTileContainer::iterator i = _baseTiles.begin(); i != _baseTiles.end(); ++i)
{
delete (*i).second->data;
delete (*i).second;
}
}
void MMapData::RemoveSwap(PhasedTile* ptile, uint32 swap, uint32 packedXY)
{
uint32 x = (packedXY >> 16);
uint32 y = (packedXY & 0x0000FFFF);
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);
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);
else
{
TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Unloaded phased %03u%02i%02i.mmtile from navmesh", swap, x, y);
// restore base tile
if (dtStatusSucceed(navMesh->addTile(_baseTiles[packedXY]->data, _baseTiles[packedXY]->dataSize, NULL, 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);
}
else
TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not load base %03u%02i%02i.mmtile to navmesh", _mapId, x, y);
}
loadedPhasedTiles[swap].erase(packedXY);
if (loadedPhasedTiles[swap].empty())
{
_activeSwaps.erase(swap);
TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Fully removed swap %u from map %u", swap, _mapId);
}
}
void MMapData::AddSwap(PhasedTile* ptile, uint32 swap, uint32 packedXY)
{
uint32 x = (packedXY >> 16);
uint32 y = (packedXY & 0x0000FFFF);
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);
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);
return;
}
dtMeshHeader* header = (dtMeshHeader*)ptile->data;
const dtMeshTile* oldTile = navMesh->getTileByRef(loadedTileRefs[packedXY]);
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);
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);
// 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);
else
{
TC_LOG_DEBUG("phase", "MMapData::AddSwap: Unloaded %03u%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())
_baseTiles[packedXY] = pt;
_activeSwaps.insert(swap);
loadedPhasedTiles[swap].insert(packedXY);
// add new swapped tile
if (dtStatusSucceed(navMesh->addTile(ptile->data, ptile->fileHeader.size, NULL, 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);
}
else
TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not load %03u%02i%02i.mmtile to navmesh", swap, x, y);
}
}
dtNavMesh* MMapData::GetNavMesh(TerrainSet swaps)
{
for (uint32 swap : _activeSwaps)
{
if (swaps.find(swap) == swaps.end()) // 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 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
}
}
}
}
return navMesh;
}
}
+56 -16
View File
@@ -23,8 +23,10 @@
#include "DetourAlloc.h"
#include "DetourNavMesh.h"
#include "DetourNavMeshQuery.h"
#include "World.h"
#include <string>
#include <unordered_map>
#include <set>
// move map related classes
namespace MMAP
@@ -32,24 +34,54 @@ namespace MMAP
typedef std::unordered_map<uint32, dtTileRef> MMapTileSet;
typedef std::unordered_map<uint32, dtNavMeshQuery*> NavMeshQuerySet;
// dummy struct to hold map's mmap data
struct MMapData
typedef std::set<uint32> TerrainSet;
struct NavMeshHolder
{
MMapData(dtNavMesh* mesh) : navMesh(mesh) { }
~MMapData()
{
for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i)
dtFreeNavMeshQuery(i->second);
if (navMesh)
dtFreeNavMesh(navMesh);
}
// Pre-built navMesh
dtNavMesh* navMesh;
// List of terrain swap map ids used to build the navMesh
TerrainSet terrainIds;
MMapTileSet loadedTileRefs;
};
struct PhasedTile
{
unsigned char* data;
MmapTileHeader fileHeader;
int32 dataSize;
};
typedef std::unordered_map<uint32, PhasedTile*> PhaseTileContainer;
typedef std::unordered_map<uint32, PhaseTileContainer> PhaseTileMap;
typedef std::unordered_map<uint32, TerrainSet> TerrainSetMap;
class MMapData
{
public:
MMapData(dtNavMesh* mesh, uint32 mapId);
~MMapData();
dtNavMesh* GetNavMesh(TerrainSet swaps);
// we have to use single dtNavMeshQuery for every instance, since those are not thread safe
NavMeshQuerySet navMeshQueries; // instanceId to query
MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile]
dtNavMesh* navMesh;
MMapTileSet loadedTileRefs;
TerrainSetMap loadedPhasedTiles;
private:
uint32 _mapId;
PhaseTileContainer _baseTiles;
std::set<uint32> _activeSwaps;
void RemoveSwap(PhasedTile* ptile, uint32 swap, uint32 packedXY);
void AddSwap(PhasedTile* tile, uint32 swap, uint32 packedXY);
};
@@ -69,17 +101,25 @@ namespace MMAP
bool unloadMapInstance(uint32 mapId, uint32 instanceId);
// the returned [dtNavMeshQuery const*] is NOT threadsafe
dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId);
dtNavMesh const* GetNavMesh(uint32 mapId);
dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId, TerrainSet swaps);
dtNavMesh const* GetNavMesh(uint32 mapId, TerrainSet swaps);
uint32 getLoadedTilesCount() const { return loadedTiles; }
uint32 getLoadedMapsCount() const { return uint32(loadedMMaps.size()); }
uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
void LoadPhaseTiles(uint32 mapId, int32 x, int32 y);
void UnloadPhaseTile(uint32 mapId, int32 x, int32 y);
PhaseTileContainer GetPhaseTileContainer(uint32 mapId) { return _phaseTiles[mapId]; }
private:
bool loadMapData(uint32 mapId);
uint32 packTileID(int32 x, int32 y);
MMapDataSet loadedMMaps;
uint32 loadedTiles;
PhasedTile* LoadTile(uint32 mapId, int32 x, int32 y);
PhaseTileMap _phaseTiles;
};
}
+18 -44
View File
@@ -424,6 +424,11 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
condMeets = true;
break;
}
case CONDITION_TERRAIN_SWAP:
{
condMeets = object->IsInTerrainSwap(ConditionValue1);
break;
}
default:
condMeets = false;
break;
@@ -596,6 +601,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case CONDITION_REALM_ACHIEVEMENT:
mask |= GRID_MAP_TYPE_MASK_ALL;
break;
case CONDITION_TERRAIN_SWAP:
mask |= GRID_MAP_TYPE_MASK_ALL;
break;
default:
ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
break;
@@ -795,7 +803,6 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType)
sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET ||
sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT ||
sourceType == CONDITION_SOURCE_TYPE_PHASE_DEFINITION ||
sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR);
}
@@ -871,22 +878,6 @@ ConditionList ConditionMgr::GetConditionsForSmartEvent(int64 entryOrGuid, uint32
return cond;
}
ConditionList const* ConditionMgr::GetConditionsForPhaseDefinition(uint32 zone, uint32 entry)
{
PhaseDefinitionConditionContainer::const_iterator itr = PhaseDefinitionsConditionStore.find(zone);
if (itr != PhaseDefinitionsConditionStore.end())
{
ConditionTypeContainer::const_iterator i = itr->second.find(entry);
if (i != itr->second.end())
{
TC_LOG_DEBUG("condition", "GetConditionsForPhaseDefinition: found conditions for zone %u entry %u", zone, entry);
return &i->second;
}
}
return NULL;
}
ConditionList ConditionMgr::GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId)
{
ConditionList cond;
@@ -1126,13 +1117,6 @@ void ConditionMgr::LoadConditions(bool isReload)
++count;
continue;
}
case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
{
PhaseDefinitionsConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
valid = true;
++count;
continue;
}
case CONDITION_SOURCE_TYPE_NPC_VENDOR:
{
NpcVendorConditionContainerStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
@@ -1661,13 +1645,6 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
return false;
}
break;
case CONDITION_SOURCE_TYPE_PHASE_DEFINITION:
/*if (!PhaseMgr::IsConditionTypeSupported(cond->ConditionType))
{
TC_LOG_ERROR("sql.sql", "Condition source type `CONDITION_SOURCE_TYPE_PHASE_DEFINITION` does not support condition type %u, ignoring.", cond->ConditionType);
return false;
}*/
break;
case CONDITION_SOURCE_TYPE_NPC_VENDOR:
{
if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
@@ -1687,6 +1664,8 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
case CONDITION_SOURCE_TYPE_SMART_EVENT:
case CONDITION_SOURCE_TYPE_NONE:
case CONDITION_SOURCE_TYPE_TERRAIN_SWAP:
case CONDITION_SOURCE_TYPE_PHASE:
default:
break;
}
@@ -2086,6 +2065,14 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
}
break;
}
case CONDITION_TERRAIN_SWAP:
{
if (cond->ConditionValue2)
TC_LOG_ERROR("sql.sql", "Terrain swap condition has useless data in value2 (%u)!", cond->ConditionValue2);
if (cond->ConditionValue3)
TC_LOG_ERROR("sql.sql", "Terrain swap condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_TITLE:
{
CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1);
@@ -2219,19 +2206,6 @@ void ConditionMgr::Clean()
SpellClickEventConditionStore.clear();
for (PhaseDefinitionConditionContainer::iterator itr = PhaseDefinitionsConditionStore.begin(); itr != PhaseDefinitionsConditionStore.end(); ++itr)
{
for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
{
for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
delete *i;
it->second.clear();
}
itr->second.clear();
}
PhaseDefinitionsConditionStore.clear();
for (NpcVendorConditionContainer::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr)
{
for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
+5 -6
View File
@@ -73,7 +73,8 @@ enum ConditionTypes
CONDITION_HP_VAL = 37, // hpVal ComparisonType 0 true if unit's hp matches given value
CONDITION_HP_PCT = 38, // hpPct ComparisonType 0 true if unit's hp matches given pct
CONDITION_REALM_ACHIEVEMENT = 39, // achievement_id 0 0 true if realm achievement is complete
CONDITION_MAX = 40 // MAX
CONDITION_TERRAIN_SWAP = 40, // terrainSwap 0 0 true if object is in terrainswap
CONDITION_MAX = 41 // MAX
};
/*! Documentation on implementing a new ConditionSourceType:
@@ -130,8 +131,9 @@ enum ConditionSourceType
CONDITION_SOURCE_TYPE_SMART_EVENT = 22,
CONDITION_SOURCE_TYPE_NPC_VENDOR = 23,
CONDITION_SOURCE_TYPE_SPELL_PROC = 24,
CONDITION_SOURCE_TYPE_PHASE_DEFINITION = 25, // only 4.3.4
CONDITION_SOURCE_TYPE_MAX = 26 // MAX
CONDITION_SOURCE_TYPE_TERRAIN_SWAP = 25,
CONDITION_SOURCE_TYPE_PHASE = 26,
CONDITION_SOURCE_TYPE_MAX = 27 // MAX
};
enum RelationType
@@ -222,7 +224,6 @@ typedef std::map<ConditionSourceType, ConditionTypeContainer> ConditionContainer
typedef std::map<uint32, ConditionTypeContainer> CreatureSpellConditionContainer;
typedef std::map<uint32, ConditionTypeContainer> NpcVendorConditionContainer;
typedef std::map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer;
typedef std::map<int32 /*zoneId*/, ConditionTypeContainer> PhaseDefinitionConditionContainer;
typedef std::map<uint32, ConditionList> ConditionReferenceContainer;//only used for references
@@ -253,7 +254,6 @@ class ConditionMgr
ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForSmartEvent(int64 entryOrGuid, uint32 eventId, uint32 sourceType);
ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId);
ConditionList const* GetConditionsForPhaseDefinition(uint32 zone, uint32 entry);
ConditionList GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId);
struct ConditionTypeInfo
@@ -285,7 +285,6 @@ class ConditionMgr
CreatureSpellConditionContainer SpellClickEventConditionStore;
NpcVendorConditionContainer NpcVendorConditionContainerStore;
SmartEventConditionContainer SmartEventConditionStore;
PhaseDefinitionConditionContainer PhaseDefinitionsConditionStore;
};
#define sConditionMgr ConditionMgr::instance()
@@ -78,8 +78,7 @@ bool AreaTrigger::CreateAreaTrigger(ObjectGuid::LowType guidlow, uint32 triggerE
SetUInt32Value(AREATRIGGER_SPELLVISUALID, spell->SpellVisual[0]);
SetUInt32Value(AREATRIGGER_DURATION, spell->GetDuration());
for (auto phase : caster->GetPhases())
SetInPhase(phase, false, true);
CopyPhaseFrom(caster);
if (!GetMap()->AddToMap(this))
return false;
+30 -8
View File
@@ -94,6 +94,8 @@ bool Corpse::Create(ObjectGuid::LowType guidlow, Player* owner)
_gridCoord = Trinity::ComputeGridCoord(GetPositionX(), GetPositionY());
CopyPhaseFrom(owner);
return true;
}
@@ -121,9 +123,20 @@ void Corpse::SaveToDB()
stmt->setUInt32(index++, uint32(m_time)); // time
stmt->setUInt8 (index++, GetType()); // corpseType
stmt->setUInt32(index++, GetInstanceId()); // instanceId
stmt->setUInt32(index++, GetPhaseMask()); // phaseMask
trans->Append(stmt);
for (uint32 phaseId : GetPhases())
{
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
trans->Append(stmt);
}
CharacterDatabase.CommitTransaction(trans);
}
@@ -148,21 +161,31 @@ void Corpse::DeleteFromDB(SQLTransaction& trans)
{
// Only specific bones
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE);
stmt->setUInt64(0, GetGUID().GetCounter());
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->setUInt64(0, GetOwnerGUID().GetCounter());
stmt->setUInt32(0, GetOwnerGUID().GetCounter());
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_CORPSES_PHASES);
stmt->setUInt32(0, GetOwnerGUID().GetCounter());
trans->Append(stmt);
}
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 16
// SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
// 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
float posX = fields[0].GetFloat();
float posY = fields[1].GetFloat();
@@ -178,12 +201,11 @@ bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields)
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[16].GetUInt64()));
SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Create<HighGuid::Player>(fields[15].GetUInt64()));
m_time = time_t(fields[11].GetUInt32());
uint32 instanceId = fields[13].GetUInt32();
//uint32 phaseMask = fields[14].GetUInt32();
// place
SetLocationInstanceId(instanceId);
@@ -1011,6 +1011,9 @@ void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask)
data.npcflag = npcflag;
data.unit_flags = unit_flags;
data.dynamicflags = dynamicflags;
data.phaseid = GetDBPhase() > 0 ? GetDBPhase() : 0;
data.phaseGroup = GetDBPhase() < 0 ? abs(GetDBPhase()) : 0;
// update in DB
SQLTransaction trans = WorldDatabase.BeginTransaction();
@@ -1026,7 +1029,8 @@ void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask)
stmt->setUInt32(index++, GetEntry());
stmt->setUInt16(index++, uint16(mapid));
stmt->setUInt32(index++, spawnMask);
stmt->setUInt32(index++, GetPhaseMask());
stmt->setUInt32(index++, data.phaseid);
stmt->setUInt32(index++, data.phaseGroup);
stmt->setUInt32(index++, displayId);
stmt->setUInt8(index++, GetCurrentEquipmentId());
stmt->setFloat(index++, GetPositionX());
@@ -819,7 +819,6 @@ void GameObject::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask)
stmt->setUInt32(index++, GetEntry());
stmt->setUInt16(index++, uint16(mapid));
stmt->setUInt8(index++, spawnMask);
stmt->setUInt32(index++, GetPhaseMask());
stmt->setFloat(index++, GetPositionX());
stmt->setFloat(index++, GetPositionY());
stmt->setFloat(index++, GetPositionZ());
@@ -2164,11 +2163,13 @@ void GameObject::SetDisplayId(uint32 displayid)
UpdateModel();
}
void GameObject::SetInPhase(uint32 id, bool update, bool apply)
bool GameObject::SetInPhase(uint32 id, bool update, bool apply)
{
WorldObject::SetInPhase(id, update, apply);
bool res = WorldObject::SetInPhase(id, update, apply);
if (m_model && m_model->isEnabled())
EnableCollision(true);
return res;
}
void GameObject::EnableCollision(bool enable)
@@ -952,7 +952,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); }
static void SetGoArtKit(uint8 artkit, GameObject* go, ObjectGuid::LowType lowguid = UI64LIT(0));
void SetInPhase(uint32 id, bool update, bool apply);
bool SetInPhase(uint32 id, bool update, bool apply);
void EnableCollision(bool enable);
void Use(Unit* user);
+222 -22
View File
@@ -1557,7 +1557,7 @@ void MovementInfo::OutDebug()
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0),
m_name(""), m_isActive(false), m_isWorldObject(isWorldObject), m_zoneScript(NULL),
m_transport(NULL), m_currMap(NULL), m_InstanceId(0),
m_phaseMask(PHASEMASK_NORMAL), m_notifyflags(0), m_executed_notifies(0)
m_phaseMask(PHASEMASK_NORMAL), _dbPhase(0), m_notifyflags(0), m_executed_notifies(0)
{
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST);
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
@@ -2463,10 +2463,6 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
}
}
std::set<uint32> phases;
if (summoner)
phases = summoner->GetPhases();
TempSummon* summon = NULL;
switch (mask)
{
@@ -2494,8 +2490,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
}
// Set the summon to the summoner's phase
for (auto phaseId : phases)
summon->SetInPhase(phaseId, false, true);
summon->CopyPhaseFrom(summoner);
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId);
@@ -2591,8 +2586,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
return NULL;
}
for (auto phase : GetPhases())
go->SetInPhase(phase, false, true);
go->CopyPhaseFrom(this);
go->SetRespawnTime(respawnTime);
if (GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT) //not sure how to handle this
@@ -3003,12 +2997,138 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
UpdateObjectVisibility();
}
void WorldObject::SetInPhase(uint32 id, bool update, bool apply)
bool WorldObject::HasInPhaseList(uint32 phase)
{
if (apply)
_phases.insert(id);
else
_phases.erase(id);
return _phases.find(phase) != _phases.end();
}
// Updates Area based phases, does not remove phases from auras
// Phases from gm commands are not taken into calculations, they can be lost!!
void WorldObject::UpdateAreaPhase()
{
bool updateNeeded = false;
PhaseInfo phases = sObjectMgr->GetAreaPhases();
for (PhaseInfo::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
{
uint32 areaId = itr->first;
for (uint32 phaseId : itr->second)
{
if (areaId == GetAreaId())
{
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_PHASE, phaseId);
if (sConditionMgr->IsObjectMeetToConditions(this, conditions))
{
// add new phase if condition passed, true if it wasnt added before
bool up = SetInPhase(phaseId, false, true);
if (!updateNeeded && up)
updateNeeded = true;
}
else
{
// condition failed, remove phase, true if there was something removed
bool up = SetInPhase(phaseId, false, false);
if (!updateNeeded && up)
updateNeeded = true;
}
}
else
{
// not in area, remove phase, true if there was something removed
bool up = SetInPhase(phaseId, false, false);
if (!updateNeeded && up)
updateNeeded = true;
}
}
}
// do not remove a phase if it would be removed by an area but we have the same phase from an aura
if (Unit* unit = ToUnit())
{
Unit::AuraEffectList const& auraPhaseList = unit->GetAuraEffectsByType(SPELL_AURA_PHASE);
for (Unit::AuraEffectList::const_iterator itr = auraPhaseList.begin(); itr != auraPhaseList.end(); ++itr)
{
uint32 phase = uint32((*itr)->GetMiscValueB());
bool up = SetInPhase(phase, false, true);
if (!updateNeeded && up)
updateNeeded = true;
}
Unit::AuraEffectList const& auraPhaseGroupList = unit->GetAuraEffectsByType(SPELL_AURA_PHASE_GROUP);
for (Unit::AuraEffectList::const_iterator itr = auraPhaseGroupList.begin(); itr != auraPhaseGroupList.end(); ++itr)
{
bool up = false;
uint32 phaseGroup = uint32((*itr)->GetMiscValueB());
std::set<uint32> const& phases = sDB2Manager.GetPhasesForGroup(phaseGroup);
for (uint32 phase : phases)
up = SetInPhase(phase, false, true);
if (!updateNeeded && up)
updateNeeded = true;
}
}
// only update visibility and send packets if there was a change in the phase list
if (updateNeeded && GetTypeId() == TYPEID_PLAYER && IsInWorld())
ToPlayer()->GetSession()->SendSetPhaseShift(GetPhases(), GetTerrainSwaps(), GetWorldMapAreaSwaps());
// only update visibilty once, to prevent objects appearing for a moment while adding in multiple phases
if (updateNeeded && IsInWorld())
UpdateObjectVisibility();
}
bool WorldObject::SetInPhase(uint32 id, bool update, bool apply)
{
if (id)
{
if (apply)
{
if (HasInPhaseList(id)) // do not run the updates if we are already in this phase
return false;
_phases.insert(id);
}
else
{
for (uint32 phaseId : sObjectMgr->GetPhasesForArea(GetAreaId()))
{
if (id == phaseId)
{
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_PHASE, phaseId);
if (sConditionMgr->IsObjectMeetToConditions(this, conditions))
{
// if area phase passes the condition we should not remove it (ie: if remove called from aura remove)
// this however breaks the .mod phase command, you wont be able to remove any area based phases with it
return false;
}
}
}
if (!HasInPhaseList(id)) // do not run the updates if we are not in this phase
return false;
_phases.erase(id);
}
}
RebuildTerrainSwaps();
if (update && IsInWorld())
UpdateObjectVisibility();
return true;
}
void WorldObject::CopyPhaseFrom(WorldObject* obj, bool update)
{
if (!obj)
return;
for (uint32 phase : obj->GetPhases())
SetInPhase(phase, false, true);
if (update && IsInWorld())
UpdateObjectVisibility();
}
void WorldObject::ClearPhases(bool update)
{
_phases.clear();
RebuildTerrainSwaps();
if (update && IsInWorld())
UpdateObjectVisibility();
@@ -3020,21 +3140,18 @@ bool WorldObject::IsInPhase(WorldObject const* obj) const
if (_phases.empty() && obj->GetPhases().empty())
return true;
if (_phases.empty() && obj->IsInPhase(169))
if (_phases.empty() && obj->IsInPhase(DEFAULT_PHASE))
return true;
if (obj->GetPhases().empty() && IsInPhase(169))
if (obj->GetPhases().empty() && IsInPhase(DEFAULT_PHASE))
return true;
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->IsGameMaster())
return true;
return Trinity::Containers::Intersects(_phases.begin(), _phases.end(), obj->GetPhases().begin(), obj->GetPhases().end());
}
bool WorldObject::InSamePhase(WorldObject const* obj) const
{
return IsInPhase(obj);
// return InSamePhase(obj->GetPhaseMask());
}
void WorldObject::PlayDistanceSound(uint32 sound_id, Player* target /*= NULL*/)
{
WorldPacket data(SMSG_PLAY_SPEAKERBOT_SOUND, 4 + 8);
@@ -3181,3 +3298,86 @@ ObjectGuid WorldObject::GetTransGUID() const
return GetTransport()->GetGUID();
return ObjectGuid::Empty;
}
void WorldObject::RebuildTerrainSwaps()
{
// Clear all terrain swaps, will be rebuilt below
// Reason for this is, multiple phases can have the same terrain swap, we should not remove the swap if another phase still use it
_terrainSwaps.clear();
ConditionList conditions;
// Check all applied phases for terrain swap and add it only once
for (uint32 phaseId : _phases)
{
std::list<uint32>& swaps = sObjectMgr->GetPhaseTerrainSwaps(phaseId);
for (uint32 swap : swaps)
{
// only add terrain swaps for current map
MapEntry const* mapEntry = sMapStore.LookupEntry(swap);
if (!mapEntry || mapEntry->ParentMapID != GetMapId())
continue;
conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap);
if (sConditionMgr->IsObjectMeetToConditions(this, conditions))
_terrainSwaps.insert(swap);
}
}
// get default terrain swaps, only for current map always
std::list<uint32>& mapSwaps = sObjectMgr->GetDefaultTerrainSwaps(GetMapId());
for (uint32 swap : mapSwaps)
{
conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap);
if (sConditionMgr->IsObjectMeetToConditions(this, conditions))
_terrainSwaps.insert(swap);
}
// online players have a game client with world map display
if (GetTypeId() == TYPEID_PLAYER)
RebuildWorldMapAreaSwaps();
}
void WorldObject::RebuildWorldMapAreaSwaps()
{
// Clear all world map area swaps, will be rebuilt below
_worldMapAreaSwaps.clear();
// get ALL default terrain swaps, if we are using it (condition is true)
// send the worldmaparea for it, to see swapped worldmaparea in client from other maps too, not just from our current
TerrainPhaseInfo defaults = sObjectMgr->GetDefaultTerrainSwapStore();
for (TerrainPhaseInfo::const_iterator itr = defaults.begin(); itr != defaults.end(); ++itr)
{
for (uint32 swap : itr->second)
{
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap);
if (sConditionMgr->IsObjectMeetToConditions(this, conditions))
{
for (uint32 map : sObjectMgr->GetTerrainWorldMaps(swap))
_worldMapAreaSwaps.insert(map);
}
}
}
// Check all applied phases for world map area swaps
for (uint32 phaseId : _phases)
{
std::list<uint32>& swaps = sObjectMgr->GetPhaseTerrainSwaps(phaseId);
for (uint32 swap : swaps)
{
// add world map swaps for ANY map
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap);
if (sConditionMgr->IsObjectMeetToConditions(this, conditions))
{
for (uint32 map : sObjectMgr->GetTerrainWorldMaps(swap))
_worldMapAreaSwaps.insert(map);
}
}
}
}
+19 -3
View File
@@ -46,6 +46,8 @@
#define NOMINAL_MELEE_RANGE 5.0f
#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players
#define DEFAULT_PHASE 169
enum TempSummonType
{
TEMPSUMMON_TIMED_OR_DEAD_DESPAWN = 1, // despawns after a specified time OR when the creature disappears
@@ -612,13 +614,24 @@ class WorldObject : public Object, public WorldLocation
uint32 GetInstanceId() const { return m_InstanceId; }
virtual void SetPhaseMask(uint32 newPhaseMask, bool update);
virtual void SetInPhase(uint32 id, bool update, bool apply);
virtual bool SetInPhase(uint32 id, bool update, bool apply);
void CopyPhaseFrom(WorldObject* obj, bool update = false);
void UpdateAreaPhase();
void ClearPhases(bool update = false);
void RebuildTerrainSwaps();
void RebuildWorldMapAreaSwaps();
bool HasInPhaseList(uint32 phase);
uint32 GetPhaseMask() const { return m_phaseMask; }
bool InSamePhase(WorldObject const* obj) const;
bool InSamePhase(uint32 phasemask) const { return (GetPhaseMask() & phasemask) != 0; }
bool IsInPhase(uint32 phase) const { return _phases.find(phase) != _phases.end(); }
bool IsInPhase(WorldObject const* obj) const;
bool IsInTerrainSwap(uint32 terrainSwap) const { return _terrainSwaps.find(terrainSwap) != _terrainSwaps.end(); }
std::set<uint32> const& GetPhases() const { return _phases; }
std::set<uint32> const& GetTerrainSwaps() const { return _terrainSwaps; }
std::set<uint32> const& GetWorldMapAreaSwaps() const { return _worldMapAreaSwaps; }
int32 GetDBPhase() { return _dbPhase; }
// if negative it is used as PhaseGroupId
void SetDBPhase(int32 p) { _dbPhase = p; }
uint32 GetZoneId() const;
uint32 GetAreaId() const;
@@ -791,6 +804,9 @@ class WorldObject : public Object, public WorldLocation
uint32 m_InstanceId; // in map copy with instance id
uint32 m_phaseMask; // in area phase state
std::set<uint32> _phases;
std::set<uint32> _terrainSwaps;
std::set<uint32> _worldMapAreaSwaps;
int32 _dbPhase;
uint16 m_notifyflags;
uint16 m_executed_notifies;
+7 -9
View File
@@ -176,11 +176,10 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
}
Map* map = owner->GetMap();
if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, owner->GetPhaseMask(), petEntry))
if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, petEntry))
return false;
for (auto itr : owner->GetPhases())
SetInPhase(itr, false, true);
CopyPhaseFrom(owner);
setPetType(petType);
setFaction(owner->getFaction());
@@ -732,7 +731,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
{
ASSERT(creature);
if (!CreateBaseAtTamed(creature->GetCreatureTemplate(), creature->GetMap(), creature->GetPhaseMask()))
if (!CreateBaseAtTamed(creature->GetCreatureTemplate(), creature->GetMap()))
return false;
Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation());
@@ -763,7 +762,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner)
{
if (!CreateBaseAtTamed(cinfo, owner->GetMap(), owner->GetPhaseMask()))
if (!CreateBaseAtTamed(cinfo, owner->GetMap()))
return false;
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
@@ -774,10 +773,10 @@ bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner)
return true;
}
bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask)
bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map)
{
TC_LOG_DEBUG("entities.pet", "Pet::CreateBaseForTamed");
if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, phaseMask, cinfo->Entry))
if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, cinfo->Entry))
return false;
setPowerType(POWER_FOCUS);
@@ -1800,12 +1799,11 @@ bool Pet::IsPermanentPetFor(Player* owner) const
}
}
bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 Entry)
bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 Entry)
{
ASSERT(map);
SetMap(map);
SetPhaseMask(phaseMask, false);
Object::_Create(ObjectGuid::Create<HighGuid::Pet>(map->GetId(), Entry, guidlow));
m_DBTableGuid = guidlow;
+2 -2
View File
@@ -55,10 +55,10 @@ class Pet : public Guardian
bool IsPermanentPetFor(Player* owner) const; // pet have tab in character windows and set UNIT_FIELD_PETNUMBER
bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 Entry);
bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 Entry);
bool CreateBaseAtCreature(Creature* creature);
bool CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner);
bool CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask);
bool CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map);
bool LoadPetFromDB(Player* owner, uint32 petentry = 0, uint32 petnumber = 0, bool current = false);
bool IsLoading() const override { return m_loading;}
void SavePetToDB(PetSaveMode mode);
+9 -17
View File
@@ -7431,6 +7431,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
UpdateLocalChannels(newZone);
UpdateZoneDependentAuras(newZone);
UpdateAreaPhase();
}
//If players are too far away from the duel flag... they lose the duel
@@ -15445,6 +15447,7 @@ void Player::SendQuestUpdate(uint32 questId)
}
UpdateForQuestWorldObjects();
SendUpdatePhasing();
}
QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
@@ -26201,15 +26204,15 @@ 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, GetPhaseMask(), entry))
if (!pet->Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, entry))
{
TC_LOG_ERROR("misc", "no such creature entry %u", entry);
delete pet;
return NULL;
}
for (auto itr : GetPhases())
pet->SetInPhase(itr, false, true);
pet->CopyPhaseFrom(this);
pet->SetCreatorGUID(GetGUID());
pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
@@ -26579,25 +26582,14 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext
#undef REMOVE_VIOLATING_FLAGS
}
void Player::UpdatePhasing()
void Player::SendUpdatePhasing()
{
if (!IsInWorld())
return;
std::set<uint32> phaseIds;
std::set<uint32> terrainswaps;
std::set<uint32> worldAreaSwaps;
RebuildTerrainSwaps(); // to set default map swaps
for (auto phase : GetPhases())
{
PhaseInfo const* info = sObjectMgr->GetPhaseInfo(phase);
if (!info)
continue;
terrainswaps.insert(info->terrainSwapMap);
worldAreaSwaps.insert(info->worldMapAreaSwap);
}
GetSession()->SendSetPhaseShift(GetPhases(), terrainswaps, worldAreaSwaps);
GetSession()->SendSetPhaseShift(GetPhases(), GetTerrainSwaps(), GetWorldMapAreaSwaps());
}
void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell)
+1 -1
View File
@@ -2449,7 +2449,7 @@ class Player : public Unit, public GridObject<Player>
void UpdateVisibilityOf(WorldObject* target);
void UpdateTriggerVisibility();
void UpdatePhasing();
void SendUpdatePhasing();
template<class T>
void UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow);
@@ -318,8 +318,7 @@ Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData c
for (auto phase : sDB2Manager.GetPhasesForGroup(data->phaseGroup))
creature->SetInPhase(phase, false, true);
else
for (auto phase : GetPhases()) // Set the creature to the transport's phases
creature->SetInPhase(phase, false, true);
creature->CopyPhaseFrom(this);
if (!map->AddToMap(creature))
{
@@ -463,8 +462,8 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
return NULL;
}
for (auto itr : phases)
summon->SetInPhase(itr, false, true);
for (uint32 phase : phases)
summon->SetInPhase(phase, false, true);
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId);
+10 -5
View File
@@ -3660,7 +3660,7 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid)
else
{
Unit* caster = aura->GetCaster();
if (!caster || (newPhase && !caster->InSamePhase(newPhase)) || (!newPhase && !caster->IsInPhase(this)))
if (!caster || (newPhase && !caster->IsInPhase(newPhase)) || (!newPhase && !caster->IsInPhase(this)))
RemoveAura(iter);
else
++iter;
@@ -3675,7 +3675,7 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid)
for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();)
{
Aura* aura = *iter;
if (aura->GetUnitOwner() != this && !aura->GetUnitOwner()->InSamePhase(newPhase))
if (aura->GetUnitOwner() != this && !aura->GetUnitOwner()->IsInPhase(newPhase))
{
aura->Remove();
iter = scAuras.begin();
@@ -11563,6 +11563,7 @@ void Unit::AddToWorld()
{
WorldObject::AddToWorld();
}
RebuildTerrainSwaps();
}
void Unit::RemoveFromWorld()
@@ -13091,6 +13092,8 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id)
return false;
}
pet->CopyPhaseFrom(this);
pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true);
// this enables pet details window (Shift+P)
pet->InitPetCreateSpells();
@@ -14421,12 +14424,12 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, u
return missChance;
}
void Unit::SetInPhase(uint32 id, bool update, bool apply)
bool Unit::SetInPhase(uint32 id, bool update, bool apply)
{
WorldObject::SetInPhase(id, update, apply);
bool res = WorldObject::SetInPhase(id, update, apply);
if (!IsInWorld())
return;
return res;
if (GetTypeId() == TYPEID_UNIT || (!ToPlayer()->IsGameMaster() && !ToPlayer()->GetSession()->PlayerLogout()))
{
@@ -14469,6 +14472,8 @@ void Unit::SetInPhase(uint32 id, bool update, bool apply)
summon->SetInPhase(id, true, apply);
RemoveNotOwnSingleTargetAuras(0, true);
return res;
}
void Unit::UpdateObjectVisibility(bool forced)
+1 -1
View File
@@ -1957,7 +1957,7 @@ class Unit : public WorldObject
void SetVisible(bool x);
// common function for visibility checks for player/creatures with detection code
void SetInPhase(uint32 id, bool update, bool apply);
bool SetInPhase(uint32 id, bool update, bool apply);
void UpdateObjectVisibility(bool forced = true) override;
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
@@ -411,6 +411,8 @@ Corpse* ObjectAccessor::ConvertCorpseForPlayer(ObjectGuid player_guid, bool insi
bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0);
}
bones->CopyPhaseFrom(corpse);
// add bones in grid store if grid loaded where corpse placed
map->AddToMap(bones);
}
+170 -88
View File
@@ -1650,8 +1650,8 @@ void ObjectMgr::LoadCreatures()
// 0 1 2 3 4 5 6 7 8 9 10
QueryResult result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, "
// 11 12 13 14 15 16 17 18 19 20 21 22 23
"currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, creature.phaseid, creature.phasegroup "
// 11 12 13 14 15 16 17 18 19 20 21 22
"currentwaypoint, curhealth, curmana, MovementType, spawnMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, creature.phaseid, creature.phasegroup "
"FROM creature "
"LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid "
"LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid");
@@ -1701,14 +1701,13 @@ void ObjectMgr::LoadCreatures()
data.curmana = fields[13].GetUInt32();
data.movementType = fields[14].GetUInt8();
data.spawnMask = fields[15].GetUInt32();
data.phaseMask = fields[16].GetUInt32();
int16 gameEvent = fields[17].GetInt8();
uint32 PoolId = fields[18].GetUInt32();
data.npcflag = fields[19].GetUInt32();
data.unit_flags = fields[20].GetUInt32();
data.dynamicflags = fields[21].GetUInt32();
data.phaseid = fields[22].GetUInt32();
data.phaseGroup = fields[23].GetUInt32();
int16 gameEvent = fields[16].GetInt8();
uint32 PoolId = fields[17].GetUInt32();
data.npcflag = fields[18].GetUInt32();
data.unit_flags = fields[19].GetUInt32();
data.dynamicflags = fields[20].GetUInt32();
data.phaseid = fields[21].GetUInt32();
data.phaseGroup = fields[22].GetUInt32();
MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
if (!mapEntry)
@@ -1778,11 +1777,7 @@ void ObjectMgr::LoadCreatures()
data.orientation = Position::NormalizeOrientation(data.orientation);
}
if (data.phaseMask == 0)
{
TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD " Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.", guid, data.id);
data.phaseMask = 1;
}
data.phaseMask = 1;
if (data.phaseGroup && data.phaseid)
{
@@ -1984,8 +1979,8 @@ void ObjectMgr::LoadGameobjects()
// 0 1 2 3 4 5 6
QueryResult result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation, "
// 7 8 9 10 11 12 13 14 15 16 17 18 19
"rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, eventEntry, pool_entry, phaseid, phasegroup "
// 7 8 9 10 11 12 13 14 15 16 17 18
"rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, eventEntry, pool_entry, phaseid, phasegroup "
"FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid "
"LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid");
@@ -2081,11 +2076,10 @@ void ObjectMgr::LoadGameobjects()
if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid])
TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: " UI64FMTD " Entry: %u) that has wrong spawn mask %u including unsupported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid);
data.phaseMask = fields[15].GetUInt32();
int16 gameEvent = fields[16].GetInt8();
uint32 PoolId = fields[17].GetUInt32();
data.phaseid = fields[18].GetUInt32();
data.phaseGroup = fields[19].GetUInt32();
int16 gameEvent = fields[15].GetInt8();
uint32 PoolId = fields[16].GetUInt32();
data.phaseid = fields[17].GetUInt32();
data.phaseGroup = fields[18].GetUInt32();
if (data.phaseGroup && data.phaseid)
{
@@ -2117,11 +2111,7 @@ void ObjectMgr::LoadGameobjects()
continue;
}
if (data.phaseMask == 0)
{
TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: " UI64FMTD " Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.", guid, data.id);
data.phaseMask = 1;
}
data.phaseMask = 1;
if (sWorld->getBoolConfig(CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA))
{
@@ -6448,11 +6438,28 @@ uint64 ObjectMgr::GenerateVoidStorageItemId()
void ObjectMgr::LoadCorpses()
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0
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)
{
@@ -6464,11 +6471,11 @@ void ObjectMgr::LoadCorpses()
do
{
Field* fields = result->Fetch();
ObjectGuid::LowType guid = fields[15].GetUInt64();
uint32 guid = fields[14].GetUInt32();
CorpseType type = CorpseType(fields[12].GetUInt8());
if (type >= MAX_CORPSE_TYPE)
{
TC_LOG_ERROR("misc", "Corpse (guid: " UI64FMTD ") have wrong corpse type (%u), not loading.", guid, type);
TC_LOG_ERROR("misc", "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type);
continue;
}
@@ -6479,6 +6486,9 @@ void ObjectMgr::LoadCorpses()
continue;
}
for (auto phaseId : phases[guid])
corpse->SetInPhase(phaseId, false, true);
sObjectAccessor->AddCorpse(corpse);
++count;
}
@@ -8527,60 +8537,18 @@ void ObjectMgr::LoadFactionChangeTitles()
TC_LOG_INFO("server.loading", ">> Loaded %u faction change title pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadPhaseDefinitions()
void ObjectMgr::LoadTerrainSwapDefaults()
{
_PhaseDefinitionStore.clear();
_terrainMapDefaultStore.clear();
uint32 oldMSTime = getMSTime();
// 0 1 2 3
QueryResult result = WorldDatabase.Query("SELECT zoneId, entry, phaseId, phaseGroup FROM `phase_definitions` ORDER BY `entry` ASC");
// 0 1
QueryResult result = WorldDatabase.Query("SELECT MapId, TerrainSwapMap FROM `terrain_swap_defaults`");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 phasing definitions. DB table `phase_definitions` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
PhaseDefinition PhaseDefinition;
PhaseDefinition.zoneId = fields[0].GetUInt32();
PhaseDefinition.entry = fields[1].GetUInt32();
PhaseDefinition.phaseId = fields[2].GetUInt32();
PhaseDefinition.phaseGroup = fields[3].GetUInt32();
if (PhaseDefinition.phaseGroup && PhaseDefinition.phaseId)
{
TC_LOG_ERROR("sql.sql", "Phase definition for zone %u (Entry: %u) has phaseGroup and phaseId set, phaseGroup set to 0", PhaseDefinition.zoneId, PhaseDefinition.entry);
PhaseDefinition.phaseGroup = 0;
}
_PhaseDefinitionStore[PhaseDefinition.zoneId].push_back(PhaseDefinition);
++count;
}
while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u phasing definitions in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadPhaseInfo()
{
_PhaseInfoStore.clear();
uint32 oldMSTime = getMSTime();
// 0 1 2
QueryResult result = WorldDatabase.Query("SELECT id, worldmapareaswap, terrainswapmap FROM `phase_info`");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 phase infos. DB table `phase_info` is empty.");
TC_LOG_INFO("server.loading", ">> Loaded 0 terrain swap defaults. DB table `terrain_swap_defaults` is empty.");
return;
}
@@ -8589,25 +8557,139 @@ void ObjectMgr::LoadPhaseInfo()
{
Field* fields = result->Fetch();
PhaseInfo phaseInfo;
phaseInfo.phaseId = fields[0].GetUInt32();
uint32 mapId = fields[0].GetUInt32();
PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseInfo.phaseId);
if (!phase)
MapEntry const* map = sMapStore.LookupEntry(mapId);
if (!map)
{
TC_LOG_ERROR("sql.sql", "Phase %u defined in `phase_info` does not exists, skipped.", phaseInfo.phaseId);
TC_LOG_ERROR("sql.sql", "Map %u defined in `terrain_swap_defaults` does not exist, skipped.", mapId);
continue;
}
phaseInfo.worldMapAreaSwap = fields[1].GetUInt32();
phaseInfo.terrainSwapMap = fields[2].GetUInt32();
uint32 terrainSwap = fields[1].GetUInt32();
_PhaseInfoStore[phaseInfo.phaseId] = phaseInfo;
map = sMapStore.LookupEntry(terrainSwap);
if (!map)
{
TC_LOG_ERROR("sql.sql", "TerrainSwapMap %u defined in `terrain_swap_defaults` does not exist, skipped.", terrainSwap);
continue;
}
_terrainMapDefaultStore[mapId].push_back(terrainSwap);
++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u terrain swap defaults in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadTerrainPhaseInfo()
{
_terrainPhaseInfoStore.clear();
uint32 oldMSTime = getMSTime();
// 0 1
QueryResult result = WorldDatabase.Query("SELECT Id, TerrainSwapMap FROM `terrain_phase_info`");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 terrain phase infos. DB table `terrain_phase_info` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 phaseId = fields[0].GetUInt32();
PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseId);
if (!phase)
{
TC_LOG_ERROR("sql.sql", "Phase %u defined in `terrain_phase_info` does not exist, skipped.", phaseId);
continue;
}
uint32 terrainSwap = fields[1].GetUInt32();
_terrainPhaseInfoStore[phaseId].push_back(terrainSwap);
++count;
}
while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u phase infos in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
TC_LOG_INFO("server.loading", ">> Loaded %u terrain phase infos in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadTerrainWorldMaps()
{
_terrainWorldMapStore.clear();
uint32 oldMSTime = getMSTime();
// 0 1
QueryResult result = WorldDatabase.Query("SELECT TerrainSwapMap, WorldMapArea FROM `terrain_worldmap`");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 terrain world maps. DB table `terrain_worldmap` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 mapId = fields[0].GetUInt32();
if (!sMapStore.LookupEntry(mapId))
{
TC_LOG_ERROR("sql.sql", "TerrainSwapMap %u defined in `terrain_worldmap` does not exist, skipped.", mapId);
continue;
}
uint32 worldMapArea = fields[1].GetUInt32();
_terrainWorldMapStore[mapId].push_back(worldMapArea);
++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u terrain world maps in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadAreaPhases()
{
_phases.clear();
uint32 oldMSTime = getMSTime();
// 0 1
QueryResult result = WorldDatabase.Query("SELECT AreaId, PhaseId FROM `phase_area`");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 phase areas. DB table `phase_area` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 area = fields[0].GetUInt32();
uint32 phase = fields[1].GetUInt32();
_phases[area].push_back(phase);
++count;
} while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u phase areas in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
}
GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry)
+17 -33
View File
@@ -129,34 +129,6 @@ typedef std::map<uint32, PageText> PageTextContainer;
// Benchmarked: Faster than std::map (insert/find)
typedef std::unordered_map<uint16, InstanceTemplate> InstanceTemplateContainer;
// Phasing (visibility)
enum PhasingFlags
{
PHASE_FLAG_OVERWRITE_EXISTING = 0x01, // don't stack with existing phases, overwrites existing phases
PHASE_FLAG_NO_MORE_PHASES = 0x02, // stop calculating phases after this phase was applied (no more phases will be applied)
PHASE_FLAG_NEGATE_PHASE = 0x04 // negate instead to add the phasemask
};
struct PhaseInfo
{
uint32 phaseId;
uint32 worldMapAreaSwap;
uint32 terrainSwapMap;
};
typedef std::unordered_map<uint32, PhaseInfo> PhaseInfoContainer;
struct PhaseDefinition
{
uint32 zoneId;
uint32 entry;
uint32 phaseId;
uint32 phaseGroup;
};
typedef std::list<PhaseDefinition> PhaseDefinitionContainer;
typedef std::unordered_map<uint32 /*zoneId*/, PhaseDefinitionContainer> PhaseDefinitionStore;
struct GameTele
{
float position_x;
@@ -672,6 +644,9 @@ struct DungeonEncounter
typedef std::list<DungeonEncounter const*> DungeonEncounterList;
typedef std::unordered_map<uint64, DungeonEncounterList> DungeonEncounterContainer;
typedef std::unordered_map<uint32, std::list<uint32>> TerrainPhaseInfo;
typedef std::unordered_map<uint32, std::list<uint32>> PhaseInfo;
class PlayerDumpReader;
class ObjectMgr
@@ -1008,8 +983,10 @@ class ObjectMgr
void LoadTrainerSpell();
void AddSpellToTrainer(uint32 entry, uint32 spell, uint32 spellCost, uint32 reqSkill, uint32 reqSkillValue, uint32 reqLevel);
void LoadPhaseDefinitions();
void LoadPhaseInfo();
void LoadTerrainPhaseInfo();
void LoadTerrainSwapDefaults();
void LoadTerrainWorldMaps();
void LoadAreaPhases();
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint8 level);
@@ -1243,7 +1220,12 @@ class ObjectMgr
return _gossipMenuItemsStore.equal_range(uiMenuId);
}
PhaseInfo const* GetPhaseInfo(uint32 phase) { return _PhaseInfoStore.find(phase) != _PhaseInfoStore.end() ? &_PhaseInfoStore[phase] : nullptr; }
std::list<uint32>& GetPhaseTerrainSwaps(uint32 phaseid) { return _terrainPhaseInfoStore[phaseid]; }
std::list<uint32>& GetDefaultTerrainSwaps(uint32 mapid) { return _terrainMapDefaultStore[mapid]; }
std::list<uint32>& GetTerrainWorldMaps(uint32 terrainId) { return _terrainWorldMapStore[terrainId]; }
TerrainPhaseInfo& GetDefaultTerrainSwapStore() { return _terrainMapDefaultStore; }
std::list<uint32>& GetPhasesForArea(uint32 area) { return _phases[area]; }
PhaseInfo& GetAreaPhases() { return _phases; }
// for wintergrasp only
GraveYardContainer GraveYardStore;
@@ -1369,8 +1351,10 @@ class ObjectMgr
PageTextContainer _pageTextStore;
InstanceTemplateContainer _instanceTemplateStore;
PhaseDefinitionStore _PhaseDefinitionStore;
PhaseInfoContainer _PhaseInfoStore;
TerrainPhaseInfo _terrainPhaseInfoStore;
TerrainPhaseInfo _terrainMapDefaultStore;
TerrainPhaseInfo _terrainWorldMapStore;
PhaseInfo _phases;
private:
void LoadScripts(ScriptsType type);
+7 -44
View File
@@ -1399,50 +1399,13 @@ void WorldSession::HandleUITimeRequest(WorldPackets::Misc::UITimeRequest& /*requ
void WorldSession::SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps, std::set<uint32> const& worldMapAreaSwaps)
{
ObjectGuid guid = _player->GetGUID();
WorldPacket data(SMSG_PHASE_SHIFT_CHANGE, 1 + 8 + 4 + 4 + 4 + 4 + 2 * phaseIds.size() + 4 + terrainswaps.size() * 2);
data.WriteBit(guid[2]);
data.WriteBit(guid[3]);
data.WriteBit(guid[1]);
data.WriteBit(guid[6]);
data.WriteBit(guid[4]);
data.WriteBit(guid[5]);
data.WriteBit(guid[0]);
data.WriteBit(guid[7]);
data.WriteByteSeq(guid[7]);
data.WriteByteSeq(guid[4]);
data << uint32(worldMapAreaSwaps.size());
for (auto mapSwap : worldMapAreaSwaps)
data << uint16(mapSwap); // WorldMapArea.dbc id (controls map display)
data.WriteByteSeq(guid[1]);
data << uint32(phaseIds.size() ? 0 : 8); // flags (not phasemask)
data.WriteByteSeq(guid[2]);
data.WriteByteSeq(guid[6]);
data << uint32(0); // Inactive terrain swaps
//for (uint8 i = 0; i < inactiveSwapsCount; ++i)
// data << uint16(0);
data << uint32(phaseIds.size()) * 2; // Phase.dbc ids
for (std::set<uint32>::const_iterator itr = phaseIds.begin(); itr != phaseIds.end(); ++itr)
data << uint16(*itr);
data.WriteByteSeq(guid[3]);
data.WriteByteSeq(guid[0]);
data << uint32(terrainswaps.size()) * 2; // Active terrain swaps
for (std::set<uint32>::const_iterator itr = terrainswaps.begin(); itr != terrainswaps.end(); ++itr)
data << uint16(*itr);
data.WriteByteSeq(guid[5]);
SendPacket(&data);
WorldPackets::Misc::PhaseShift phaseShift;
phaseShift.ClientGUID = _player->GetGUID();
phaseShift.PersonalGUID = _player->GetGUID();
phaseShift.PhaseShifts = phaseIds;
phaseShift.VisibleMapIDs = terrainswaps;
phaseShift.UiWorldMapAreaIDSwaps = worldMapAreaSwaps;
SendPacket(phaseShift.Write());
}
// Battlefield and Battleground
+1 -1
View File
@@ -633,5 +633,5 @@ void InstanceScript::UpdatePhasing()
Map::PlayerList const& players = instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
player->UpdatePhasing();
player->SendUpdatePhasing();
}
+4
View File
@@ -498,6 +498,8 @@ bool Map::AddPlayerToMap(Player* player)
player->m_clientGUIDs.clear();
player->UpdateObjectVisibility(false);
player->SendUpdatePhasing();
sScriptMgr->OnPlayerEnterMap(this, player);
return true;
}
@@ -556,6 +558,8 @@ bool Map::AddToMap(T* obj)
if (obj->isActiveObject())
AddToActive(obj);
obj->RebuildTerrainSwaps();
//something, such as vehicle, needs to be update immediately
//also, trigger needs to cast spell, if not update, cannot see visual
obj->UpdateObjectVisibility(true);
+2 -2
View File
@@ -42,8 +42,8 @@ PathGenerator::PathGenerator(const Unit* owner) :
if (DisableMgr::IsPathfindingEnabled(mapId))
{
MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager();
_navMesh = mmap->GetNavMesh(mapId);
_navMeshQuery = mmap->GetNavMeshQuery(mapId, _sourceUnit->GetInstanceId());
_navMesh = mmap->GetNavMesh(mapId, _sourceUnit->GetTerrainSwaps());
_navMeshQuery = mmap->GetNavMeshQuery(mapId, _sourceUnit->GetInstanceId(), _sourceUnit->GetTerrainSwaps());
}
CreateFilter();
@@ -379,3 +379,30 @@ WorldPacket const* WorldPackets::Misc::RandomRoll::Write()
return &_worldPacket;
}
WorldPacket const* WorldPackets::Misc::PhaseShift::Write()
{
_worldPacket << ClientGUID; // CLientGUID
_worldPacket << uint32(PhaseShifts.size() ? 0 : 8); // PhaseShiftFlags
_worldPacket << uint32(PhaseShifts.size()); // PhaseShiftCount
_worldPacket << PersonalGUID; // PersonalGUID
for (uint32 phase : PhaseShifts)
{
_worldPacket << uint16(1); // PhaseFlags
_worldPacket << uint16(phase); // PhaseID
}
_worldPacket << uint32(VisibleMapIDs.size() * 2); // Active terrain swaps size
for (uint32 map : VisibleMapIDs)
_worldPacket << uint16(map); // Active terrain swap map id
_worldPacket << uint32(PreloadMapIDs.size() * 2); // Inactive terrain swaps size
for (uint32 map : PreloadMapIDs)
_worldPacket << uint16(map); // Inactive terrain swap map id
_worldPacket << uint32(UiWorldMapAreaIDSwaps.size() * 2); // UI map swaps size
for (uint32 map : UiWorldMapAreaIDSwaps)
_worldPacket << uint16(map); // UI map id, WorldMapArea.dbc, controls map display
return &_worldPacket;
}
@@ -538,6 +538,21 @@ namespace WorldPackets
WorldPacket const* Write() override { return &_worldPacket; }
};
class PhaseShift final : public ServerPacket
{
public:
PhaseShift() : ServerPacket(SMSG_PHASE_SHIFT_CHANGE, 4) { }
WorldPacket const* Write() override;
ObjectGuid ClientGUID;
ObjectGuid PersonalGUID;
std::set<uint32> PhaseShifts;
std::set<uint32> PreloadMapIDs;
std::set<uint32> UiWorldMapAreaIDSwaps;
std::set<uint32> VisibleMapIDs;
};
}
}
+1 -1
View File
@@ -1522,7 +1522,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_STABLE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_TAME_FAILURE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_UNLEARNED_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PHASE_SHIFT_CHANGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PHASE_SHIFT_CHANGE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PLAYED_TIME, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PLAYER_BOUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PLAYER_SAVE_GUILD_EMBLEM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1738,7 +1738,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
{
if (player->IsInWorld())
player->GetMap()->SendUpdateTransportVisibility(player, oldPhases);
player->UpdatePhasing();
player->SendUpdatePhasing();
}
// need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
@@ -1770,7 +1770,7 @@ void AuraEffect::HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, boo
{
if (player->IsInWorld())
player->GetMap()->SendUpdateTransportVisibility(player, oldPhases);
player->UpdatePhasing();
player->SendUpdatePhasing();
}
// need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
+6 -12
View File
@@ -3218,8 +3218,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
return;
}
for (auto phase : m_caster->GetPhases())
pGameObj->SetInPhase(phase, false, true);
pGameObj->CopyPhaseFrom(m_caster);
int32 duration = m_spellInfo->GetDuration();
@@ -3242,8 +3241,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
if (linkedGO->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), linkedEntry, map,
m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
for (auto phase : m_caster->GetPhases())
linkedGO->SetInPhase(phase, false, true);
linkedGO->CopyPhaseFrom(m_caster);
linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
linkedGO->SetSpellId(m_spellInfo->Id);
@@ -3877,8 +3875,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex)
return;
}
for (auto phase : m_caster->GetPhases())
pGameObj->SetInPhase(phase, false, true);
pGameObj->CopyPhaseFrom(m_caster);
pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction());
pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1);
@@ -4250,8 +4247,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex)
return;
}
for (auto phase : m_caster->GetPhases())
go->SetInPhase(phase, false, true);
go->CopyPhaseFrom(m_caster);
//pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
int32 duration = m_spellInfo->GetDuration();
@@ -4888,8 +4884,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
return;
}
for (auto phase : m_caster->GetPhases())
pGameObj->SetInPhase(phase, false, true);
pGameObj->CopyPhaseFrom(m_caster);
int32 duration = m_spellInfo->GetDuration();
@@ -4953,8 +4948,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
if (linkedGO->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), linkedEntry, cMap,
0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY))
{
for (auto phase : m_caster->GetPhases())
linkedGO->SetInPhase(phase, false, true);
linkedGO->CopyPhaseFrom(m_caster);
linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0);
//linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
+15 -5
View File
@@ -1460,6 +1460,10 @@ void World::SetInitialWorldSettings()
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);
@@ -1550,9 +1554,6 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Spell Group Stack Rules...");
sSpellMgr->LoadSpellGroupStackRules();
TC_LOG_INFO("server.loading", "Loading Spell Phase Dbc Info...");
sObjectMgr->LoadPhaseInfo();
TC_LOG_INFO("server.loading", "Loading NPC Texts...");
sObjectMgr->LoadGossipText();
@@ -1801,8 +1802,17 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions
LoadWorldStates();
TC_LOG_INFO("server.loading", "Loading Phase definitions...");
sObjectMgr->LoadPhaseDefinitions();
TC_LOG_INFO("server.loading", "Loading Terrain Phase definitions...");
sObjectMgr->LoadTerrainPhaseInfo();
TC_LOG_INFO("server.loading", "Loading Terrain Swap Default definitions...");
sObjectMgr->LoadTerrainSwapDefaults();
TC_LOG_INFO("server.loading", "Loading Terrain World Map definitions...");
sObjectMgr->LoadTerrainWorldMaps();
TC_LOG_INFO("server.loading", "Loading Phase Area definitions...");
sObjectMgr->LoadAreaPhases();
TC_LOG_INFO("server.loading", "Loading Conditions...");
sConditionMgr->LoadConditions();
+31 -11
View File
@@ -935,8 +935,7 @@ public:
return false;
}
for (auto phase : handler->GetSession()->GetPlayer()->GetPhases())
v->SetInPhase(phase, false, true);
v->CopyPhaseFrom(handler->GetSession()->GetPlayer());
map->AddToMap(v->ToCreature());
@@ -960,6 +959,7 @@ public:
char* t = strtok((char*)args, " ");
char* p = strtok(NULL, " ");
char* m = strtok(NULL, " ");
if (!t)
return false;
@@ -968,10 +968,16 @@ public:
std::set<uint32> phaseId;
std::set<uint32> worldMapSwap;
terrainswap.insert((uint32)atoi(t));
if (uint32 ut = (uint32)atoi(t))
terrainswap.insert(ut);
if (p)
phaseId.insert((uint32)atoi(p));
if (uint32 up = (uint32)atoi(p))
phaseId.insert(up);
if (m)
if (uint32 um = (uint32)atoi(m))
worldMapSwap.insert(um);
handler->GetSession()->SendSetPhaseShift(phaseId, terrainswap, worldMapSwap);
return true;
@@ -1391,14 +1397,28 @@ public:
return true;
}
static bool HandleDebugPhaseCommand(ChatHandler* /*handler*/, char const* /*args*/)
static bool HandleDebugPhaseCommand(ChatHandler* handler, char const* /*args*/)
{
/*/
Unit* unit = handler->getSelectedUnit();
Player* player = handler->GetSession()->GetPlayer();
if (unit && unit->GetTypeId() == TYPEID_PLAYER)
player = unit->ToPlayer();
*/
Unit* target = handler->getSelectedUnit();
if (!target)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
std::stringstream phases;
for (uint32 phase : target->GetPhases())
{
phases << phase << " ";
}
if (!phases.str().empty())
handler->PSendSysMessage("Target's current phases: %s", phases.str().c_str());
else
handler->SendSysMessage("Target is not phased");
return true;
}
};
+1 -2
View File
@@ -158,8 +158,7 @@ public:
return false;
}
for (auto phase : player->GetPhases())
object->SetInPhase(phase, false, true);
object->CopyPhaseFrom(player);
if (spawntimeSecs)
{
+18 -5
View File
@@ -219,7 +219,7 @@ public:
uint32 haveMap = Map::ExistMap(mapId, gridX, gridY) ? 1 : 0;
uint32 haveVMap = Map::ExistVMap(mapId, gridX, gridY) ? 1 : 0;
uint32 haveMMap = (DisableMgr::IsPathfindingEnabled(mapId) && MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) ? 1 : 0;
uint32 haveMMap = (DisableMgr::IsPathfindingEnabled(mapId) && MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId(), handler->GetSession()->GetPlayer()->GetTerrainSwaps())) ? 1 : 0;
if (haveVMap)
{
@@ -248,6 +248,21 @@ public:
if (status)
handler->PSendSysMessage(LANG_LIQUID_STATUS, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, liquidStatus.type_flags, status);
if (!object->GetTerrainSwaps().empty())
{
std::stringstream ss;
for (uint32 swap : object->GetTerrainSwaps())
ss << swap << " ";
handler->PSendSysMessage("Target's active terrain swaps: %s", ss.str().c_str());
}
if (!object->GetWorldMapAreaSwaps().empty())
{
std::stringstream ss;
for (uint32 swap : object->GetWorldMapAreaSwaps())
ss << swap << " ";
handler->PSendSysMessage("Target's active world map area swaps: %s", ss.str().c_str());
}
return true;
}
@@ -408,8 +423,7 @@ public:
target->GetContactPoint(_player, x, y, z);
_player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE);
for (auto phase : target->GetPhases())
_player->SetInPhase(phase, true, true);
_player->CopyPhaseFrom(target, true);
}
else
{
@@ -533,8 +547,7 @@ public:
float x, y, z;
handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize());
target->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation());
for (auto phase : handler->GetSession()->GetPlayer()->GetPhases())
target->SetInPhase(phase, true, true);
target->CopyPhaseFrom(handler->GetSession()->GetPlayer(), true);
}
else
{
+6 -6
View File
@@ -64,7 +64,7 @@ public:
static bool HandleMmapPathCommand(ChatHandler* handler, char const* args)
{
if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()))
if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId(), handler->GetSession()->GetPlayer()->GetTerrainSwaps()))
{
handler->PSendSysMessage("NavMesh not loaded for current map.");
return true;
@@ -132,8 +132,8 @@ public:
handler->PSendSysMessage("gridloc [%i, %i]", gy, gx);
// calculate navmesh tile location
dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId());
dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId());
dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId(), handler->GetSession()->GetPlayer()->GetTerrainSwaps());
dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId(), handler->GetSession()->GetPlayer()->GetTerrainSwaps());
if (!navmesh || !navmeshquery)
{
handler->PSendSysMessage("NavMesh not loaded for current map.");
@@ -184,8 +184,8 @@ public:
static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, char const* /*args*/)
{
uint32 mapid = handler->GetSession()->GetPlayer()->GetMapId();
dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid);
dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId());
dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid, handler->GetSession()->GetPlayer()->GetTerrainSwaps());
dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId(), handler->GetSession()->GetPlayer()->GetTerrainSwaps());
if (!navmesh || !navmeshquery)
{
handler->PSendSysMessage("NavMesh not loaded for current map.");
@@ -215,7 +215,7 @@ public:
MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager();
handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount());
dtNavMesh const* navmesh = manager->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId());
dtNavMesh const* navmesh = manager->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId(), handler->GetSession()->GetPlayer()->GetTerrainSwaps());
if (!navmesh)
{
handler->PSendSysMessage("NavMesh not loaded for current map.");
+7 -4
View File
@@ -1279,10 +1279,13 @@ public:
uint32 phase = (uint32)atoi((char*)args);
Unit* target = handler->getSelectedUnit();
if (target)
target->SetInPhase(phase, true, !target->IsInPhase(phase));
else
handler->GetSession()->GetPlayer()->SetInPhase(phase, true, !handler->GetSession()->GetPlayer()->IsInPhase(phase));
if (!target)
target = handler->GetSession()->GetPlayer();
target->SetInPhase(phase, true, !target->IsInPhase(phase));
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->SendUpdatePhasing();
return true;
}
+37 -8
View File
@@ -206,6 +206,7 @@ public:
{ "model", rbac::RBAC_PERM_COMMAND_NPC_SET_MODEL, false, &HandleNpcSetModelCommand, "", NULL },
{ "movetype", rbac::RBAC_PERM_COMMAND_NPC_SET_MOVETYPE, false, &HandleNpcSetMoveTypeCommand, "", NULL },
{ "phase", rbac::RBAC_PERM_COMMAND_NPC_SET_PHASE, false, &HandleNpcSetPhaseCommand, "", NULL },
{ "phasegroup", rbac::RBAC_PERM_COMMAND_NPC_SET_PHASE, false, &HandleNpcSetPhaseGroup, "", NULL },
{ "spawndist", rbac::RBAC_PERM_COMMAND_NPC_SET_SPAWNDIST, false, &HandleNpcSetSpawnDistCommand, "", NULL },
{ "spawntime", rbac::RBAC_PERM_COMMAND_NPC_SET_SPAWNTIME, false, &HandleNpcSetSpawnTimeCommand, "", NULL },
{ "data", rbac::RBAC_PERM_COMMAND_NPC_SET_DATA, false, &HandleNpcSetDataCommand, "", NULL },
@@ -285,9 +286,6 @@ public:
return false;
}
for (auto phase : chr->GetPhases())
creature->SetInPhase(phase, false, true);
creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask());
ObjectGuid::LowType db_guid = creature->GetDBTableGUIDLow();
@@ -1100,7 +1098,37 @@ public:
}
//npc phase handling
//change phase of creature or pet
//change phase of creature
static bool HandleNpcSetPhaseGroup(ChatHandler* handler, char const* args)
{
if (!*args)
return false;
uint32 phaseGroupId = (uint32)atoi((char*)args);
Creature* creature = handler->getSelectedCreature();
if (!creature || creature->IsPet())
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
creature->ClearPhases();
for (uint32 id : sDB2Manager.GetPhasesForGroup(phaseGroupId))
creature->SetInPhase(id, false, true); // don't send update here for multiple phases, only send it once after adding all phases
creature->UpdateObjectVisibility();
creature->SetDBPhase(-int(phaseGroupId));
creature->SaveToDB();
return true;
}
//npc phase handling
//change phase of creature
static bool HandleNpcSetPhaseCommand(ChatHandler* handler, char const* args)
{
if (!*args)
@@ -1109,17 +1137,18 @@ public:
uint32 phase = (uint32) atoi((char*)args);
Creature* creature = handler->getSelectedCreature();
if (!creature)
if (!creature || creature->IsPet())
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
creature->SetInPhase(phase, true, !creature->IsInPhase(phase));
creature->ClearPhases();
creature->SetInPhase(phase, true, true);
creature->SetDBPhase(phase);
if (!creature->IsPet())
creature->SaveToDB();
creature->SaveToDB();
return true;
}
+3 -3
View File
@@ -1104,10 +1104,10 @@ public:
static bool HandleReloadPhaseDefinitionsCommand(ChatHandler* handler, const char* /*args*/)
{
TC_LOG_INFO("misc", "Reloading phase_definitions table...");
sObjectMgr->LoadPhaseDefinitions();
TC_LOG_INFO("misc", "Reloading terrain_phase_info table...");
sObjectMgr->LoadTerrainPhaseInfo();
sWorld->UpdatePhaseDefinitions();
handler->SendGlobalGMSysMessage("Phase Definitions reloaded.");
handler->SendGlobalGMSysMessage("Terrain phase infos reloaded.");
return true;
}
+4 -8
View File
@@ -682,8 +682,7 @@ public:
return false;
}
for (auto phase : chr->GetPhases())
wpCreature2->SetInPhase(phase, false, true);
wpCreature2->CopyPhaseFrom(chr);
wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask());
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
@@ -902,8 +901,7 @@ public:
return false;
}
for (auto phase : chr->GetPhases())
wpCreature->SetInPhase(phase, false, true);
wpCreature->CopyPhaseFrom(chr);
// Set "wpguid" column to the visual waypoint
stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID);
@@ -967,8 +965,7 @@ public:
return false;
}
for (auto phase : chr->GetPhases())
creature->SetInPhase(phase, false, true);
creature->CopyPhaseFrom(chr);
creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask());
if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map))
@@ -1019,8 +1016,7 @@ public:
return false;
}
for (auto phase : chr->GetPhases())
creature->SetInPhase(phase, false, true);
creature->CopyPhaseFrom(chr);
creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask());
if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map))
@@ -172,8 +172,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId)
return true;
}
for (auto phase : player->GetPhases())
go->SetInPhase(phase, false, true);
go->CopyPhaseFrom(player);
go->SetRespawnTime(0);
@@ -209,8 +208,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId)
return true;
}
for (auto phase : player->GetPhases())
go->SetInPhase(phase, false, true);
go->CopyPhaseFrom(player);
go->SetRespawnTime(0);
@@ -336,11 +336,16 @@ 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, phaseMask, 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, phaseMask) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
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);
// Creature respawn
PrepareStatement(CHAR_SEL_CREATURE_RESPAWNS, "SELECT guid, respawnTime FROM creature_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH);
@@ -294,6 +294,11 @@ enum CharacterDatabaseStatements
CHAR_DEL_CORPSE,
CHAR_DEL_PLAYER_CORPSES,
CHAR_DEL_OLD_CORPSES,
CHAR_SEL_CORPSE_PHASES,
CHAR_DEL_CORPSE_PHASES,
CHAR_DEL_PLAYER_CORPSES_PHASES,
CHAR_DEL_OLD_CORPSE_PHASES,
CHAR_INS_CORPSE_PHASES,
CHAR_SEL_CREATURE_RESPAWNS,
CHAR_REP_CREATURE_RESPAWN,
@@ -81,10 +81,10 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM creature WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
PrepareStatement(WORLD_INS_CREATURE, "INSERT INTO creature (guid, id , map, spawnMask, phaseMask, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint, curhealth, curmana, MovementType, npcflag, unit_flags, dynamicflags) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_INS_CREATURE, "INSERT INTO creature (guid, id , map, spawnMask, PhaseId, PhaseGroup, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint, curhealth, curmana, MovementType, npcflag, unit_flags, dynamicflags) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_DEL_GAME_EVENT_CREATURE, "DELETE FROM game_event_creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP, "DELETE FROM game_event_model_equip WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_INS_GAMEOBJECT, "INSERT INTO gameobject (guid, id, map, spawnMask, phaseMask, position_x, position_y, position_z, orientation, rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_INS_GAMEOBJECT, "INSERT INTO gameobject (guid, id, map, spawnMask, position_x, position_y, position_z, orientation, rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_INS_DISABLES, "INSERT INTO disables (entry, sourceType, flags, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_DISABLES, "SELECT entry FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC);
@@ -3347,6 +3347,7 @@ Logger.sql.updates=3,Console Server
#Logger.network.opcode=3,Console Server
#Logger.network.soap=3,Console Server
#Logger.outdoorpvp=3,Console Server
#Logger.phase=3,Console Server
#Logger.pool=3,Console Server
#Logger.rbac=3,Console Server
#Logger.scripts=3,Console Server