From 7167cfaf8666d7e3dff4684406405a0c7d519d07 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 28 Mar 2018 18:05:54 -0400 Subject: [PATCH] Core/Maps: Implemented getting area id from gameobject spawns --- Source/Game/Collision/Callbacks.cs | 19 ++++++- Source/Game/Collision/DynamicTree.cs | 27 +++++++++- .../Game/Collision/Models/GameObjectModel.cs | 28 ++++++++++ Source/Game/Collision/Models/IModel.cs | 1 + Source/Game/Collision/RegularGrid2D.cs | 2 +- Source/Game/Entities/GameObject/GameObject.cs | 53 +++++++++++++++---- Source/Game/Maps/Map.cs | 49 +++++++++++++++-- 7 files changed, 161 insertions(+), 18 deletions(-) diff --git a/Source/Game/Collision/Callbacks.cs b/Source/Game/Collision/Callbacks.cs index 6cc7f9e16..287d5df47 100644 --- a/Source/Game/Collision/Callbacks.cs +++ b/Source/Game/Collision/Callbacks.cs @@ -24,6 +24,7 @@ namespace Game.Collision public class WorkerCallback { public virtual void Invoke(Vector3 point, uint entry) { } + public virtual void Invoke(Vector3 point, IModel entry) { } public virtual bool Invoke(Ray ray, uint entry, ref float distance, bool pStopAtFirstHit) { return false; } public virtual bool Invoke(Ray r, IModel obj, ref float distance) { return false; } public virtual bool Invoke(Ray ray, uint idx, ref float maxDist) { return false; } @@ -59,7 +60,7 @@ namespace Game.Collision zDist = float.PositiveInfinity; zVec = down; } - + List prims; public GroupModel hit; public float zDist; @@ -245,5 +246,21 @@ namespace Game.Collision PhaseShift _phaseShift; } + public class DynamicTreeAreaInfoCallback : WorkerCallback + { + public DynamicTreeAreaInfoCallback(PhaseShift phaseShift) + { + _phaseShift = phaseShift; + } + public override void Invoke(Vector3 p, IModel obj) + { + obj.IntersectPoint(p, _areaInfo, _phaseShift); + } + + public AreaInfo GetAreaInfo() { return _areaInfo; } + + PhaseShift _phaseShift; + AreaInfo _areaInfo; + } } diff --git a/Source/Game/Collision/DynamicTree.cs b/Source/Game/Collision/DynamicTree.cs index 6a2c9fb21..290302b7b 100644 --- a/Source/Game/Collision/DynamicTree.cs +++ b/Source/Game/Collision/DynamicTree.cs @@ -23,12 +23,11 @@ namespace Game.Collision { public class DynamicMapTree { - DynTreeImpl impl; - public DynamicMapTree() { impl = new DynTreeImpl(); } + public void insert(GameObjectModel mdl) { impl.insert(mdl); @@ -128,6 +127,30 @@ namespace Game.Collision else 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) + { + flags = 0; + adtId = 0; + rootId = 0; + groupId = 0; + + Vector3 v = new Vector3(x, y, z + 0.5f); + DynamicTreeAreaInfoCallback intersectionCallBack = new DynamicTreeAreaInfoCallback(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; + } + + DynTreeImpl impl; } public class DynTreeImpl : RegularGrid2D> diff --git a/Source/Game/Collision/Models/GameObjectModel.cs b/Source/Game/Collision/Models/GameObjectModel.cs index 1f491d4eb..a15eab954 100644 --- a/Source/Game/Collision/Models/GameObjectModel.cs +++ b/Source/Game/Collision/Models/GameObjectModel.cs @@ -31,6 +31,7 @@ namespace Game.Collision { public virtual bool IsSpawned() { return false; } public virtual uint GetDisplayId() { return 0; } + public virtual byte GetNameSetId() { return 0; } public virtual bool IsInPhase(PhaseShift phaseShift) { return false; } public virtual Vector3 GetPosition() { return Vector3.Zero; } public virtual float GetOrientation() { return 0.0f; } @@ -111,6 +112,33 @@ namespace Game.Collision return hit; } + public override void IntersectPoint(Vector3 point, AreaInfo info, PhaseShift phaseShift) + { + if (!isCollisionEnabled() || !owner.IsSpawned()) + return; + + if (!owner.IsInPhase(phaseShift)) + return; + + if (!iBound.contains(point)) + return; + + // child bounds are defined in object space: + Vector3 pModel = iInvRot * (point - iPos) * iInvScale; + Vector3 zDirModel = iInvRot * 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 = ((modelGround * iInvRot) * iScale + iPos).Z; + if (info.ground_Z < world_Z) + { + info.ground_Z = world_Z; + info.adtId = owner.GetNameSetId(); + } + } + } + public bool UpdatePosition() { if (iModel == null) diff --git a/Source/Game/Collision/Models/IModel.cs b/Source/Game/Collision/Models/IModel.cs index f4262f4ee..1dcff227a 100644 --- a/Source/Game/Collision/Models/IModel.cs +++ b/Source/Game/Collision/Models/IModel.cs @@ -27,5 +27,6 @@ namespace Game.Collision public virtual bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift) { return false; } public virtual bool IntersectRay(Ray ray, ref float distance, bool stopAtFirstHit) { return false; } + public virtual void IntersectPoint(Vector3 point, AreaInfo info, PhaseShift phaseShift) { } } } diff --git a/Source/Game/Collision/RegularGrid2D.cs b/Source/Game/Collision/RegularGrid2D.cs index 0a173f0fa..ef7f087ad 100644 --- a/Source/Game/Collision/RegularGrid2D.cs +++ b/Source/Game/Collision/RegularGrid2D.cs @@ -184,7 +184,7 @@ namespace Game.Collision } while (cell.isValid()); } - void intersectPoint(Vector3 point, WorkerCallback intersectCallback) + public void intersectPoint(Vector3 point, WorkerCallback intersectCallback) { Cell cell = Cell.ComputeCell(point.X, point.Y); if (!cell.isValid()) diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index 6bd2bed7f..ec57130f2 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -2157,8 +2157,8 @@ namespace Game.Entities uint modelId = m_goInfo.displayId; DestructibleModelDataRecord modelData = CliDB.DestructibleModelDataStorage.LookupByKey(m_goInfo.DestructibleBuilding.DestructibleModelRec); if (modelData != null) - if (modelData.State0Wmo != 0) - modelId = modelData.State0Wmo; + if (modelData.State1Wmo != 0) + modelId = modelData.State1Wmo; SetDisplayId(modelId); if (setHealth) @@ -2189,8 +2189,8 @@ namespace Game.Entities uint modelId = m_goInfo.displayId; DestructibleModelDataRecord modelData = CliDB.DestructibleModelDataStorage.LookupByKey(m_goInfo.DestructibleBuilding.DestructibleModelRec); if (modelData != null) - if (modelData.State1Wmo != 0) - modelId = modelData.State1Wmo; + if (modelData.State2Wmo != 0) + modelId = modelData.State2Wmo; SetDisplayId(modelId); if (setHealth) @@ -2209,8 +2209,8 @@ namespace Game.Entities uint modelId = m_goInfo.displayId; DestructibleModelDataRecord modelData = CliDB.DestructibleModelDataStorage.LookupByKey(m_goInfo.DestructibleBuilding.DestructibleModelRec); if (modelData != null) - if (modelData.State2Wmo != 0) - modelId = modelData.State2Wmo; + if (modelData.State3Wmo != 0) + modelId = modelData.State3Wmo; SetDisplayId(modelId); // restores to full health @@ -2303,6 +2303,40 @@ namespace Game.Entities UpdateModel(); } + public byte GetNameSetId() + { + switch (GetGoType()) + { + case GameObjectTypes.DestructibleBuilding: + DestructibleModelDataRecord modelData = CliDB.DestructibleModelDataStorage.LookupByKey(m_goInfo.DestructibleBuilding.DestructibleModelRec); + if (modelData != null) + { + switch (GetDestructibleState()) + { + case GameObjectDestructibleState.Intact: + return modelData.State0NameSet; + case GameObjectDestructibleState.Damaged: + return modelData.State1NameSet; + case GameObjectDestructibleState.Destroyed: + return modelData.State2NameSet; + case GameObjectDestructibleState.Rebuilding: + return modelData.State3NameSet; + default: + break; + } + } + break; + case GameObjectTypes.GarrisonBuilding: + case GameObjectTypes.GarrisonPlot: + case GameObjectTypes.PhaseableMo: + return (byte)(GetByteValue(GameObjectFields.Flags, 1) & 0xF); + default: + break; + } + + return 0; + } + void EnableCollision(bool enable) { if (m_model == null) @@ -2753,12 +2787,9 @@ namespace Game.Entities _owner = owner; } - public override bool IsSpawned() - { - return _owner.isSpawned(); - } - + public override bool IsSpawned() { return _owner.isSpawned(); } public override uint GetDisplayId() { return _owner.GetDisplayId(); } + public override byte GetNameSetId() { return _owner.GetNameSetId(); } public override bool IsInPhase(PhaseShift phaseShift) { return _owner.GetPhaseShift().CanSee(phaseShift); } public override Vector3 GetPosition() { return new Vector3(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ()); } public override float GetOrientation() { return _owner.GetOrientation(); } diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index 1c347d736..a1d46b5fa 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -1834,16 +1834,59 @@ namespace Game.Maps groupId = 0; float vmap_z = z; + float dynamic_z = z; + float check_z = z; uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y); - if (Global.VMapMgr.getAreaInfo(terrainMapId, x, y, ref vmap_z, out flags, out adtId, out rootId, out groupId)) + uint vflags; + int vadtId; + int vrootId; + int vgroupId; + uint dflags; + int dadtId; + int drootId; + int dgroupId; + + bool hasVmapAreaInfo = Global.VMapMgr.getAreaInfo(terrainMapId, x, y, ref vmap_z, out vflags, out vadtId, out vrootId, out vgroupId); + bool hasDynamicAreaInfo = _dynamicTree.getAreaInfo(x, y, ref dynamic_z, phaseShift, out dflags, out dadtId, out drootId, out dgroupId); + + if (hasVmapAreaInfo) + { + if (hasDynamicAreaInfo && dynamic_z > vmap_z) + { + check_z = dynamic_z; + flags = dflags; + adtId = dadtId; + rootId = drootId; + groupId = dgroupId; + } + else + { + check_z = vmap_z; + flags = vflags; + adtId = vadtId; + rootId = vrootId; + groupId = vgroupId; + } + } + else if (hasDynamicAreaInfo) + { + check_z = dynamic_z; + flags = dflags; + adtId = dadtId; + rootId = drootId; + groupId = dgroupId; + } + + + if (hasVmapAreaInfo || hasDynamicAreaInfo) { // check if there's terrain between player height and object height GridMap gmap = GetGridMap(terrainMapId, x, y); if (gmap != null) { - float _mapheight = gmap.getHeight(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 > vmap_z) + if (z + 2.0f > mapHeight && mapHeight > check_z) return false; } return true;