From ce4e1378893cb03792bc235e91d0b4e517c94384 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Fri, 9 Mar 2018 23:44:05 +0100 Subject: [PATCH] Core/Entities: Take terrain swaps into account when calculating LoS/height/area --- src/server/game/Entities/Object/Object.cpp | 9 ++-- src/server/game/Entities/Player/Player.cpp | 4 +- src/server/game/Entities/Unit/Unit.cpp | 6 +-- src/server/game/Globals/ObjectMgr.cpp | 17 +++++-- src/server/game/Handlers/MovementHandler.cpp | 2 +- src/server/game/Maps/Map.cpp | 46 +++++++++---------- src/server/game/Maps/Map.h | 18 ++++---- src/server/game/Maps/MapManager.h | 13 +++--- .../FleeingMovementGenerator.cpp | 2 +- src/server/game/Movement/PathGenerator.cpp | 6 +-- src/server/game/Phasing/PhaseShift.cpp | 29 ++++++++++++ src/server/game/Phasing/PhaseShift.h | 1 + src/server/game/Phasing/PhasingHandler.cpp | 6 ++- src/server/game/Spells/Spell.cpp | 6 +-- src/server/scripts/Commands/cs_go.cpp | 6 +-- src/server/scripts/Commands/cs_misc.cpp | 4 +- src/server/scripts/Commands/cs_tele.cpp | 2 +- .../instance_the_black_morass.cpp | 2 +- .../TheBlackMorass/the_black_morass.cpp | 2 +- 19 files changed, 111 insertions(+), 70 deletions(-) diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 7d1b5839f37..4460dac48bc 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1297,7 +1297,7 @@ void WorldObject::ProcessPositionDataChanged(PositionFullTerrainStatus const& da void WorldObject::AddToWorld() { Object::AddToWorld(); - GetBaseMap()->GetZoneAndAreaId(m_zoneId, m_areaId, GetPositionX(), GetPositionY(), GetPositionZ()); + GetBaseMap()->GetZoneAndAreaId(GetPhaseShift(), m_zoneId, m_areaId, GetPositionX(), GetPositionY(), GetPositionZ()); } void WorldObject::RemoveFromWorld() @@ -2101,7 +2101,8 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert } // Set the summon to the summoner's phase - PhasingHandler::InheritPhaseShift(summon, summoner); + if (summoner) + PhasingHandler::InheritPhaseShift(summon, summoner); summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId); @@ -2476,7 +2477,7 @@ float NormalizeZforCollision(WorldObject* obj, float x, float y, float z) return z; } LiquidData liquid_status; - ZLiquidStatus res = obj->GetMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquid_status); + ZLiquidStatus res = obj->GetMap()->GetLiquidStatus(obj->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &liquid_status); if (res && liquid_status.level > helper) // water must be above ground { if (liquid_status.level > z) // z is underwater @@ -2503,7 +2504,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float } destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ()); - bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f); + bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetPhaseShift().GetTerrainMapId(GetMapId(), pos.m_positionX, pos.m_positionY), pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f); // collision occured if (col) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index fef28a96973..b75dd0a1e11 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -6434,7 +6434,7 @@ void Player::CheckAreaExploreAndOutdoor() return; bool isOutdoor; - uint32 areaId = GetBaseMap()->GetAreaId(GetPositionX(), GetPositionY(), GetPositionZ(), &isOutdoor); + uint32 areaId = GetBaseMap()->GetAreaId(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), &isOutdoor); AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId); if (sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK) && !isOutdoor) @@ -7357,7 +7357,7 @@ uint32 Player::GetZoneIdFromDB(ObjectGuid guid) if (!sMapStore.LookupEntry(map)) return 0; - zone = sMapMgr->GetZoneId(map, posx, posy, posz); + zone = sMapMgr->GetZoneId(PhaseShift(), map, posx, posy, posz); if (zone > 0) { diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index bb31bc01edd..7f101ee0032 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3106,12 +3106,12 @@ bool Unit::isInAccessiblePlaceFor(Creature const* c) const bool Unit::IsInWater() const { - return GetBaseMap()->IsInWater(GetPositionX(), GetPositionY(), GetPositionZ()); + return GetBaseMap()->IsInWater(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ()); } bool Unit::IsUnderWater() const { - return GetBaseMap()->IsUnderWater(GetPositionX(), GetPositionY(), GetPositionZ()); + return GetBaseMap()->IsUnderWater(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ()); } void Unit::ProcessPositionDataChanged(PositionFullTerrainStatus const& data) @@ -8098,7 +8098,7 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const mountFlags = areaTable->MountFlags; LiquidData liquid; - ZLiquidStatus liquidStatus = GetMap()->GetLiquidStatus(GetPositionX(), GetPositionY(), GetPositionZ(), MAP_ALL_LIQUIDS, &liquid); + ZLiquidStatus liquidStatus = GetMap()->GetLiquidStatus(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), MAP_ALL_LIQUIDS, &liquid); isSubmerged = (liquidStatus & LIQUID_MAP_UNDER_WATER) != 0 || HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING); isInWater = (liquidStatus & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 39ec0d6e960..505cd405b5a 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -40,6 +40,7 @@ #include "MapManager.h" #include "Object.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "PoolMgr.h" #include "ReputationMgr.h" #include "ScriptMgr.h" @@ -1850,7 +1851,9 @@ void ObjectMgr::LoadCreatures() if (GetMapDifficultyData(i, Difficulty(k))) spawnMasks[i] |= (1 << k); - _creatureDataStore.rehash(result->GetRowCount()); + PhaseShift phaseShift; + + _creatureDataStore.reserve(result->GetRowCount()); do { @@ -2018,7 +2021,8 @@ void ObjectMgr::LoadCreatures() { uint32 zoneId = 0; uint32 areaId = 0; - sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); + PhasingHandler::InitDbVisibleMapId(phaseShift, data.terrainSwapMap); + sMapMgr->GetZoneAndAreaId(phaseShift, zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA); @@ -2191,7 +2195,9 @@ void ObjectMgr::LoadGameobjects() if (GetMapDifficultyData(i, Difficulty(k))) spawnMasks[i] |= (1 << k); - _gameObjectDataStore.rehash(result->GetRowCount()); + PhaseShift phaseShift; + + _gameObjectDataStore.reserve(result->GetRowCount()); do { @@ -2367,7 +2373,8 @@ void ObjectMgr::LoadGameobjects() { uint32 zoneId = 0; uint32 areaId = 0; - sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); + PhasingHandler::InitDbVisibleMapId(phaseShift, data.terrainSwapMap); + sMapMgr->GetZoneAndAreaId(phaseShift, zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA); @@ -6331,7 +6338,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetDefaultGraveYard(uint32 team) const WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team) const { // search for zone associated closest graveyard - uint32 zoneId = sMapMgr->GetZoneId(MapId, x, y, z); + uint32 zoneId = sMapMgr->GetZoneId(PhaseShift(), MapId, x, y, z); if (!zoneId) { diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 354a3376fdf..404f6d5f336 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -373,7 +373,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { // now client not include swimming flag in case jumping under water - plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); + plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(plrMover->GetPhaseShift(), movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } uint32 mstime = GameTime::GetGameTimeMS(); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index bfde82d670a..9fbb2a2da46 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2248,7 +2248,7 @@ float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, LiquidData liquid_status; - ZLiquidStatus res = GetLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status); + ZLiquidStatus res = GetLiquidStatus(phaseShift, x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status); switch (res) { case LIQUID_MAP_ABOVE_WATER: @@ -2263,7 +2263,7 @@ float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, return VMAP_INVALID_HEIGHT_VALUE; } -float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const +float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const { // find raw .map surface under Z coordinates float mapHeight = VMAP_INVALID_HEIGHT_VALUE; @@ -2280,7 +2280,7 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); if (vmgr->isHeightCalcEnabled()) - vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor + vmapHeight = vmgr->getHeight(phaseShift.GetTerrainMapId(GetId(), x, y), x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor } // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT @@ -2329,13 +2329,13 @@ inline bool IsOutdoorWMO(uint32 mogpFlags, int32 /*adtId*/, int32 /*rootId*/, in return outdoor; } -bool Map::IsOutdoors(float x, float y, float z) const +bool Map::IsOutdoors(PhaseShift const& phaseShift, float x, float y, float z) const { uint32 mogpFlags; int32 adtId, rootId, groupId; // no wmo found? -> outside by default - if (!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) + if (!GetAreaInfo(phaseShift, x, y, z, mogpFlags, adtId, rootId, groupId)) return true; AreaTableEntry const* atEntry = nullptr; @@ -2348,11 +2348,11 @@ bool Map::IsOutdoors(float x, float y, float z) const return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry); } -bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const +bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const { float vmap_z = z; VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - if (vmgr->getAreaInfo(GetId(), x, y, vmap_z, flags, adtId, rootId, groupId)) + if (vmgr->getAreaInfo(phaseShift.GetTerrainMapId(GetId(), x, y), x, y, vmap_z, flags, adtId, rootId, groupId)) { // check if there's terrain between player height and object height if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) @@ -2367,7 +2367,7 @@ bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, in return false; } -uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const +uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, bool *isOutdoors) const { uint32 mogpFlags; int32 adtId, rootId, groupId; @@ -2375,7 +2375,7 @@ uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const AreaTableEntry const* atEntry = nullptr; bool haveAreaInfo = false; - if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) + if (GetAreaInfo(phaseShift, x, y, z, mogpFlags, adtId, rootId, groupId)) { haveAreaInfo = true; wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId); @@ -2407,9 +2407,9 @@ uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const return areaId; } -uint32 Map::GetZoneId(float x, float y, float z) const +uint32 Map::GetZoneId(PhaseShift const& phaseShift, float x, float y, float z) const { - uint32 areaId = GetAreaId(x, y, z); + uint32 areaId = GetAreaId(phaseShift, x, y, z); if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId)) if (area->zone) return area->zone; @@ -2417,9 +2417,9 @@ uint32 Map::GetZoneId(float x, float y, float z) const return areaId; } -void Map::GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const +void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z) const { - areaid = zoneid = GetAreaId(x, y, z); + areaid = zoneid = GetAreaId(phaseShift, x, y, z); if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaid)) if (area->zone) zoneid = area->zone; @@ -2433,14 +2433,14 @@ uint8 Map::GetTerrainType(float x, float y) const return 0; } -ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const +ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const { ZLiquidStatus result = LIQUID_MAP_NO_WATER; VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); float liquid_level = INVALID_HEIGHT; float ground_level = INVALID_HEIGHT; uint32 liquid_type = 0; - if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) + if (vmgr->GetLiquidLevel(phaseShift.GetTerrainMapId(GetId(), x, y), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) { TC_LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type); // Check water level and ground level @@ -2459,7 +2459,7 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp if (liquid_type && liquid_type < 21) { - if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(x, y, z))) + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(phaseShift, x, y, z))) { uint32 overrideLiquid = area->LiquidTypeOverride[liquidFlagType]; if (!overrideLiquid && area->zone) @@ -2630,7 +2630,7 @@ float Map::GetWaterLevel(float x, float y) const bool Map::isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const { if ((checks & LINEOFSIGHT_CHECK_VMAP) - && !VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2, ignoreFlags)) + && !VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(phaseShift.GetTerrainMapId(GetId(), x1, x2), x1, y1, z1, x2, y2, z2, ignoreFlags)) return false; if (sWorld->getBoolConfig(CONFIG_CHECK_GOBJECT_LOS) && (checks & LINEOFSIGHT_CHECK_GOBJECT) && !_dynamicTree.isInLineOfSight({x1, y1, z1}, {x2, y2, z2}, phaseShift)) @@ -2654,19 +2654,19 @@ bool Map::getObjectHitPos(PhaseShift const& phaseShift, float x1, float y1, floa float Map::GetHeight(PhaseShift const& phaseShift, float x, float y, float z, bool vmap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const { - return std::max(GetHeight(x, y, z, vmap, maxSearchDist), GetGameObjectFloor(phaseShift, x, y, z, maxSearchDist)); + return std::max(GetStaticHeight(phaseShift, x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phaseShift)); } -bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const +bool Map::IsInWater(PhaseShift const& phaseShift, float x, float y, float pZ, LiquidData* data) const { LiquidData liquid_status; LiquidData* liquid_ptr = data ? data : &liquid_status; - return (GetLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; + return (GetLiquidStatus(phaseShift, x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; } -bool Map::IsUnderWater(float x, float y, float z) const +bool Map::IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z) const { - return (GetLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0; + return (GetLiquidStatus(phaseShift, x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0; } bool Map::CheckGridIntegrity(Creature* c, bool moved) const @@ -3912,7 +3912,7 @@ void Map::RemoveOldCorpses() void Map::SendZoneDynamicInfo(Player* player) { - uint32 zoneId = GetZoneId(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); + uint32 zoneId = GetZoneId(player->GetPhaseShift(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); ZoneDynamicInfoMap::const_iterator itr = _zoneDynamicInfo.find(zoneId); if (itr == _zoneDynamicInfo.end()) return; diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index e4c6c50c0fa..8fd5e27cd37 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -359,22 +359,22 @@ class TC_GAME_API Map : public GridRefManager // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height - float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; + float GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; void GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS) const; - ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr) const; + ZLiquidStatus GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr) const; - bool GetAreaInfo(float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; - uint32 GetAreaId(float x, float y, float z, bool *isOutdoors = nullptr) const; - uint32 GetZoneId(float x, float y, float z) const; - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const; + bool GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; + uint32 GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, bool *isOutdoors = nullptr) const; + uint32 GetZoneId(PhaseShift const& phaseShift, float x, float y, float z) const; + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z) const; - bool IsOutdoors(float x, float y, float z) const; + bool IsOutdoors(PhaseShift const& phaseShift, float x, float y, float z) const; uint8 GetTerrainType(float x, float y) const; float GetWaterLevel(float x, float y) const; - bool IsInWater(float x, float y, float z, LiquidData* data = nullptr) const; - bool IsUnderWater(float x, float y, float z) const; + bool IsInWater(PhaseShift const& phaseShift, float x, float y, float z, LiquidData* data = nullptr) const; + bool IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z) const; void MoveAllCreaturesInMoveList(); void MoveAllGameObjectsInMoveList(); diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index ca75b7382f3..f875cc2e129 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -26,6 +26,7 @@ #include "MapUpdater.h" #include +class PhaseShift; class Transport; struct TransportCreatureProto; @@ -39,20 +40,20 @@ class TC_GAME_API MapManager Map* CreateMap(uint32 mapId, Player* player, uint32 loginInstanceId=0); Map* FindMap(uint32 mapId, uint32 instanceId) const; - uint32 GetAreaId(uint32 mapid, float x, float y, float z) const + uint32 GetAreaId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z) const { Map const* m = const_cast(this)->CreateBaseMap(mapid); - return m->GetAreaId(x, y, z); + return m->GetAreaId(phaseShift, x, y, z); } - uint32 GetZoneId(uint32 mapid, float x, float y, float z) const + uint32 GetZoneId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z) const { Map const* m = const_cast(this)->CreateBaseMap(mapid); - return m->GetZoneId(x, y, z); + return m->GetZoneId(phaseShift, x, y, z); } - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) { Map const* m = const_cast(this)->CreateBaseMap(mapid); - m->GetZoneAndAreaId(zoneid, areaid, x, y, z); + m->GetZoneAndAreaId(phaseShift, zoneid, areaid, x, y, z); } void Initialize(void); diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 8fdbd03ec86..5d227eef3f9 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -116,7 +116,7 @@ void FleeingMovementGenerator::SetTargetLocation(T* owner) // Add LOS check for target point Position currentPosition = owner->GetPosition(); - if (!VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(owner->GetMapId(), currentPosition.m_positionX, currentPosition.m_positionY, currentPosition.m_positionZ + 1.0f, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ() + 1.0f, VMAP::ModelIgnoreFlags::Nothing)) + if (!VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(owner->GetPhaseShift().GetTerrainMapId(owner->GetMapId(), currentPosition.m_positionX, currentPosition.m_positionY), currentPosition.m_positionX, currentPosition.m_positionY, currentPosition.m_positionZ + 1.0f, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ() + 1.0f, VMAP::ModelIgnoreFlags::Nothing)) { _timer.Reset(200); return; diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 0d447effabb..4755e8dfd54 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -185,7 +185,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // Check both start and end points, if they're both in water, then we can *safely* let the creature move for (uint32 i = 0; i < _pathPoints.size(); ++i) { - ZLiquidStatus status = _sourceUnit->GetBaseMap()->GetLiquidStatus(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); + ZLiquidStatus status = _sourceUnit->GetBaseMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); // One of the points is not in the water, cancel movement. if (status == LIQUID_MAP_NO_WATER) { @@ -211,7 +211,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con Creature* owner = (Creature*)_sourceUnit; G3D::Vector3 const& p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) + if (_sourceUnit->GetBaseMap()->IsUnderWater(_sourceUnit->GetPhaseShift(), p.x, p.y, p.z)) { TC_LOG_DEBUG("maps", "++ BuildPolyPath :: underWater case\n"); if (owner->CanSwim()) @@ -648,7 +648,7 @@ void PathGenerator::UpdateFilter() NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) { LiquidData data; - ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); + ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &data); if (liquidStatus == LIQUID_MAP_NO_WATER) return NAV_GROUND; diff --git a/src/server/game/Phasing/PhaseShift.cpp b/src/server/game/Phasing/PhaseShift.cpp index cfeaf61c199..0762d958530 100644 --- a/src/server/game/Phasing/PhaseShift.cpp +++ b/src/server/game/Phasing/PhaseShift.cpp @@ -17,6 +17,8 @@ #include "PhaseShift.h" #include "Containers.h" +#include "GridDefines.h" +#include "VMapFactory.h" bool PhaseShift::AddPhase(uint32 phaseId, PhaseFlags flags, PhaseInfoStruct const* phase, std::vector const* areaConditions, int32 references /*= 1*/) { @@ -145,6 +147,33 @@ bool PhaseShift::CanSee(PhaseShift const& other) const return checkInversePhaseShift(other, *this); } +uint32 PhaseShift::GetTerrainMapId(uint32 realMapId, float x, float y) const +{ + if (VisibleMapIds.empty()) + return realMapId; + + if (VisibleMapIds.size() == 1) + return VisibleMapIds.begin()->first; + + GridCoord gridCoord = Trinity::ComputeGridCoord(x, y); + int32 gx = (MAX_NUMBER_OF_GRIDS - 1) - gridCoord.x_coord; + int32 gy = (MAX_NUMBER_OF_GRIDS - 1) - gridCoord.y_coord; + + int32 minDistance = std::numeric_limits::max(); + uint32 terrainMapId; + for (auto itr = VisibleMapIds.begin(); itr != VisibleMapIds.end(); ++itr) + { + int32 dist = VMAP::VMapFactory::createOrGetVMapManager()->GetDistanceToClosestPrimaryTile(itr->first, gx, gy); + if (dist < minDistance) + { + minDistance = dist; + terrainMapId = itr->first; + } + } + + return terrainMapId; +} + void PhaseShift::ModifyPhasesReferences(PhaseContainer::iterator itr, int32 references) { itr->References += references; diff --git a/src/server/game/Phasing/PhaseShift.h b/src/server/game/Phasing/PhaseShift.h index 7576af4a9c5..a175410c40a 100644 --- a/src/server/game/Phasing/PhaseShift.h +++ b/src/server/game/Phasing/PhaseShift.h @@ -103,6 +103,7 @@ public: void ClearPhases(); bool CanSee(PhaseShift const& other) const; + uint32 GetTerrainMapId(uint32 realMapId, float x, float y) const; protected: friend class PhasingHandler; diff --git a/src/server/game/Phasing/PhasingHandler.cpp b/src/server/game/Phasing/PhasingHandler.cpp index 1294f58809d..ef1f2d80087 100644 --- a/src/server/game/Phasing/PhasingHandler.cpp +++ b/src/server/game/Phasing/PhasingHandler.cpp @@ -288,7 +288,7 @@ void PhasingHandler::OnConditionChange(WorldObject* object) for (auto itr = phaseShift.Phases.begin(); itr != phaseShift.Phases.end();) { - if (!sConditionMgr->IsObjectMeetToConditions(srcInfo, *itr->AreaConditions)) + if (itr->AreaConditions && !sConditionMgr->IsObjectMeetToConditions(srcInfo, *itr->AreaConditions)) { newSuppressions.AddPhase(itr->Id, itr->Flags, itr->PhaseInfo, itr->AreaConditions, itr->References); itr = phaseShift.Phases.erase(itr); @@ -299,7 +299,7 @@ void PhasingHandler::OnConditionChange(WorldObject* object) for (auto itr = suppressedPhaseShift.Phases.begin(); itr != suppressedPhaseShift.Phases.end();) { - if (sConditionMgr->IsObjectMeetToConditions(srcInfo, *itr->AreaConditions)) + if (sConditionMgr->IsObjectMeetToConditions(srcInfo, *ASSERT_NOTNULL(itr->AreaConditions))) { changed = phaseShift.AddPhase(itr->Id, itr->Flags, itr->PhaseInfo, itr->AreaConditions, itr->References) || changed; itr = suppressedPhaseShift.Phases.erase(itr); @@ -446,6 +446,7 @@ void PhasingHandler::FillPartyMemberPhase(WorldPacket* data, PhaseShift const& p void PhasingHandler::InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId) { + phaseShift.ClearPhases(); phaseShift.IsDbPhaseShift = true; EnumClassFlag flags = PhaseShiftFlags::None; @@ -473,6 +474,7 @@ void PhasingHandler::InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlag void PhasingHandler::InitDbVisibleMapId(PhaseShift& phaseShift, int32 visibleMapId) { + phaseShift.VisibleMapIds.clear(); if (visibleMapId != -1) phaseShift.AddVisibleMapId(visibleMapId, sObjectMgr->GetTerrainSwapInfo(visibleMapId)); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 0acebd94256..b289c048c0f 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1306,7 +1306,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseShift(), x, y, z, true, 50.0f); float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; LiquidData liquidData; - if (m_caster->GetMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquidData)) + if (m_caster->GetMap()->GetLiquidStatus(m_caster->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &liquidData)) liquidLevel = liquidData.level; if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level @@ -5042,11 +5042,11 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (m_caster->GetTypeId() == TYPEID_PLAYER && VMAP::VMapFactory::createOrGetVMapManager()->isLineOfSightCalcEnabled()) { if (m_spellInfo->HasAttribute(SPELL_ATTR0_OUTDOORS_ONLY) && - !m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ())) + !m_caster->GetMap()->IsOutdoors(m_caster->GetPhaseShift(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ())) return SPELL_FAILED_ONLY_OUTDOORS; if (m_spellInfo->HasAttribute(SPELL_ATTR0_INDOORS_ONLY) && - m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ())) + m_caster->GetMap()->IsOutdoors(m_caster->GetPhaseShift(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ())) return SPELL_FAILED_ONLY_INDOORS; } diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 8224b83a33d..c9aec14d8af 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -245,7 +245,7 @@ public: player->SaveRecallPosition(); Map const* map = sMapMgr->CreateBaseMap(mapId); - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + float z = std::max(map->GetStaticHeight(PhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); player->TeleportTo(mapId, x, y, z, player->GetOrientation()); return true; @@ -465,7 +465,7 @@ public: else player->SaveRecallPosition(); - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + float z = std::max(map->GetStaticHeight(PhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); player->TeleportTo(zoneEntry->mapid, x, y, z, player->GetOrientation()); return true; @@ -513,7 +513,7 @@ public: return false; } Map const* map = sMapMgr->CreateBaseMap(mapId); - z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + z = std::max(map->GetStaticHeight(PhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); } // stop flight if need diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 0e7ad943fb6..c8f972d24e4 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -253,7 +253,7 @@ public: if (haveVMap) { - if (map->IsOutdoors(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ())) + if (map->IsOutdoors(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ())) handler->PSendSysMessage(LANG_GPS_POSITION_OUTDOORS); else handler->PSendSysMessage(LANG_GPS_POSITION_INDOORS); @@ -277,7 +277,7 @@ public: zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap, haveMMap); LiquidData liquidStatus; - ZLiquidStatus status = map->GetLiquidStatus(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus); + ZLiquidStatus status = map->GetLiquidStatus(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus); if (status) handler->PSendSysMessage(LANG_LIQUID_STATUS, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, liquidStatus.type_flags, status); diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index be818f6ff42..f584254abc8 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -202,7 +202,7 @@ public: SQLTransaction dummy; Player::SavePositionInDB(WorldLocation(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation), - sMapMgr->GetZoneId(tele->mapId, tele->position_x, tele->position_y, tele->position_z), target_guid, dummy); + sMapMgr->GetZoneId(PhaseShift(), tele->mapId, tele->position_x, tele->position_y, tele->position_z), target_guid, dummy); } return true; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp index 09c79fd51dc..7f066983607 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp @@ -270,7 +270,7 @@ public: Position pos = me->GetRandomNearPosition(10.0f); //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + pos.m_positionZ = std::max(me->GetMap()->GetHeight(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); if (Creature* summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) return summon; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp index e54b10a5922..d25214cc737 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp @@ -305,7 +305,7 @@ public: Position pos = me->GetRandomNearPosition(10.0f); //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + pos.m_positionZ = std::max(me->GetMap()->GetHeight(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); if (Unit* Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) if (Unit* temp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MEDIVH)))