diff --git a/Source/Game/Collision/Callbacks.cs b/Source/Game/Collision/Callbacks.cs index 68f9fd071..1d36f8808 100644 --- a/Source/Game/Collision/Callbacks.cs +++ b/Source/Game/Collision/Callbacks.cs @@ -15,6 +15,7 @@ namespace Game.Collision public virtual void Invoke(Vector3 point, GameObjectModel obj) { } 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 r, GameObjectModel obj, ref float distance) { return false; } } public class TriBoundFunc @@ -51,7 +52,7 @@ namespace Game.Collision public override bool Invoke(Ray ray, uint entry, ref float distance, bool stopAtFirstHit) { GroupModel.InsideResult result = prims[(int)entry].IsInsideObject(ray, out float group_Z); - if ( result != GroupModel.InsideResult.OutOfBounds) + if (result != GroupModel.InsideResult.OutOfBounds) { if (result != GroupModel.InsideResult.MaybeInside) { @@ -219,6 +220,26 @@ namespace Game.Collision PhaseShift _phaseShift; } + class DynamicTreeLosCallback : WorkerCallback + { + bool _didHit; + PhaseShift _phaseShift; + + public DynamicTreeLosCallback(PhaseShift phaseShift) + { + _phaseShift = phaseShift; + } + + public override bool Invoke(Ray r, GameObjectModel obj, ref float distance) + { + if (!obj.IsLosBlockingDisabled()) + _didHit = obj.IntersectRay(r, ref distance, true, _phaseShift, ModelIgnoreFlags.Nothing); + return _didHit; + } + + public bool DidHit() { return _didHit; } + } + public class DynamicTreeLocationInfoCallback : WorkerCallback { public DynamicTreeLocationInfoCallback(PhaseShift phaseShift) diff --git a/Source/Game/Collision/DynamicTree.cs b/Source/Game/Collision/DynamicTree.cs index 7fe4b4e94..fa1ae4898 100644 --- a/Source/Game/Collision/DynamicTree.cs +++ b/Source/Game/Collision/DynamicTree.cs @@ -94,7 +94,7 @@ namespace Game.Collision return true; Ray r = new(startPos, (endPos - startPos) / maxDist); - DynamicTreeIntersectionCallback callback = new(phaseShift); + DynamicTreeLosCallback callback = new(phaseShift); impl.IntersectRay(r, callback, ref maxDist, endPos); return !callback.DidHit(); diff --git a/Source/Game/Collision/Models/GameObjectModel.cs b/Source/Game/Collision/Models/GameObjectModel.cs index 6889f043d..bfc3fc002 100644 --- a/Source/Game/Collision/Models/GameObjectModel.cs +++ b/Source/Game/Collision/Models/GameObjectModel.cs @@ -185,8 +185,10 @@ namespace Game.Collision public override Vector3 GetPosition() { return iPos; } public override AxisAlignedBox GetBounds() { return iBound; } - public void EnableCollision(bool enable) { _collisionEnabled = enable; } - bool IsCollisionEnabled() { return _collisionEnabled; } + public void EnableCollision(bool enable) { iCollisionEnabled = enable; } + public bool IsCollisionEnabled() { return iCollisionEnabled; } + public void DisableLosBlocking(bool enable) { iLosBlockingDisabled = enable; } + public bool IsLosBlockingDisabled() { return iLosBlockingDisabled; } public byte GetNameSetId() { return owner.GetNameSetId(); } public static bool LoadGameObjectModelList() @@ -232,7 +234,8 @@ namespace Game.Collision return true; } - bool _collisionEnabled; + bool iCollisionEnabled; // Is model ignored in all checks + bool iLosBlockingDisabled; // Is model ignored during line of sight checks (but is always included in location/height checks) AxisAlignedBox iBound; Matrix4x4 iInvRot; Vector3 iPos; diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index f035497c7..543affd57 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -3885,8 +3885,14 @@ namespace Game.Entities public void CreateModel() { m_model = GameObjectModel.Create(new GameObjectModelOwnerImpl(this)); - if (m_model != null && m_model.IsMapObject()) - SetFlag(GameObjectFlags.MapObject); + if (m_model != null) + { + if (m_model.IsMapObject()) + SetFlag(GameObjectFlags.MapObject); + + if (GetGoType() == GameObjectTypes.Door) + m_model.DisableLosBlocking(GetGoInfo().Door.NotLOSBlocking != 0); + } } // There's many places not ready for dynamic spawns. This allows them to live on for now.