diff options
23 files changed, 321 insertions, 118 deletions
diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp index 40acfb6c49b..bae8ab38dc1 100644 --- a/src/common/Collision/DynamicTree.cpp +++ b/src/common/Collision/DynamicTree.cpp @@ -16,17 +16,16 @@ */ #include "DynamicTree.h" -//#include "QuadTree.h" -//#include "RegularGrid.h" #include "BoundingIntervalHierarchyWrapper.h" - +#include "GameObjectModel.h" #include "Log.h" +#include "MapTree.h" +#include "ModelIgnoreFlags.h" +#include "ModelInstance.h" #include "RegularGrid.h" #include "Timer.h" -#include "GameObjectModel.h" -#include "ModelInstance.h" -#include "ModelIgnoreFlags.h" - +#include "VMapFactory.h" +#include "VMapManager2.h" #include <G3D/AABox.h> #include <G3D/Ray.h> #include <G3D/Vector3.h> @@ -174,6 +173,41 @@ struct DynamicTreeIntersectionCallback_WithLogger bool didHit() const { return did_hit;} }; +struct DynamicTreeAreaInfoCallback +{ + DynamicTreeAreaInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask) {} + + void operator()(G3D::Vector3 const& p, GameObjectModel const& obj) + { + obj.intersectPoint(p, _areaInfo, _phaseMask); + } + + VMAP::AreaInfo const& GetAreaInfo() const { return _areaInfo; } + +private: + uint32 _phaseMask; + VMAP::AreaInfo _areaInfo; +}; + +struct DynamicTreeLocationInfoCallback +{ + DynamicTreeLocationInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask), _hitModel(nullptr) {} + + void operator()(G3D::Vector3 const& p, GameObjectModel const& obj) + { + if (obj.GetLocationInfo(p, _locationInfo, _phaseMask)) + _hitModel = &obj; + } + + VMAP::LocationInfo& GetLocationInfo() { return _locationInfo; } + GameObjectModel const* GetHitModel() const { return _hitModel; } + +private: + uint32 _phaseMask; + VMAP::LocationInfo _locationInfo; + GameObjectModel const* _hitModel; +}; + bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray, const G3D::Vector3& endPos, float& maxDist) const { @@ -253,3 +287,41 @@ float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, else return -G3D::finf(); } + +bool DynamicMapTree::getAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const +{ + G3D::Vector3 v(x, y, z + 0.5f); + DynamicTreeAreaInfoCallback intersectionCallBack(phasemask); + impl->intersectPoint(v, intersectionCallBack); + if (intersectionCallBack.GetAreaInfo().result) + { + flags = intersectionCallBack.GetAreaInfo().flags; + adtId = intersectionCallBack.GetAreaInfo().adtId; + rootId = intersectionCallBack.GetAreaInfo().rootId; + groupId = intersectionCallBack.GetAreaInfo().groupId; + z = intersectionCallBack.GetAreaInfo().ground_Z; + return true; + } + return false; +} + +void DynamicMapTree::getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const +{ + G3D::Vector3 v(x, y, z + 0.5f); + DynamicTreeLocationInfoCallback intersectionCallBack(phasemask); + impl->intersectPoint(v, intersectionCallBack); + if (intersectionCallBack.GetLocationInfo().hitModel) + { + data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z; + uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType(); + float liquidLevel; + if (!reqLiquidType || (dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())->GetLiquidFlagsPtr(liquidType) & reqLiquidType)) + if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel)) + data.liquidInfo = boost::in_place(liquidType, liquidLevel); + + data.areaInfo = boost::in_place(0, + intersectionCallBack.GetLocationInfo().rootId, + intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(), + intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags()); + } +} diff --git a/src/common/Collision/DynamicTree.h b/src/common/Collision/DynamicTree.h index 8f2729cb76a..a890f828b96 100644 --- a/src/common/Collision/DynamicTree.h +++ b/src/common/Collision/DynamicTree.h @@ -30,6 +30,11 @@ namespace G3D class GameObjectModel; struct DynTreeImpl; +namespace VMAP +{ + struct AreaAndLiquidData; +} + class TC_COMMON_API DynamicMapTree { DynTreeImpl *impl; @@ -44,6 +49,8 @@ public: bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray, const G3D::Vector3& endPos, float& maxDist) const; + bool getAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const; + void getAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const; bool getObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1, const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos, diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp index 54b48714c90..2c95187fbb2 100644 --- a/src/common/Collision/Models/GameObjectModel.cpp +++ b/src/common/Collision/Models/GameObjectModel.cpp @@ -146,6 +146,7 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model #endif owner = std::move(modelOwner); + isWmo = it->second.isWmo; return true; } @@ -183,6 +184,69 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto return hit; } +void GameObjectModel::intersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const +{ + if (!(phasemask & ph_mask) || !owner->IsSpawned() || !isMapObject()) + return; + + if (!iBound.contains(point)) + return; + + // child bounds are defined in object space: + Vector3 pModel = iInvRot * (point - iPos) * iInvScale; + Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); + float zDist; + if (iModel->IntersectPoint(pModel, zDirModel, zDist, info)) + { + Vector3 modelGround = pModel + zDist * zDirModel; + float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; + if (info.ground_Z < world_Z) + info.ground_Z = world_Z; + } +} + +bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const +{ + if (!(phasemask & ph_mask) || !owner->IsSpawned() || !isMapObject()) + return false; + + if (!iBound.contains(point)) + return false; + + // child bounds are defined in object space: + Vector3 pModel = iInvRot * (point - iPos) * iInvScale; + Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); + float zDist; + if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info)) + { + Vector3 modelGround = pModel + zDist * zDirModel; + float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; + if (info.ground_Z < world_Z) + { + info.ground_Z = world_Z; + return true; + } + } + + return false; +} + +bool GameObjectModel::GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const +{ + // child bounds are defined in object space: + Vector3 pModel = iInvRot * (point - iPos) * iInvScale; + //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); + float zDist; + if (info.hitModel->GetLiquidLevel(pModel, zDist)) + { + // calculate world height (zDist in model coords): + // assume WMO not tilted (wouldn't make much sense anyway) + liqHeight = zDist * iScale + iPos.z; + return true; + } + return false; +} + bool GameObjectModel::UpdatePosition() { if (!iModel) diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index 99ffef0ee98..78f17b75391 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -29,6 +29,8 @@ namespace VMAP { class WorldModel; + struct AreaInfo; + struct LocationInfo; enum class ModelIgnoreFlags : uint32; } @@ -38,6 +40,8 @@ struct GameObjectDisplayInfoEntry; class TC_COMMON_API GameObjectModelOwnerBase { public: + virtual ~GameObjectModelOwnerBase() = default; + virtual bool IsSpawned() const = 0; virtual uint32 GetDisplayId() const = 0; virtual uint32 GetPhaseMask() const = 0; @@ -45,12 +49,11 @@ public: virtual float GetOrientation() const = 0; virtual float GetScale() const = 0; virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const = 0; - virtual ~GameObjectModelOwnerBase() { } }; class TC_COMMON_API GameObjectModel /*, public Intersectable*/ { - GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(nullptr) { } + GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(nullptr), isWmo(false) { } public: std::string name; @@ -65,8 +68,12 @@ public: void enable(uint32 ph_mask) { phasemask = ph_mask;} bool isEnabled() const {return phasemask != 0;} + bool isMapObject() const { return isWmo; } bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const; + void intersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const; + bool GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const; + bool GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const; static GameObjectModel* Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath); @@ -83,6 +90,7 @@ private: float iScale; VMAP::WorldModel* iModel; std::unique_ptr<GameObjectModelOwnerBase> owner; + bool isWmo; }; TC_COMMON_API void LoadGameObjectModelList(std::string const& dataPath); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 9a6c9db819f..8228ef5a3ba 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1048,7 +1048,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u { // area/zone id is needed immediately for ZoneScript::GetCreatureEntry hook before it is known which creature template to load (no model/scale available yet) PositionFullTerrainStatus data; - GetMap()->GetFullTerrainStatusForPosition(GetPositionX(), GetPositionY(), GetPositionZ(), data, MAP_ALL_LIQUIDS, DEFAULT_COLLISION_HEIGHT); + GetMap()->GetFullTerrainStatusForPosition(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ(), data, MAP_ALL_LIQUIDS, DEFAULT_COLLISION_HEIGHT); ProcessPositionDataChanged(data); } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index f15780362d1..0cb8ab61365 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -2280,8 +2280,8 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, WorldOb uint32 modelId = m_goInfo->displayId; if (DestructibleModelDataEntry const* modelData = sDestructibleModelDataStore.LookupEntry(m_goInfo->building.destructibleData)) - if (modelData->DamagedDisplayId) - modelId = modelData->DamagedDisplayId; + if (modelData->State1Wmo) + modelId = modelData->State1Wmo; SetDisplayId(modelId); if (setHealth) @@ -2309,8 +2309,8 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, WorldOb uint32 modelId = m_goInfo->displayId; if (DestructibleModelDataEntry const* modelData = sDestructibleModelDataStore.LookupEntry(m_goInfo->building.destructibleData)) - if (modelData->DestroyedDisplayId) - modelId = modelData->DestroyedDisplayId; + if (modelData->State2Wmo) + modelId = modelData->State2Wmo; SetDisplayId(modelId); if (setHealth) @@ -2328,8 +2328,8 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, WorldOb uint32 modelId = m_goInfo->displayId; if (DestructibleModelDataEntry const* modelData = sDestructibleModelDataStore.LookupEntry(m_goInfo->building.destructibleData)) - if (modelData->RebuildingDisplayId) - modelId = modelData->RebuildingDisplayId; + if (modelData->State3Wmo) + modelId = modelData->State3Wmo; SetDisplayId(modelId); // restores to full health @@ -2662,13 +2662,13 @@ class GameObjectModelOwnerImpl : public GameObjectModelOwnerBase public: explicit GameObjectModelOwnerImpl(GameObject const* owner) : _owner(owner) { } - virtual bool IsSpawned() const override { return _owner->isSpawned(); } - virtual uint32 GetDisplayId() const override { return _owner->GetDisplayId(); } - virtual uint32 GetPhaseMask() const override { return _owner->GetPhaseMask(); } - virtual G3D::Vector3 GetPosition() const override { return G3D::Vector3(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); } - virtual float GetOrientation() const override { return _owner->GetOrientation(); } - virtual float GetScale() const override { return _owner->GetObjectScale(); } - virtual void DebugVisualizeCorner(G3D::Vector3 const& corner) const override { const_cast<GameObject*>(_owner)->SummonCreature(1, corner.x, corner.y, corner.z, 0, TEMPSUMMON_MANUAL_DESPAWN); } + bool IsSpawned() const override { return _owner->isSpawned(); } + uint32 GetDisplayId() const override { return _owner->GetDisplayId(); } + uint32 GetPhaseMask() const override { return _owner->GetPhaseMask(); } + G3D::Vector3 GetPosition() const override { return G3D::Vector3(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); } + float GetOrientation() const override { return _owner->GetOrientation(); } + float GetScale() const override { return _owner->GetObjectScale(); } + void DebugVisualizeCorner(G3D::Vector3 const& corner) const override { const_cast<GameObject*>(_owner)->SummonCreature(1, corner.x, corner.y, corner.z, 0, TEMPSUMMON_MANUAL_DESPAWN); } private: GameObject const* _owner; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 44fdec8c563..a149c484276 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1058,7 +1058,7 @@ void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 void WorldObject::UpdatePositionData() { PositionFullTerrainStatus data; - GetMap()->GetFullTerrainStatusForPosition(GetPositionX(), GetPositionY(), GetPositionZ(), data, MAP_ALL_LIQUIDS, GetCollisionHeight()); + GetMap()->GetFullTerrainStatusForPosition(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ(), data, MAP_ALL_LIQUIDS, GetCollisionHeight()); ProcessPositionDataChanged(data); } @@ -1076,7 +1076,7 @@ void WorldObject::ProcessPositionDataChanged(PositionFullTerrainStatus const& da void WorldObject::AddToWorld() { Object::AddToWorld(); - GetBaseMap()->GetZoneAndAreaId(m_zoneId, m_areaId, GetPositionX(), GetPositionY(), GetPositionZ()); + GetMap()->GetZoneAndAreaId(GetPhaseMask(), m_zoneId, m_areaId, GetPositionX(), GetPositionY(), GetPositionZ()); } void WorldObject::RemoveFromWorld() @@ -1827,12 +1827,6 @@ void WorldObject::ResetMap() //m_InstanceId = 0; } -Map const* WorldObject::GetBaseMap() const -{ - ASSERT(m_currMap); - return m_currMap->GetParent(); -} - void WorldObject::AddObjectToRemoveList() { ASSERT(m_uint32Values); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 7b735e5b2c7..c648b1d2914 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -394,9 +394,6 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation Map* FindMap() const { return m_currMap; } //used to check all object's GetMap() calls when object is not in world! - //this function should be removed in nearest time... - Map const* GetBaseMap() const; - void SetZoneScript(); void ClearZoneScript(); ZoneScript* GetZoneScript() const { return m_zoneScript; } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b7064c67b9c..1ef6a79e4f8 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1280,7 +1280,7 @@ void Player::Update(uint32 p_time) } // not auto-free ghost from body in instances or if its affected by risen ally - if (m_deathTimer > 0 && !GetBaseMap()->Instanceable() && !HasAuraType(SPELL_AURA_PREVENT_RESURRECTION) && !IsGhouled()) + if (m_deathTimer > 0 && !GetMap()->Instanceable() && !HasAuraType(SPELL_AURA_PREVENT_RESURRECTION) && !IsGhouled()) { if (p_time >= m_deathTimer) { @@ -6980,7 +6980,7 @@ uint32 Player::GetZoneIdFromDB(ObjectGuid guid) if (!sMapStore.LookupEntry(map)) return 0; - zone = sMapMgr->GetZoneId(map, posx, posy, posz); + zone = sMapMgr->GetZoneId(PHASEMASK_NORMAL, map, posx, posy, posz); if (zone > 0) { diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 9a88a8bc782..c44b56b62e2 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2215,7 +2215,7 @@ void ObjectMgr::LoadCreatures() { uint32 zoneId = 0; uint32 areaId = 0; - sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapId, data.spawnPoint); + sMapMgr->GetZoneAndAreaId(data.phaseMask, zoneId, areaId, data.mapId, data.spawnPoint); WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA); @@ -2522,7 +2522,7 @@ void ObjectMgr::LoadGameObjects() { uint32 zoneId = 0; uint32 areaId = 0; - sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapId, data.spawnPoint); + sMapMgr->GetZoneAndAreaId(data.phaseMask, zoneId, areaId, data.mapId, data.spawnPoint); WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA); @@ -6856,7 +6856,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(PHASEMASK_NORMAL, MapId, x, y, z); if (!zoneId) { diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 3d2e1ed4599..a8f1e9ad6c2 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -2184,7 +2184,7 @@ void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo) else { WorldSafeLocsEntry const * graveyardLocation = sObjectMgr->GetClosestGraveyard(instanceEntrance->target_X, instanceEntrance->target_Y, instanceEntrance->target_Z, instanceEntrance->target_mapId, SendMsgTo->GetTeam()); - uint32 const zoneId = sMapMgr->GetZoneId(graveyardLocation->map_id, graveyardLocation->x, graveyardLocation->y, graveyardLocation->z); + uint32 const zoneId = sMapMgr->GetZoneId(PHASEMASK_NORMAL, graveyardLocation->map_id, graveyardLocation->x, graveyardLocation->y, graveyardLocation->z); for (MemberSlot const& member : GetMemberSlots()) { diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index f8e38a775bc..9314fb82449 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -366,7 +366,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) 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->GetMap()->IsUnderWater(plrMover->GetPhaseMask(), movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } /* process position-change */ diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index e0378bfb7aa..bc23cc3ec5f 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2446,7 +2446,7 @@ float Map::GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, fl LiquidData liquid_status; - ZLiquidStatus res = GetLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status, collisionHeight); + ZLiquidStatus res = GetLiquidStatus(phasemask, x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status, collisionHeight); switch (res) { case LIQUID_MAP_ABOVE_WATER: @@ -2518,14 +2518,61 @@ float Map::GetMinHeight(float x, float y) const static inline bool IsInWMOInterior(uint32 mogpFlags) { return (mogpFlags & 0x2000) != 0; +} + +bool Map::GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const +{ + float vmap_z = z; + float dynamic_z = z; + float check_z = z; + VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); + uint32 vflags; + int32 vadtId; + int32 vrootId; + int32 vgroupId; + uint32 dflags; + int32 dadtId; + int32 drootId; + int32 dgroupId; + + bool hasVmapAreaInfo = vmgr->getAreaInfo(GetId(), x, y, vmap_z, vflags, vadtId, vrootId, vgroupId); + bool hasDynamicAreaInfo = _dynamicTree.getAreaInfo(x, y, dynamic_z, phaseMask, dflags, dadtId, drootId, dgroupId); + auto useVmap = [&]() { check_z = vmap_z; flags = vflags; adtId = vadtId; rootId = vrootId; groupId = vgroupId; }; + auto useDyn = [&]() { check_z = dynamic_z; flags = dflags; adtId = dadtId; rootId = drootId; groupId = dgroupId; }; + + if (hasVmapAreaInfo) + { + if (hasDynamicAreaInfo && dynamic_z > vmap_z) + useDyn(); + else + useVmap(); + } + else if (hasDynamicAreaInfo) + { + useDyn(); } -uint32 Map::GetAreaId(float x, float y, float z) const + if (hasVmapAreaInfo || hasDynamicAreaInfo) + { + // check if there's terrain between player height and object height + if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) + { + float mapHeight = gmap->getHeight(x, y); + // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice... + if (z + 2.0f > mapHeight && mapHeight > check_z) + return false; + } + return true; + } + return false; +} + +uint32 Map::GetAreaId(uint32 phaseMask, float x, float y, float z) const { uint32 mogpFlags; int32 adtId, rootId, groupId; float vmapZ = z; - bool hasVmapArea = VMAP::VMapFactory::createOrGetVMapManager()->getAreaInfo(GetId(), x, y, vmapZ, mogpFlags, adtId, rootId, groupId); + bool hasVmapArea = GetAreaInfo(phaseMask, x, y, vmapZ, mogpFlags, adtId, rootId, groupId); uint32 gridAreaId = 0; float gridMapHeight = INVALID_HEIGHT; @@ -2556,9 +2603,9 @@ uint32 Map::GetAreaId(float x, float y, float z) const return areaId; } -uint32 Map::GetZoneId(float x, float y, float z) const +uint32 Map::GetZoneId(uint32 phaseMask, float x, float y, float z) const { - uint32 areaId = GetAreaId(x, y, z); + uint32 areaId = GetAreaId(phaseMask, x, y, z); if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId)) if (area->zone) return area->zone; @@ -2566,15 +2613,15 @@ 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(uint32 phaseMask, uint32& zoneid, uint32& areaid, float x, float y, float z) const { - areaid = zoneid = GetAreaId(x, y, z); + areaid = zoneid = GetAreaId(phaseMask, x, y, z); if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaid)) if (area->zone) zoneid = area->zone; } -ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) const +ZLiquidStatus Map::GetLiquidStatus(uint32 phaseMask, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) const { ZLiquidStatus result = LIQUID_MAP_NO_WATER; VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); @@ -2603,7 +2650,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(phaseMask, x, y, z))) { uint32 overrideLiquid = area->LiquidTypeOverride[liquidFlagType]; if (!overrideLiquid && area->zone) @@ -2665,12 +2712,15 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp return result; } -void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) const +void Map::GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) const { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); VMAP::AreaAndLiquidData vmapData; + VMAP::AreaAndLiquidData dynData; + VMAP::AreaAndLiquidData* wmoData = nullptr; GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y); vmgr->getAreaAndLiquidData(GetId(), x, y, z, reqLiquidType, vmapData); + _dynamicTree.getAreaAndLiquidData(x, y, z, phaseMask, reqLiquidType, dynData); uint32 gridAreaId = 0; float gridMapHeight = INVALID_HEIGHT; @@ -2680,7 +2730,6 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul gridMapHeight = gmap->getHeight(x, y); } - bool vmapLocation = false; bool useGridLiquid = true; // floor is the height we are closer to (but only if above) @@ -2692,17 +2741,28 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul (G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || vmapData.floorZ > gridMapHeight)) { data.floorZ = vmapData.floorZ; - vmapLocation = true; + wmoData = &vmapData; + } + // NOTE: Objects will not detect a case when a wmo providing area/liquid despawns from under them + // but this is fine as these kind of objects are not meant to be spawned and despawned a lot + // example: Lich King platform + if (dynData.floorZ > VMAP_INVALID_HEIGHT && + G3D::fuzzyGe(z, dynData.floorZ - GROUND_HEIGHT_TOLERANCE) && + (G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || dynData.floorZ > gridMapHeight) && + (G3D::fuzzyLt(z, vmapData.floorZ - GROUND_HEIGHT_TOLERANCE) || dynData.floorZ > vmapData.floorZ)) + { + data.floorZ = dynData.floorZ; + wmoData = &dynData; } - if (vmapLocation) + if (wmoData) { - if (vmapData.areaInfo) + if (wmoData->areaInfo) { - data.areaInfo = boost::in_place(vmapData.areaInfo->adtId, vmapData.areaInfo->rootId, vmapData.areaInfo->groupId, vmapData.areaInfo->mogpFlags); + data.areaInfo = boost::in_place(wmoData->areaInfo->adtId, wmoData->areaInfo->rootId, wmoData->areaInfo->groupId, wmoData->areaInfo->mogpFlags); // wmo found - WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(vmapData.areaInfo->rootId, vmapData.areaInfo->adtId, vmapData.areaInfo->groupId); - data.outdoors = (vmapData.areaInfo->mogpFlags & 0x8) != 0; + WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(wmoData->areaInfo->rootId, wmoData->areaInfo->adtId, wmoData->areaInfo->groupId); + data.outdoors = (wmoData->areaInfo->mogpFlags & 0x8) != 0; if (wmoEntry) { data.areaId = wmoEntry->areaId; @@ -2715,7 +2775,7 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul if (!data.areaId) data.areaId = gridAreaId; - useGridLiquid = !IsInWMOInterior(vmapData.areaInfo->mogpFlags); + useGridLiquid = !IsInWMOInterior(wmoData->areaInfo->mogpFlags); } } else @@ -2733,9 +2793,9 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul // liquid processing data.liquidStatus = LIQUID_MAP_NO_WATER; - if (vmapLocation && vmapData.liquidInfo && vmapData.liquidInfo->level > vmapData.floorZ) + if (wmoData && wmoData->liquidInfo && wmoData->liquidInfo->level > wmoData->floorZ) { - uint32 liquidType = vmapData.liquidInfo->type; + uint32 liquidType = wmoData->liquidInfo->type; if (GetId() == 530 && liquidType == 2) // gotta love blizzard hacks liquidType = 15; @@ -2761,12 +2821,12 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul } data.liquidInfo = boost::in_place(); - data.liquidInfo->level = vmapData.liquidInfo->level; - data.liquidInfo->depth_level = vmapData.floorZ; + data.liquidInfo->level = wmoData->liquidInfo->level; + data.liquidInfo->depth_level = wmoData->floorZ; data.liquidInfo->entry = liquidType; data.liquidInfo->type_flags = 1 << liquidFlagType; - float delta = vmapData.liquidInfo->level - z; + float delta = wmoData->liquidInfo->level - z; if (delta > collisionHeight) data.liquidStatus = LIQUID_MAP_UNDER_WATER; else if (delta > 0.0f) @@ -2781,7 +2841,7 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul { LiquidData gridMapLiquid; ZLiquidStatus gridMapStatus = gmap->GetLiquidStatus(x, y, z, reqLiquidType, &gridMapLiquid, collisionHeight); - if (gridMapStatus != LIQUID_MAP_NO_WATER && (gridMapLiquid.level > vmapData.floorZ)) + if (gridMapStatus != LIQUID_MAP_NO_WATER && (!wmoData || gridMapLiquid.level > wmoData->floorZ)) { if (GetId() == 530 && gridMapLiquid.entry == 2) gridMapLiquid.entry = 15; @@ -2824,16 +2884,16 @@ bool Map::getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float return result; } -bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const +bool Map::IsInWater(uint32 phaseMask, 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(phaseMask, 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(uint32 phaseMask, 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(phaseMask, x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0; } bool Map::CheckGridIntegrity(Creature* c, bool moved) const diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 5d5c61bb80b..a6a4e53bc50 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -396,19 +396,20 @@ class TC_GAME_API Map : public GridRefManager<NGridType> Map const* GetParent() const { return m_parentMap; } - void GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h - ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h + void GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) const; + ZLiquidStatus GetLiquidStatus(uint32 phaseMask, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h - uint32 GetAreaId(float x, float y, float z) const; - uint32 GetAreaId(Position const& pos) const { return GetAreaId(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - uint32 GetZoneId(float x, float y, float z) const; - uint32 GetZoneId(Position const& pos) const { return GetZoneId(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const; - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, Position const& pos) const { GetZoneAndAreaId(zoneid, areaid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + bool GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; + uint32 GetAreaId(uint32 phaseMask, float x, float y, float z) const; + uint32 GetAreaId(uint32 phaseMask, Position const& pos) const { return GetAreaId(phaseMask, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + uint32 GetZoneId(uint32 phaseMask, float x, float y, float z) const; + uint32 GetZoneId(uint32 phaseMask, Position const& pos) const { return GetZoneId(phaseMask, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + void GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, float x, float y, float z) const; + void GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, Position const& pos) const { GetZoneAndAreaId(phaseMask, zoneid, areaid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } 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(uint32 phaseMask, float x, float y, float z, LiquidData* data = nullptr) const; + bool IsUnderWater(uint32 phaseMask, 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 9d3b1a1746b..2323e31ab9a 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -38,27 +38,27 @@ 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(uint32 phaseMask, uint32 mapid, float x, float y, float z) const { Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid); - return m->GetAreaId(x, y, z); + return m->GetAreaId(phaseMask, x, y, z); } - uint32 GetAreaId(uint32 mapid, Position const& pos) const { return GetAreaId(mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - uint32 GetAreaId(WorldLocation const& loc) const { return GetAreaId(loc.GetMapId(), loc); } - uint32 GetZoneId(uint32 mapid, float x, float y, float z) const + uint32 GetAreaId(uint32 phaseMask, uint32 mapid, Position const& pos) const { return GetAreaId(phaseMask, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + uint32 GetAreaId(uint32 phaseMask, WorldLocation const& loc) const { return GetAreaId(phaseMask, loc.GetMapId(), loc); } + uint32 GetZoneId(uint32 phaseMask, uint32 mapid, float x, float y, float z) const { Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid); - return m->GetZoneId(x, y, z); + return m->GetZoneId(phaseMask, x, y, z); } - uint32 GetZoneId(uint32 mapid, Position const& pos) const { return GetZoneId(mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - uint32 GetZoneId(WorldLocation const& loc) const { return GetZoneId(loc.GetMapId(), loc); } - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) const + uint32 GetZoneId(uint32 phaseMask, uint32 mapid, Position const& pos) const { return GetZoneId(phaseMask, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + uint32 GetZoneId(uint32 phaseMask, WorldLocation const& loc) const { return GetZoneId(phaseMask, loc.GetMapId(), loc); } + void GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) const { Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid); - m->GetZoneAndAreaId(zoneid, areaid, x, y, z); + m->GetZoneAndAreaId(phaseMask, zoneid, areaid, x, y, z); } - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, Position const& pos) const { GetZoneAndAreaId(zoneid, areaid, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, WorldLocation const& loc) const { GetZoneAndAreaId(zoneid, areaid, loc.GetMapId(), loc); } + void GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, uint32 mapid, Position const& pos) const { GetZoneAndAreaId(phaseMask, zoneid, areaid, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + void GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, WorldLocation const& loc) const { GetZoneAndAreaId(phaseMask, zoneid, areaid, loc.GetMapId(), loc); } void Initialize(void); void Update(uint32); diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 305c6b2bd67..35d518b752e 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -186,7 +186,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 = _source->GetBaseMap()->GetLiquidStatus(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, nullptr, _source->GetCollisionHeight()); + ZLiquidStatus status = _source->GetMap()->GetLiquidStatus(_source->GetPhaseMask(), _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, nullptr, _source->GetCollisionHeight()); // One of the points is not in the water, cancel movement. if (status == LIQUID_MAP_NO_WATER) { @@ -220,7 +220,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con bool buildShotrcut = false; G3D::Vector3 const& p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (_source->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) + if (_source->GetMap()->IsUnderWater(_source->GetPhaseMask(), p.x, p.y, p.z)) { TC_LOG_DEBUG("maps.mmaps", "++ BuildPolyPath :: underWater case"); if (Unit const* _sourceUnit = _source->ToUnit()) @@ -698,7 +698,7 @@ void PathGenerator::UpdateFilter() NavTerrainFlag PathGenerator::GetNavTerrain(float x, float y, float z) { LiquidData data; - ZLiquidStatus liquidStatus = _source->GetBaseMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data, _source->GetCollisionHeight()); + ZLiquidStatus liquidStatus = _source->GetMap()->GetLiquidStatus(_source->GetPhaseMask(), x, y, z, MAP_ALL_LIQUIDS, &data, _source->GetCollisionHeight()); if (liquidStatus == LIQUID_MAP_NO_WATER) return NAV_GROUND; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 857b9def33c..3b0d337f52a 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5025,7 +5025,7 @@ void AuraEffect::HandlePreventResurrection(AuraApplication const* aurApp, uint8 if (apply) aurApp->GetTarget()->RemoveByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_RELEASE_TIMER); - else if (!aurApp->GetTarget()->GetBaseMap()->Instanceable()) + else if (!aurApp->GetTarget()->GetMap()->Instanceable()) aurApp->GetTarget()->SetByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_RELEASE_TIMER); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 2675a8ae62c..4eb9b163c3a 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1322,7 +1322,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici float ground = m_caster->GetMapHeight(x, y, z); float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; LiquidData liquidData; - if (m_caster->GetMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquidData, m_caster->GetCollisionHeight())) + if (m_caster->GetMap()->GetLiquidStatus(m_caster->GetPhaseMask(), x, y, z, MAP_ALL_LIQUIDS, &liquidData, m_caster->GetCollisionHeight())) liquidLevel = liquidData.level; if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index e3925b284f6..855389ae868 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -716,7 +716,7 @@ public: uint32 respawnZoneId = 0; if (SpawnData const* edata = data->ToSpawnData()) { - respawnZoneId = map->GetZoneId(edata->spawnPoint); + respawnZoneId = map->GetZoneId(edata->phaseMask, edata->spawnPoint); if (range) { if (!player->IsInDist(edata->spawnPoint, range)) diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index f7fb8525475..2afbd4f367a 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -292,7 +292,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, object->GetCollisionHeight()); + ZLiquidStatus status = map->GetLiquidStatus(object->GetPhaseMask(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus, object->GetCollisionHeight()); 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 0b4479513a5..2800c186f28 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -194,7 +194,7 @@ public: CharacterDatabaseTransaction 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(PHASEMASK_NORMAL, tele->mapId, tele->position_x, tele->position_y, tele->position_z), target_guid, dummy); } return true; diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 3f0a4dfce5c..c83cd236629 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -211,7 +211,7 @@ class spell_spawn_blood_pool : public SpellScript Unit* caster = GetCaster(); Position summonPos = caster->GetPosition(); LiquidData liquidStatus; - if (caster->GetMap()->GetLiquidStatus(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus, caster->GetCollisionHeight())) + if (caster->GetMap()->GetLiquidStatus(caster->GetPhaseMask(), caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus, caster->GetCollisionHeight())) summonPos.m_positionZ = liquidStatus.level; dest.Relocate(summonPos); } diff --git a/src/server/shared/DataStores/DBCStructure.h b/src/server/shared/DataStores/DBCStructure.h index e2d828f37a7..5a5039b8312 100644 --- a/src/server/shared/DataStores/DBCStructure.h +++ b/src/server/shared/DataStores/DBCStructure.h @@ -579,24 +579,24 @@ struct CurrencyTypesEntry struct DestructibleModelDataEntry { uint32 Id; - //uint32 DamagedUnk1; - //uint32 DamagedUnk2; - uint32 DamagedDisplayId; - //uint32 DamagedUnk3; - //uint32 DestroyedUnk1; - //uint32 DestroyedUnk2; - uint32 DestroyedDisplayId; - //uint32 DestroyedUnk3; - //uint32 RebuildingUnk1; - //uint32 RebuildingUnk2; - uint32 RebuildingDisplayId; - //uint32 RebuildingUnk3; - //uint32 SmokeUnk1; - //uint32 SmokeUnk2; - uint32 SmokeDisplayId; - //uint32 SmokeUnk3; - //uint32 Unk4; - //uint32 Unk5; + //uint32 State0ImpactEffectDoodadSet; + //uint32 State0AmbientDoodadSet; + uint32 State1Wmo; + //uint32 State1DestructionDoodadSet; + //uint32 State1ImpactEffectDoodadSet; + //uint32 State1AmbientDoodadSet; + uint32 State2Wmo; + //uint32 State2DestructionDoodadSet; + //uint32 State2ImpactEffectDoodadSet; + //uint32 State2AmbientDoodadSet; + uint32 State3Wmo; + //uint32 State3InitDoodadSet; + //uint32 State3AmbientDoodadSet; + //uint32 EjectDirection; + uint32 State0Wmo; + //uint32 DoNotHighlight; + //uint32 HealEffect; + //uint32 HealEffectSpeed; }; struct DungeonEncounterEntry |