diff --git a/Subsurface/Source/Characters/AICharacter.cs b/Subsurface/Source/Characters/AICharacter.cs index 7c9c93bfe..e95d72a76 100644 --- a/Subsurface/Source/Characters/AICharacter.cs +++ b/Subsurface/Source/Characters/AICharacter.cs @@ -47,7 +47,7 @@ namespace Barotrauma AnimController.SimplePhysicsEnabled = false; } - if (IsDead || Health <= 0.0f) return; + if (IsDead || Health <= 0.0f || IsUnconscious || Stun > 0.0f) return; if (Controlled == this || !aiController.Enabled) return; diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index 9a1ec85f1..c91a68137 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -941,6 +941,9 @@ namespace Barotrauma target.AnimController.TargetMovement, (character.SimPosition + Vector2.UnitX * Dir) - target.SimPosition, 0.5f); } + + //if on stairs, make the dragged character "climb up" (= collide with stairs) + if (stairs != null) target.AnimController.TargetMovement = new Vector2 (target.AnimController.TargetMovement.X, 1.0f); } public void Grab(Vector2 rightHandPos, Vector2 leftHandPos) diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 9b5267069..34086d3bc 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -707,17 +707,36 @@ namespace Barotrauma public void FindHull(Vector2? worldPosition = null, bool setSubmarine = true) { - if (!CanEnterSubmarine) - { - return; - } - Vector2 findPos = worldPosition==null ? this.WorldPosition : (Vector2)worldPosition; Hull newHull = Hull.FindHull(findPos, currentHull); if (newHull == currentHull) return; + if (!CanEnterSubmarine) + { + //character is inside the sub even though it shouldn't be able to enter -> teleport it out + + //far from an ideal solution, but monsters getting lodged inside the sub seems to be + //pretty rare during normal gameplay (requires abnormally high velocities), so I think + //this is preferable to the cost of using continuous collision detection for the character collider + if (newHull != null) + { + //find a position 32 units away from the hull + Vector2? intersection = MathUtils.GetLineRectangleIntersection( + newHull.WorldPosition, + newHull.WorldPosition + Vector2.Normalize(WorldPosition - newHull.WorldPosition) * Math.Max(newHull.Rect.Width, newHull.Rect.Height), + new Rectangle(newHull.WorldRect.X - 32, newHull.WorldRect.Y + 32, newHull.WorldRect.Width + 64, newHull.Rect.Height + 64)); + + if (intersection != null) + { + Collider.SetTransform(ConvertUnits.ToSimUnits((Vector2)intersection), Collider.Rotation); + } + } + + return; + } + if (setSubmarine) { //in -> out @@ -1358,10 +1377,26 @@ namespace Barotrauma { float halfHeight = Collider.height * 0.5f + Collider.radius; - Vector2 offset = Vector2.Zero; - offset.Y = -colliderHeightFromFloor; - return Collider.SimPosition + offset + - new Vector2((float)Math.Sin(Collider.Rotation), -(float)Math.Cos(Collider.Rotation)) * halfHeight; + float offset = 0.0f; + + if (!character.IsUnconscious && !character.IsDead && character.Stun <= 0.0f) + { + offset = -colliderHeightFromFloor; + } + + float lowestBound = Collider.SimPosition.Y; + for (int i = 0; i < Collider.FarseerBody.FixtureList.Count; i++) + { + FarseerPhysics.Collision.AABB aabb; + FarseerPhysics.Common.Transform transform; + + Collider.FarseerBody.GetTransform(out transform); + Collider.FarseerBody.FixtureList[i].Shape.ComputeAABB(out aabb, ref transform, i); + + lowestBound = Math.Min(aabb.LowerBound.Y, lowestBound); + } + + return new Vector2(Collider.SimPosition.X, lowestBound + offset); } public Limb FindLowestLimb()