From c76fb32e15be43f5d0711164f3cbf20e34286bc2 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Thu, 28 Mar 2019 18:12:23 +0200 Subject: [PATCH] (5bab406f1) Fixed "allowInsideFixture" raycasts not working correctly - checking if the ray is inside the AABB is not enough, we also need to take the shape and rotation of the fixture into account. --- .../Source/Items/ItemPrefab.cs | 33 +++++++++++++++++++ .../BarotraumaShared/Source/Map/Submarine.cs | 28 ++++++++++++---- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs index df13f9a00..c298546ab 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs @@ -884,6 +884,39 @@ namespace Barotrauma AllowedLinks = element.GetAttributeStringArray("allowedlinks", new string[0], convertToLowerInvariant: true).ToList(); + if (sprite == null) + { + DebugConsole.ThrowError("Item \"" + Name + "\" has no sprite!"); +#if SERVER + sprite = new Sprite("", Vector2.Zero); + sprite.SourceRect = new Rectangle(0, 0, 32, 32); +#else + sprite = new Sprite(TextureLoader.PlaceHolderTexture, null, null) + { + Origin = TextureLoader.PlaceHolderTexture.Bounds.Size.ToVector2() / 2 + }; +#endif + size = sprite.size; + sprite.EntityID = identifier; + } + + if (!category.HasFlag(MapEntityCategory.Legacy) && string.IsNullOrEmpty(identifier)) + { + DebugConsole.ThrowError( + "Item prefab \"" + name + "\" has no identifier. All item prefabs have a unique identifier string that's used to differentiate between items during saving and loading."); + } + if (!string.IsNullOrEmpty(identifier)) + { + MapEntityPrefab existingPrefab = List.Find(e => e.Identifier == identifier); + if (existingPrefab != null) + { + DebugConsole.ThrowError( + "Map entity prefabs \"" + name + "\" and \"" + existingPrefab.Name + "\" have the same identifier!"); + } + } + + AllowedLinks = element.GetAttributeStringArray("allowedlinks", new string[0], convertToLowerInvariant: true).ToList(); + List.Add(this); } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs index 1629b9bff..738c9fa16 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs @@ -678,17 +678,24 @@ namespace Barotrauma Body closestBody = null; if (allowInsideFixture) { - var aabb = new FarseerPhysics.Collision.AABB(rayStart - Vector2.UnitY * 0.001f, rayStart + Vector2.UnitY * 0.001f); + var aabb = new FarseerPhysics.Collision.AABB(rayStart - Vector2.One * 0.001f, rayStart + Vector2.One * 0.001f); GameMain.World.QueryAABB((fixture) => { - if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return false; } + if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return true; } + + fixture.Body.GetTransform(out FarseerPhysics.Common.Transform transform); + if (!fixture.Shape.TestPoint(ref transform, ref rayStart)) { return true; } + closestFraction = 0.0f; closestNormal = Vector2.Normalize(rayEnd - rayStart); if (fixture.Body != null) closestBody = fixture.Body; - return true; + return false; }, ref aabb); if (closestFraction <= 0.0f) { + lastPickedPosition = rayStart; + lastPickedFraction = closestFraction; + lastPickedNormal = closestNormal; return closestBody; } } @@ -740,14 +747,21 @@ namespace Barotrauma if (allowInsideFixture) { - var aabb = new FarseerPhysics.Collision.AABB(rayStart - Vector2.UnitY * 0.001f, rayStart + Vector2.UnitY * 0.001f); + var aabb = new FarseerPhysics.Collision.AABB(rayStart - Vector2.One * 0.001f, rayStart + Vector2.One * 0.001f); GameMain.World.QueryAABB((fixture) => { - if (bodies.Contains(fixture.Body) || fixture.Body == null) { return false; } - if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return false; } + if (bodies.Contains(fixture.Body) || fixture.Body == null) { return true; } + if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return true; } + + fixture.Body.GetTransform(out FarseerPhysics.Common.Transform transform); + if (!fixture.Shape.TestPoint(ref transform, ref rayStart)) { return true; } + closestFraction = 0.0f; + lastPickedPosition = rayStart; + lastPickedFraction = 0.0f; + lastPickedNormal = Vector2.Normalize(rayEnd - rayStart); bodies.Add(fixture.Body); - return true; + return false; }, ref aabb); }