diff --git a/Source/Game/Chat/Commands/MiscCommands.cs b/Source/Game/Chat/Commands/MiscCommands.cs index de5829183..0c4ffbcf0 100644 --- a/Source/Game/Chat/Commands/MiscCommands.cs +++ b/Source/Game/Chat/Commands/MiscCommands.cs @@ -632,7 +632,7 @@ namespace Game.Chat zoneX, zoneY, groundZ, floorZ, map.GetMinHeight(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY()), haveMap, haveVMap, haveMMap); LiquidData liquidStatus; - ZLiquidStatus status = map.GetLiquidStatus(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), LiquidHeaderTypeFlags.AllLiquids, out liquidStatus); + ZLiquidStatus status = map.GetLiquidStatus(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), out liquidStatus); if (liquidStatus != null) handler.SendSysMessage(CypherStrings.LiquidStatus, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, liquidStatus.type_flags, status); diff --git a/Source/Game/Collision/Callbacks.cs b/Source/Game/Collision/Callbacks.cs index ac17462e7..1ebb6c318 100644 --- a/Source/Game/Collision/Callbacks.cs +++ b/Source/Game/Collision/Callbacks.cs @@ -174,24 +174,6 @@ namespace Game.Collision ModelIgnoreFlags flags; } - public class AreaInfoCallback : WorkerCallback - { - public AreaInfoCallback(ModelInstance[] val) - { - prims = val; - } - public override void Invoke(Vector3 point, uint entry) - { - if (prims[entry] == null) - return; - - prims[entry].IntersectPoint(point, aInfo); - } - - ModelInstance[] prims; - public AreaInfo aInfo = new(); - } - public class LocationInfoCallback : WorkerCallback { public LocationInfoCallback(ModelInstance[] val, LocationInfo info) @@ -232,25 +214,6 @@ namespace Game.Collision PhaseShift _phaseShift; } - public class DynamicTreeAreaInfoCallback : WorkerCallback - { - public DynamicTreeAreaInfoCallback(PhaseShift phaseShift) - { - _phaseShift = phaseShift; - _areaInfo = new AreaInfo(); - } - - public override void Invoke(Vector3 p, GameObjectModel obj) - { - obj.IntersectPoint(p, _areaInfo, _phaseShift); - } - - public AreaInfo GetAreaInfo() { return _areaInfo; } - - PhaseShift _phaseShift; - AreaInfo _areaInfo; - } - public class DynamicTreeLocationInfoCallback : WorkerCallback { public DynamicTreeLocationInfoCallback(PhaseShift phaseShift) diff --git a/Source/Game/Collision/DynamicTree.cs b/Source/Game/Collision/DynamicTree.cs index a43a8255b..7fe4b4e94 100644 --- a/Source/Game/Collision/DynamicTree.cs +++ b/Source/Game/Collision/DynamicTree.cs @@ -113,31 +113,9 @@ namespace Game.Collision return float.NegativeInfinity; } - public bool GetAreaInfo(float x, float y, ref float z, PhaseShift phaseShift, out uint flags, out int adtId, out int rootId, out int groupId) + public bool GetAreaAndLiquidData(float x, float y, float z, PhaseShift phaseShift, byte? reqLiquidType, out AreaAndLiquidData data) { - flags = 0; - adtId = 0; - rootId = 0; - groupId = 0; - - Vector3 v = new(x, y, z + 0.5f); - DynamicTreeAreaInfoCallback intersectionCallBack = new(phaseShift); - 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; - } - - public AreaAndLiquidData GetAreaAndLiquidData(float x, float y, float z, PhaseShift phaseShift, byte reqLiquidType) - { - AreaAndLiquidData data = new(); + data = new(); Vector3 v = new(x, y, z + 0.5f); DynamicTreeLocationInfoCallback intersectionCallBack = new(phaseShift); @@ -147,17 +125,17 @@ namespace Game.Collision data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z; uint liquidType = intersectionCallBack.GetLocationInfo().hitModel.GetLiquidType(); float liquidLevel = 0; - if (reqLiquidType == 0 || (Global.DB2Mgr.GetLiquidFlags(liquidType) & reqLiquidType) != 0) + if (!reqLiquidType.HasValue || (Global.DB2Mgr.GetLiquidFlags(liquidType) & reqLiquidType.Value) != 0) if (intersectionCallBack.GetHitModel().GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), ref liquidLevel)) data.liquidInfo = new AreaAndLiquidData.LiquidInfo(liquidType, liquidLevel); - data.areaInfo = new(intersectionCallBack.GetHitModel().GetNameSetId(), intersectionCallBack.GetLocationInfo().rootId, - (int)intersectionCallBack.GetLocationInfo().hitModel.GetWmoID(), intersectionCallBack.GetLocationInfo().hitModel.GetMogpFlags()); + data.areaInfo = new((int)intersectionCallBack.GetLocationInfo().hitModel.GetWmoID(), intersectionCallBack.GetHitModel().GetNameSetId(), intersectionCallBack.GetLocationInfo().rootId, intersectionCallBack.GetLocationInfo().hitModel.GetMogpFlags(), 0); + return true; } - return data; + return false; } - + DynTreeImpl impl; } diff --git a/Source/Game/Collision/Management/VMapManager.cs b/Source/Game/Collision/Management/VMapManager.cs index 72fd1f72a..18f7a462a 100644 --- a/Source/Game/Collision/Management/VMapManager.cs +++ b/Source/Game/Collision/Management/VMapManager.cs @@ -147,66 +147,12 @@ namespace Game.Collision return MapConst.VMAPInvalidHeightValue; } - public bool GetAreaInfo(uint mapId, float x, float y, ref float z, out uint flags, out int adtId, out int rootId, out int groupId) + + + public bool GetAreaAndLiquidData(uint mapId, float x, float y, float z, byte? reqLiquidType, out AreaAndLiquidData data) { - flags = 0; - adtId = 0; - rootId = 0; - groupId = 0; - if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapAreaFlag)) - { - var instanceTree = iInstanceMapTrees.LookupByKey(mapId); - if (instanceTree != null) - { - Vector3 pos = ConvertPositionToInternalRep(x, y, z); - bool result = instanceTree.GetAreaInfo(ref pos, out flags, out adtId, out rootId, out groupId); - // z is not touched by convertPositionToInternalRep(), so just copy - z = pos.Z; - return result; - } - } + data = new AreaAndLiquidData(); - return false; - } - - public bool GetLiquidLevel(uint mapId, float x, float y, float z, uint reqLiquidType, ref float level, ref float floor, ref uint type, ref uint mogpFlags) - { - if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLiquidStatus)) - { - var instanceTree = iInstanceMapTrees.LookupByKey(mapId); - if (instanceTree != null) - { - LocationInfo info = new(); - Vector3 pos = ConvertPositionToInternalRep(x, y, z); - if (instanceTree.GetLocationInfo(pos, info)) - { - floor = info.ground_Z; - Cypher.Assert(floor < float.MaxValue); - type = info.hitModel.GetLiquidType(); // entry from LiquidType.dbc - mogpFlags = info.hitModel.GetMogpFlags(); - if (reqLiquidType != 0 && !Convert.ToBoolean(Global.DB2Mgr.GetLiquidFlags(type) & reqLiquidType)) - return false; - if (info.hitInstance.GetLiquidLevel(pos, info, ref level)) - return true; - } - } - } - return false; - } - - public AreaAndLiquidData GetAreaAndLiquidData(uint mapId, float x, float y, float z, uint reqLiquidType) - { - var data = new AreaAndLiquidData(); - - if (Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLiquidStatus)) - { - data.floorZ = z; - int adtId, rootId, groupId; - uint flags; - if (GetAreaInfo(mapId, x, y, ref data.floorZ, out flags, out adtId, out rootId, out groupId)) - data.areaInfo = new(adtId, rootId, groupId, flags); - return data; - } var instanceTree = iInstanceMapTrees.LookupByKey(mapId); if (instanceTree != null) { @@ -215,18 +161,24 @@ namespace Game.Collision if (instanceTree.GetLocationInfo(pos, info)) { data.floorZ = info.ground_Z; - uint liquidType = info.hitModel.GetLiquidType(); - float liquidLevel = 0; - if (reqLiquidType == 0 || Convert.ToBoolean(Global.DB2Mgr.GetLiquidFlags(liquidType) & reqLiquidType)) - if (info.hitInstance.GetLiquidLevel(pos, info, ref liquidLevel)) - data.liquidInfo = new(liquidType, liquidLevel); if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLiquidStatus)) - data.areaInfo = new(info.hitInstance.adtId, info.rootId, (int)info.hitModel.GetWmoID(), info.hitModel.GetMogpFlags()); + { + uint liquidType = info.hitModel.GetLiquidType(); // entry from LiquidType.dbc + float liquidLevel = 0; + if (!reqLiquidType.HasValue || (Global.DB2Mgr.GetLiquidFlags(liquidType) & reqLiquidType.Value) != 0) + if (info.hitInstance.GetLiquidLevel(pos, info, ref liquidLevel)) + data.liquidInfo = new(liquidType, liquidLevel); + } + + if (!Global.DisableMgr.IsVMAPDisabledFor(mapId, DisableFlags.VmapLiquidStatus)) + data.areaInfo = new((int)info.hitModel.GetWmoID(), info.hitInstance.adtId, info.rootId, info.hitModel.GetMogpFlags(), info.hitInstance.Id); + + return true; } } - return data; + return false; } public WorldModel AcquireModelInstance(string filename) @@ -336,22 +288,25 @@ namespace Game.Collision public class AreaAndLiquidData { - public struct AreaInfo + public class AreaInfo { + public int GroupId; public int AdtId; public int RootId; - public int GroupId; public uint MogpFlags; + public uint UniqueId; - public AreaInfo(int adtId, int rootId, int groupId, uint flags) + public AreaInfo(int groupId, int adtId, int rootId, uint mogpFlags, uint uniqueId) { + GroupId = groupId; AdtId = adtId; RootId = rootId; - GroupId = groupId; - MogpFlags = flags; + MogpFlags = mogpFlags; + UniqueId = uniqueId; } } - public struct LiquidInfo + + public class LiquidInfo { public uint LiquidType; public float Level; @@ -364,7 +319,7 @@ namespace Game.Collision } public float floorZ = MapConst.VMAPInvalidHeightValue; - public AreaInfo? areaInfo; - public LiquidInfo? liquidInfo; + public AreaInfo areaInfo; + public LiquidInfo liquidInfo; } } diff --git a/Source/Game/Collision/Maps/MapTree.cs b/Source/Game/Collision/Maps/MapTree.cs index 1d7040cf7..82b97af4c 100644 --- a/Source/Game/Collision/Maps/MapTree.cs +++ b/Source/Game/Collision/Maps/MapTree.cs @@ -287,27 +287,6 @@ namespace Game.Collision return $"{mapID:D4}_{tileY:D2}_{tileX:D2}.vmtile"; } - public bool GetAreaInfo(ref Vector3 pos, out uint flags, out int adtId, out int rootId, out int groupId) - { - flags = 0; - adtId = 0; - rootId = 0; - groupId = 0; - - AreaInfoCallback intersectionCallBack = new(iTreeValues); - iTree.IntersectPoint(pos, intersectionCallBack); - if (intersectionCallBack.aInfo.result) - { - flags = intersectionCallBack.aInfo.flags; - adtId = intersectionCallBack.aInfo.adtId; - rootId = intersectionCallBack.aInfo.rootId; - groupId = intersectionCallBack.aInfo.groupId; - pos.Z = intersectionCallBack.aInfo.ground_Z; - return true; - } - return false; - } - public bool GetLocationInfo(Vector3 pos, LocationInfo info) { LocationInfoCallback intersectionCallBack = new(iTreeValues, info); diff --git a/Source/Game/Collision/Models/GameObjectModel.cs b/Source/Game/Collision/Models/GameObjectModel.cs index ae3121ed2..7eb349555 100644 --- a/Source/Game/Collision/Models/GameObjectModel.cs +++ b/Source/Game/Collision/Models/GameObjectModel.cs @@ -104,33 +104,6 @@ namespace Game.Collision return hit; } - public override void IntersectPoint(Vector3 point, AreaInfo info, PhaseShift phaseShift) - { - if (!IsCollisionEnabled() || !owner.IsSpawned() || !IsMapObject()) - return; - - if (!owner.IsInPhase(phaseShift)) - return; - - if (!iBound.contains(point)) - return; - - // child bounds are defined in object space: - Vector3 pModel = iInvRot.Multiply(point - iPos) * iInvScale; - Vector3 zDirModel = iInvRot.Multiply(new Vector3(0.0f, 0.0f, -1.0f)); - float zDist; - if (iModel.IntersectPoint(pModel, zDirModel, out zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - float world_Z = (iInvRot.Multiply(modelGround) * iScale + iPos).Z; - if (info.ground_Z < world_Z) - { - info.ground_Z = world_Z; - info.adtId = owner.GetNameSetId(); - } - } - } - public bool GetLocationInfo(Vector3 point, LocationInfo info, PhaseShift phaseShift) { if (!IsCollisionEnabled() || !owner.IsSpawned() || !IsMapObject()) diff --git a/Source/Game/Collision/Models/ModelInstance.cs b/Source/Game/Collision/Models/ModelInstance.cs index 133f093b8..0cb90adb6 100644 --- a/Source/Game/Collision/Models/ModelInstance.cs +++ b/Source/Game/Collision/Models/ModelInstance.cs @@ -120,37 +120,6 @@ namespace Game.Collision return hit; } - public void IntersectPoint(Vector3 p, AreaInfo info) - { - if (iModel == null) - return; - - // M2 files don't contain area info, only WMO files - if (iModel.IsM2()) - return; - - if (!iBound.contains(p)) - return; - - // child bounds are defined in object space: - Vector3 pModel = iInvRot.Multiply(p - iPos) * iInvScale; - Vector3 zDirModel = iInvRot.Multiply(new Vector3(0.0f, 0.0f, -1.0f)); - float zDist; - if (iModel.IntersectPoint(pModel, zDirModel, out zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - // Transform back to world space. Note that: - // Mat * vec == vec * Mat.transpose() - // and for rotation matrices: Mat.inverse() == Mat.transpose() - float world_Z = (iInvRot.Multiply(modelGround) * iScale + iPos).Z; - if (info.ground_Z < world_Z) - { - info.ground_Z = world_Z; - info.adtId = adtId; - } - } - } - public bool GetLiquidLevel(Vector3 p, LocationInfo info, ref float liqHeight) { // child bounds are defined in object space: diff --git a/Source/Game/Collision/Models/WorldModel.cs b/Source/Game/Collision/Models/WorldModel.cs index 90ba4c2eb..3ca2d9b89 100644 --- a/Source/Game/Collision/Models/WorldModel.cs +++ b/Source/Game/Collision/Models/WorldModel.cs @@ -301,7 +301,7 @@ namespace Game.Collision if ((ignoreFlags & ModelIgnoreFlags.M2) != ModelIgnoreFlags.Nothing) { // M2 models are not taken into account for LoS calculation if caller requested their ignoring. - if (Flags.HasFlag(ModelFlags.None)) + if (IsM2()) return false; } @@ -315,26 +315,6 @@ namespace Game.Collision return isc.hit; } - public bool IntersectPoint(Vector3 p, Vector3 down, out float dist, AreaInfo info) - { - dist = 0f; - if (groupModels.Empty()) - return false; - - WModelAreaCallback callback = new(groupModels, down); - groupTree.IntersectPoint(p, callback); - if (callback.hit != null) - { - info.rootId = (int)RootWMOID; - info.groupId = (int)callback.hit.GetWmoID(); - info.flags = callback.hit.GetMogpFlags(); - info.result = true; - dist = callback.zDist; - return true; - } - return false; - } - public bool GetLocationInfo(Vector3 p, Vector3 down, out float dist, GroupLocationInfo info) { dist = 0f; diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 1a8c8e5d7..4e2245080 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -829,9 +829,9 @@ namespace Game.Entities { // 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 positionData = new(); - GetMap().GetFullTerrainStatusForPosition(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), positionData, LiquidHeaderTypeFlags.AllLiquids, MapConst.DefaultCollesionHeight); - ProcessPositionDataChanged(positionData); + PositionFullTerrainStatus terrainStatus = new(); + GetMap().GetFullTerrainStatusForPosition(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), terrainStatus); + ProcessPositionDataChanged(terrainStatus); } // Allow players to see those units while dead, do it here (mayby altered by addon auras) diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 98aa90f01..9e6e6f9a9 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -104,7 +104,7 @@ namespace Game.Entities public void UpdatePositionData() { PositionFullTerrainStatus data = new(); - GetMap().GetFullTerrainStatusForPosition(_phaseShift, GetPositionX(), GetPositionY(), GetPositionZ(), data, LiquidHeaderTypeFlags.AllLiquids, GetCollisionHeight()); + GetMap().GetFullTerrainStatusForPosition(_phaseShift, GetPositionX(), GetPositionY(), GetPositionZ(), data, null, GetCollisionHeight()); ProcessPositionDataChanged(data); } diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index 5a9e7b9d8..e33de30f8 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -803,7 +803,7 @@ namespace Game.Entities mountFlags = (AreaMountFlags)areaTable.MountFlags; } - ZLiquidStatus liquidStatus = GetMap().GetLiquidStatus(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), LiquidHeaderTypeFlags.AllLiquids); + ZLiquidStatus liquidStatus = GetMap().GetLiquidStatus(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ()); isSubmerged = liquidStatus.HasAnyFlag(ZLiquidStatus.UnderWater) || HasUnitMovementFlag(MovementFlag.Swimming); isInWater = liquidStatus.HasAnyFlag(ZLiquidStatus.InWater | ZLiquidStatus.UnderWater); diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index 67f92239b..d8ac60c5f 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -1520,24 +1520,19 @@ namespace Game.Maps return (mogpFlags & 0x2000) != 0; } - public void GetFullTerrainStatusForPosition(PhaseShift phaseShift, float x, float y, float z, PositionFullTerrainStatus data, LiquidHeaderTypeFlags reqLiquidType, float collisionHeight = MapConst.DefaultCollesionHeight) + public void GetFullTerrainStatusForPosition(PhaseShift phaseShift, float x, float y, float z, PositionFullTerrainStatus data, LiquidHeaderTypeFlags? reqLiquidType = null, float collisionHeight = MapConst.DefaultCollesionHeight) { m_terrain.GetFullTerrainStatusForPosition(phaseShift, GetId(), x, y, z, data, reqLiquidType, collisionHeight, _dynamicTree); } - public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, float x, float y, float z, LiquidHeaderTypeFlags reqLiquidType, float collisionHeight = MapConst.DefaultCollesionHeight) + public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, float x, float y, float z, LiquidHeaderTypeFlags? reqLiquidType = null, float collisionHeight = MapConst.DefaultCollesionHeight) { - return m_terrain.GetLiquidStatus(phaseShift, GetId(), x, y, z, reqLiquidType, out _, collisionHeight); + return m_terrain.GetLiquidStatus(phaseShift, GetId(), x, y, z, out _, reqLiquidType, collisionHeight); } - public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, float x, float y, float z, LiquidHeaderTypeFlags reqLiquidType, out LiquidData data, float collisionHeight = MapConst.DefaultCollesionHeight) + public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, float x, float y, float z, out LiquidData data, LiquidHeaderTypeFlags? reqLiquidType = null, float collisionHeight = MapConst.DefaultCollesionHeight) { - return m_terrain.GetLiquidStatus(phaseShift, GetId(), x, y, z, reqLiquidType, out data, collisionHeight); - } - - private bool GetAreaInfo(PhaseShift phaseShift, float x, float y, float z, out uint mogpflags, out int adtId, out int rootId, out int groupId) - { - return m_terrain.GetAreaInfo(phaseShift, GetId(), x, y, z, out mogpflags, out adtId, out rootId, out groupId, _dynamicTree); + return m_terrain.GetLiquidStatus(phaseShift, GetId(), x, y, z, out data, reqLiquidType, collisionHeight); } public uint GetAreaId(PhaseShift phaseShift, Position pos) @@ -5013,9 +5008,9 @@ namespace Game.Maps raidInstanceMessage.DifficultyID = GetDifficultyID(); raidInstanceMessage.Write(); - foreach (Player player in GetPlayers()) + foreach (Player player in GetPlayers()) player.SendPacket(raidInstanceMessage); - + if (i_data != null) { PendingRaidLock pendingRaidLock = new(); @@ -5321,29 +5316,29 @@ namespace Game.Maps } } + public class WmoLocation + { + public int GroupId; + public int NameSetId; + public int RootId; + public uint UniqueId; + + public WmoLocation(int groupId, int nameSetId, int rootId, uint uniqueId) + { + GroupId = groupId; + NameSetId = nameSetId; + RootId = rootId; + UniqueId = uniqueId; + } + } + public class PositionFullTerrainStatus { - public struct AreaInfo - { - public int AdtId; - public int RootId; - public int GroupId; - public uint MogpFlags; - - public AreaInfo(int adtId, int rootId, int groupId, uint flags) - { - AdtId = adtId; - RootId = rootId; - GroupId = groupId; - MogpFlags = flags; - } - } - public uint AreaId; public float FloorZ; public bool outdoors = true; public ZLiquidStatus LiquidStatus; - public AreaInfo? areaInfo; + public WmoLocation? wmoLocation; public LiquidData LiquidInfo; } diff --git a/Source/Game/Maps/TerrainManager.cs b/Source/Game/Maps/TerrainManager.cs index a6b51be81..e137d88f7 100644 --- a/Source/Game/Maps/TerrainManager.cs +++ b/Source/Game/Maps/TerrainManager.cs @@ -266,7 +266,7 @@ namespace Game.Maps if (++_referenceCountFromMap[gx][gy] != 1) // check if already loaded return; - lock(_loadLock) + lock (_loadLock) LoadMapAndVMapImpl(gx, gy); } @@ -393,7 +393,7 @@ namespace Game.Maps // ensure GridMap is loaded if (!_loadedGrids[GetBitsetIndex(gx, gy)] && loadIfMissing) { - lock(_loadLock) + lock (_loadLock) LoadMapAndVMapImpl(gx, gy); } @@ -428,16 +428,17 @@ namespace Game.Maps return (mogpFlags & 0x2000) != 0; } - public void GetFullTerrainStatusForPosition(PhaseShift phaseShift, uint mapId, float x, float y, float z, PositionFullTerrainStatus data, LiquidHeaderTypeFlags reqLiquidType = LiquidHeaderTypeFlags.AllLiquids, float collisionHeight = MapConst.DefaultCollesionHeight, DynamicMapTree dynamicMapTree = null) + public void GetFullTerrainStatusForPosition(PhaseShift phaseShift, uint mapId, float x, float y, float z, PositionFullTerrainStatus data, LiquidHeaderTypeFlags? reqLiquidType = null, float collisionHeight = MapConst.DefaultCollesionHeight, DynamicMapTree dynamicMapTree = null) { AreaAndLiquidData dynData = null; AreaAndLiquidData wmoData = null; uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, mapId, this, x, y); GridMap gmap = GetGrid(terrainMapId, x, y); - AreaAndLiquidData vmapData = Global.VMapMgr.GetAreaAndLiquidData(terrainMapId, x, y, z, (byte)reqLiquidType); + AreaAndLiquidData vmapData; + Global.VMapMgr.GetAreaAndLiquidData(terrainMapId, x, y, z, reqLiquidType.HasValue ? (byte)reqLiquidType : null, out vmapData); if (dynamicMapTree != null) - dynData = dynamicMapTree.GetAreaAndLiquidData(x, y, z, phaseShift, (byte)reqLiquidType); + dynamicMapTree.GetAreaAndLiquidData(x, y, z, phaseShift, reqLiquidType.HasValue ? (byte)reqLiquidType : null, out dynData); uint gridAreaId = 0; float gridMapHeight = MapConst.InvalidHeight; @@ -475,15 +476,15 @@ namespace Game.Maps if (wmoData != null) { - if (wmoData.areaInfo.HasValue) + if (wmoData.areaInfo != null) { - data.areaInfo = new(wmoData.areaInfo.Value.AdtId, wmoData.areaInfo.Value.RootId, wmoData.areaInfo.Value.GroupId, wmoData.areaInfo.Value.MogpFlags); + data.wmoLocation = new(wmoData.areaInfo.AdtId, wmoData.areaInfo.RootId, wmoData.areaInfo.GroupId, wmoData.areaInfo.MogpFlags); // wmo found - var wmoEntry = Global.DB2Mgr.GetWMOAreaTable(wmoData.areaInfo.Value.RootId, wmoData.areaInfo.Value.AdtId, wmoData.areaInfo.Value.GroupId); + var wmoEntry = Global.DB2Mgr.GetWMOAreaTable(wmoData.areaInfo.RootId, wmoData.areaInfo.AdtId, wmoData.areaInfo.GroupId); if (wmoEntry == null) - wmoEntry = Global.DB2Mgr.GetWMOAreaTable(wmoData.areaInfo.Value.RootId, wmoData.areaInfo.Value.AdtId, -1); + wmoEntry = Global.DB2Mgr.GetWMOAreaTable(wmoData.areaInfo.RootId, wmoData.areaInfo.AdtId, -1); - data.outdoors = (wmoData.areaInfo.Value.MogpFlags & 0x8) != 0; + data.outdoors = (wmoData.areaInfo.MogpFlags & 0x8) != 0; if (wmoEntry != null) { data.AreaId = wmoEntry.AreaTableID; @@ -496,7 +497,7 @@ namespace Game.Maps if (data.AreaId == 0) data.AreaId = gridAreaId; - useGridLiquid = !IsInWMOInterior(wmoData.areaInfo.Value.MogpFlags); + useGridLiquid = !IsInWMOInterior(wmoData.areaInfo.MogpFlags); } } else @@ -515,9 +516,9 @@ namespace Game.Maps // liquid processing data.LiquidStatus = ZLiquidStatus.NoWater; - if (wmoData != null && wmoData.liquidInfo.HasValue && wmoData.liquidInfo.Value.Level > wmoData.floorZ) + if (wmoData != null && wmoData.liquidInfo != null && wmoData.liquidInfo.Level > wmoData.floorZ) { - uint liquidType = wmoData.liquidInfo.Value.LiquidType; + uint liquidType = wmoData.liquidInfo.LiquidType; if (GetId() == 530 && liquidType == 2) // gotta love hacks liquidType = 15; @@ -545,12 +546,12 @@ namespace Game.Maps } data.LiquidInfo = new(); - data.LiquidInfo.level = wmoData.liquidInfo.Value.Level; + data.LiquidInfo.level = wmoData.liquidInfo.Level; data.LiquidInfo.depth_level = wmoData.floorZ; data.LiquidInfo.entry = liquidType; data.LiquidInfo.type_flags = (LiquidHeaderTypeFlags)(1 << (int)liquidFlagType); - float delta = wmoData.liquidInfo.Value.Level - z; + float delta = wmoData.liquidInfo.Level - z; ZLiquidStatus status = ZLiquidStatus.AboveWater; if (delta > collisionHeight) status = ZLiquidStatus.UnderWater; @@ -580,38 +581,35 @@ namespace Game.Maps } } - public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, uint mapId, float x, float y, float z, LiquidHeaderTypeFlags ReqLiquidType, out LiquidData data, float collisionHeight = MapConst.DefaultCollesionHeight) + public ZLiquidStatus GetLiquidStatus(PhaseShift phaseShift, uint mapId, float x, float y, float z, out LiquidData data, LiquidHeaderTypeFlags? ReqLiquidType = null, float collisionHeight = MapConst.DefaultCollesionHeight) { data = null; ZLiquidStatus result = ZLiquidStatus.NoWater; - float liquid_level = MapConst.InvalidHeight; - float ground_level = MapConst.InvalidHeight; - uint liquid_type = 0; - uint mogpFlags = 0; + AreaAndLiquidData vmapData; bool useGridLiquid = true; uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, mapId, this, x, y); - if (Global.VMapMgr.GetLiquidLevel(terrainMapId, x, y, z, (byte)ReqLiquidType, ref liquid_level, ref ground_level, ref liquid_type, ref mogpFlags)) + if (Global.VMapMgr.GetAreaAndLiquidData(terrainMapId, x, y, z, ReqLiquidType.HasValue ? (byte)ReqLiquidType : null, out vmapData) && vmapData.liquidInfo != null) { - useGridLiquid = !IsInWMOInterior(mogpFlags); - Log.outDebug(LogFilter.Maps, $"GetLiquidStatus(): vmap liquid level: {liquid_level} ground: {ground_level} type: {liquid_type}"); + useGridLiquid = vmapData.areaInfo == null || !IsInWMOInterior(vmapData.areaInfo.MogpFlags); + Log.outDebug(LogFilter.Maps, $"GetLiquidStatus(): vmap liquid level: {vmapData.liquidInfo.Level} ground: {vmapData.floorZ} type: {vmapData.liquidInfo.LiquidType}"); // Check water level and ground level - if (liquid_level > ground_level && MathFunctions.fuzzyGe(z, ground_level - MapConst.GroundHeightTolerance)) + if (vmapData.liquidInfo.Level > vmapData.floorZ && MathFunctions.fuzzyGe(z, vmapData.floorZ - MapConst.GroundHeightTolerance)) { // All ok in water . store data data = new(); // hardcoded in client like this - if (GetId() == 530 && liquid_type == 2) - liquid_type = 15; + if (GetId() == 530 && vmapData.liquidInfo.LiquidType == 2) + vmapData.liquidInfo.LiquidType = 15; uint liquidFlagType = 0; - var liq = CliDB.LiquidTypeStorage.LookupByKey(liquid_type); + var liq = CliDB.LiquidTypeStorage.LookupByKey(vmapData.liquidInfo.LiquidType); if (liq != null) liquidFlagType = liq.SoundBank; - if (liquid_type != 0 && liquid_type < 21) + if (vmapData.liquidInfo.LiquidType != 0 && vmapData.liquidInfo.LiquidType < 21) { var area = CliDB.AreaTableStorage.LookupByKey(GetAreaId(phaseShift, mapId, x, y, z)); if (area != null) @@ -627,19 +625,19 @@ namespace Game.Maps var liq1 = CliDB.LiquidTypeStorage.LookupByKey(overrideLiquid); if (liq1 != null) { - liquid_type = overrideLiquid; + vmapData.liquidInfo.LiquidType = overrideLiquid; liquidFlagType = liq1.SoundBank; } } } - data.level = liquid_level; - data.depth_level = ground_level; + data.level = vmapData.liquidInfo.Level; + data.depth_level = vmapData.floorZ; - data.entry = liquid_type; + data.entry = vmapData.liquidInfo.LiquidType; data.type_flags = (LiquidHeaderTypeFlags)(1 << (int)liquidFlagType); - float delta = liquid_level - z; + float delta = vmapData.liquidInfo.Level - z; ZLiquidStatus status = ZLiquidStatus.AboveWater; // Above water @@ -652,7 +650,7 @@ namespace Game.Maps if (status != ZLiquidStatus.AboveWater) { - if (MathF.Abs(ground_level - z) <= MapConst.GroundHeightTolerance) + if (MathF.Abs(vmapData.floorZ - z) <= MapConst.GroundHeightTolerance) status |= ZLiquidStatus.OceanFloor; return status; @@ -670,7 +668,7 @@ namespace Game.Maps LiquidData map_data = new(); ZLiquidStatus map_result = gmap.GetLiquidStatus(x, y, z, ReqLiquidType, map_data, collisionHeight); // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER: - if (map_result != ZLiquidStatus.NoWater && (map_data.level > ground_level)) + if (map_result != ZLiquidStatus.NoWater && (map_data.level > vmapData.floorZ)) { // hardcoded in client like this if (GetId() == 530 && map_data.entry == 2) @@ -692,49 +690,41 @@ namespace Game.Maps rootId = 0; groupId = 0; - float vmap_z = z; - float dynamic_z = z; float check_z = z; uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, mapId, this, x, y); - uint vflags; - int vadtId; - int vrootId; - int vgroupId; - uint dflags = 0; - int dadtId = 0; - int drootId = 0; - int dgroupId = 0; + AreaAndLiquidData vdata; + AreaAndLiquidData ddata = null; - bool hasVmapAreaInfo = Global.VMapMgr.GetAreaInfo(terrainMapId, x, y, ref vmap_z, out vflags, out vadtId, out vrootId, out vgroupId); - bool hasDynamicAreaInfo = dynamicMapTree != null ? dynamicMapTree.GetAreaInfo(x, y, ref dynamic_z, phaseShift, out dflags, out dadtId, out drootId, out dgroupId) : false; + bool hasVmapAreaInfo = Global.VMapMgr.GetAreaAndLiquidData(terrainMapId, x, y, z, null, out vdata) && vdata.areaInfo != null; + bool hasDynamicAreaInfo = dynamicMapTree != null ? dynamicMapTree.GetAreaAndLiquidData(x, y, z, phaseShift, null, out ddata) && ddata.areaInfo != null : false; if (hasVmapAreaInfo) { - if (hasDynamicAreaInfo && dynamic_z > vmap_z) + if (hasDynamicAreaInfo && ddata.floorZ > vdata.floorZ) { - check_z = dynamic_z; - mogpflags = dflags; - adtId = dadtId; - rootId = drootId; - groupId = dgroupId; + check_z = ddata.floorZ; + groupId = ddata.areaInfo.GroupId; + adtId = ddata.areaInfo.AdtId; + rootId = ddata.areaInfo.RootId; + mogpflags = ddata.areaInfo.MogpFlags; } else { - check_z = vmap_z; - mogpflags = vflags; - adtId = vadtId; - rootId = vrootId; - groupId = vgroupId; + check_z = vdata.floorZ; + groupId = vdata.areaInfo.GroupId; + adtId = vdata.areaInfo.AdtId; + rootId = vdata.areaInfo.RootId; + mogpflags = vdata.areaInfo.MogpFlags; } } else if (hasDynamicAreaInfo) { - check_z = dynamic_z; - mogpflags = dflags; - adtId = dadtId; - rootId = drootId; - groupId = dgroupId; + check_z = ddata.floorZ; + groupId = ddata.areaInfo.GroupId; + adtId = ddata.areaInfo.AdtId; + rootId = ddata.areaInfo.RootId; + mogpflags = ddata.areaInfo.MogpFlags; } if (hasVmapAreaInfo || hasDynamicAreaInfo) @@ -754,7 +744,7 @@ namespace Game.Maps } public uint GetAreaId(PhaseShift phaseShift, uint mapId, Position pos, DynamicMapTree dynamicMapTree = null) { return GetAreaId(phaseShift, mapId, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), dynamicMapTree); } - + public uint GetAreaId(PhaseShift phaseShift, uint mapId, float x, float y, float z, DynamicMapTree dynamicMapTree = null) { uint mogpFlags; @@ -794,7 +784,7 @@ namespace Game.Maps } public uint GetZoneId(PhaseShift phaseShift, uint mapId, Position pos, DynamicMapTree dynamicMapTree = null) { return GetZoneId(phaseShift, mapId, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), dynamicMapTree); } - + public uint GetZoneId(PhaseShift phaseShift, uint mapId, float x, float y, float z, DynamicMapTree dynamicMapTree = null) { uint areaId = GetAreaId(phaseShift, mapId, x, y, z, dynamicMapTree); @@ -807,7 +797,7 @@ namespace Game.Maps } public void GetZoneAndAreaId(PhaseShift phaseShift, uint mapId, out uint zoneid, out uint areaid, Position pos, DynamicMapTree dynamicMapTree = null) { GetZoneAndAreaId(phaseShift, mapId, out zoneid, out areaid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), dynamicMapTree); } - + public void GetZoneAndAreaId(PhaseShift phaseShift, uint mapId, out uint zoneid, out uint areaid, float x, float y, float z, DynamicMapTree dynamicMapTree = null) { areaid = zoneid = GetAreaId(phaseShift, mapId, x, y, z, dynamicMapTree); @@ -881,18 +871,18 @@ namespace Game.Maps GridMap gmap = GetGrid(PhasingHandler.GetTerrainMapId(phaseShift, mapId, this, x, y), x, y); if (gmap != null) return gmap.GetLiquidLevel(x, y); - + return 0; } public bool IsInWater(PhaseShift phaseShift, uint mapId, float x, float y, float pZ, out LiquidData data) { - return (GetLiquidStatus(phaseShift, mapId, x, y, pZ, LiquidHeaderTypeFlags.AllLiquids, out data) & (ZLiquidStatus.InWater | ZLiquidStatus.UnderWater)) != 0; + return (GetLiquidStatus(phaseShift, mapId, x, y, pZ, out data, null) & (ZLiquidStatus.InWater | ZLiquidStatus.UnderWater)) != 0; } public bool IsUnderWater(PhaseShift phaseShift, uint mapId, float x, float y, float z) { - return (GetLiquidStatus(phaseShift, mapId, x, y, z, LiquidHeaderTypeFlags.Water | LiquidHeaderTypeFlags.Ocean, out _) & ZLiquidStatus.UnderWater) != 0; + return (GetLiquidStatus(phaseShift, mapId, x, y, z, out _, LiquidHeaderTypeFlags.Water | LiquidHeaderTypeFlags.Ocean) & ZLiquidStatus.UnderWater) != 0; } public float GetWaterOrGroundLevel(PhaseShift phaseShift, uint mapId, float x, float y, float z, ref float ground, bool swim = false, float collisionHeight = MapConst.DefaultCollesionHeight, DynamicMapTree dynamicMapTree = null) @@ -907,7 +897,7 @@ namespace Game.Maps ground = ground_z; LiquidData liquid_status; - ZLiquidStatus res = GetLiquidStatus(phaseShift, mapId, x, y, ground_z, LiquidHeaderTypeFlags.AllLiquids, out liquid_status, collisionHeight); + ZLiquidStatus res = GetLiquidStatus(phaseShift, mapId, x, y, ground_z, out liquid_status, null, collisionHeight); switch (res) { case ZLiquidStatus.AboveWater: diff --git a/Source/Game/Movement/Generators/PathGenerator.cs b/Source/Game/Movement/Generators/PathGenerator.cs index 88f36f959..7cf6b0d3a 100644 --- a/Source/Game/Movement/Generators/PathGenerator.cs +++ b/Source/Game/Movement/Generators/PathGenerator.cs @@ -161,7 +161,7 @@ namespace Game.Movement // Check both start and end points, if they're both in water, then we can *safely* let the creature move for (uint i = 0; i < _pathPoints.Length; ++i) { - ZLiquidStatus status = _source.GetMap().GetLiquidStatus(_source.GetPhaseShift(), _pathPoints[i].X, _pathPoints[i].Y, _pathPoints[i].Z, LiquidHeaderTypeFlags.AllLiquids, _source.GetCollisionHeight()); + ZLiquidStatus status = _source.GetMap().GetLiquidStatus(_source.GetPhaseShift(), _pathPoints[i].X, _pathPoints[i].Y, _pathPoints[i].Z, null, _source.GetCollisionHeight()); // One of the points is not in the water, cancel movement. if (status == ZLiquidStatus.NoWater) { @@ -893,7 +893,7 @@ namespace Game.Movement NavTerrainFlag GetNavTerrain(float x, float y, float z) { - ZLiquidStatus liquidStatus = _source.GetMap().GetLiquidStatus(_source.GetPhaseShift(), x, y, z, LiquidHeaderTypeFlags.AllLiquids, out LiquidData data, _source.GetCollisionHeight()); + ZLiquidStatus liquidStatus = _source.GetMap().GetLiquidStatus(_source.GetPhaseShift(), x, y, z, out LiquidData data, null, _source.GetCollisionHeight()); if (liquidStatus == ZLiquidStatus.NoWater) return NavTerrainFlag.Ground; diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index e8a0281bf..bbf3fb7f1 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -311,7 +311,7 @@ namespace Game.Spells { if (m_spellInfo.HasAttribute(SpellAttr8.RequiresLocationToBeOnLiquidSurface)) { - ZLiquidStatus status = m_caster.GetMap().GetLiquidStatus(m_caster.GetPhaseShift(), m_targets.GetDstPos().GetPositionX(), m_targets.GetDstPos().GetPositionY(), m_targets.GetDstPos().GetPositionZ(), LiquidHeaderTypeFlags.AllLiquids); + ZLiquidStatus status = m_caster.GetMap().GetLiquidStatus(m_caster.GetPhaseShift(), m_targets.GetDstPos().GetPositionX(), m_targets.GetDstPos().GetPositionY(), m_targets.GetDstPos().GetPositionZ()); if (!status.HasAnyFlag(ZLiquidStatus.WaterWalk | ZLiquidStatus.InWater)) { SendCastResult(SpellCastResult.NoLiquid); @@ -1004,7 +1004,7 @@ namespace Game.Spells float ground = m_caster.GetMapHeight(x, y, z); float liquidLevel = MapConst.VMAPInvalidHeightValue; LiquidData liquidData; - if (m_caster.GetMap().GetLiquidStatus(m_caster.GetPhaseShift(), x, y, z, LiquidHeaderTypeFlags.AllLiquids, out liquidData, m_caster.GetCollisionHeight()) != 0) + if (m_caster.GetMap().GetLiquidStatus(m_caster.GetPhaseShift(), x, y, z, out liquidData, null, m_caster.GetCollisionHeight()) != 0) liquidLevel = liquidData.level; if (liquidLevel <= ground) // When there is no liquid Map.GetWaterOrGroundLevel returns ground level diff --git a/Source/Scripts/Spells/Generic.cs b/Source/Scripts/Spells/Generic.cs index 0b08e99f4..81650faea 100644 --- a/Source/Scripts/Spells/Generic.cs +++ b/Source/Scripts/Spells/Generic.cs @@ -153,7 +153,7 @@ namespace Scripts.Spells.Generic Unit caster = GetCaster(); Position summonPos = caster.GetPosition(); LiquidData liquidStatus; - if (caster.GetMap().GetLiquidStatus(caster.GetPhaseShift(), caster.GetPositionX(), caster.GetPositionY(), caster.GetPositionZ(), LiquidHeaderTypeFlags.AllLiquids, out liquidStatus, caster.GetCollisionHeight()) != ZLiquidStatus.NoWater) + if (caster.GetMap().GetLiquidStatus(caster.GetPhaseShift(), caster.GetPositionX(), caster.GetPositionY(), caster.GetPositionZ(), out liquidStatus, null, caster.GetCollisionHeight()) != ZLiquidStatus.NoWater) summonPos.posZ = liquidStatus.level; dest.Relocate(summonPos); }