diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index c9ef82302..de4362d40 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -164,7 +164,7 @@ namespace Barotrauma currentHull = value; foreach (Limb limb in Limbs) { - limb.body.Submarine = currentHull == null ? null : Submarine.Loaded; + limb.body.Submarine = currentHull == null ? null : currentHull.Submarine; } } } @@ -227,6 +227,7 @@ namespace Barotrauma Limb limb = new Limb(character, subElement, scale); + limb.body.FarseerBody.OnCollision += OnLimbCollision; Limbs[ID] = limb; @@ -381,6 +382,8 @@ namespace Barotrauma private void CalculateImpact(Fixture f1, Fixture f2, Contact contact) { + if (character.DisableImpactDamageTimer > 0.0f) return; + Vector2 normal = contact.Manifold.LocalNormal; Vector2 avgVelocity = Vector2.Zero; @@ -574,18 +577,18 @@ namespace Barotrauma for (int i = -1; i < 2; i += 2) { //don't teleport outside the sub if right next to a hull - if (Hull.FindHull(findPos + new Vector2(Submarine.GridSize.X * 2.0f * i, 0.0f), currentHull) != null) return; - if (Hull.FindHull(findPos + new Vector2(0.0f, Submarine.GridSize.Y * 2.0f * i), currentHull) != null) return; + if (Hull.FindHull(findPos + new Vector2(Submarine.GridSize.X * 4.0f * i, 0.0f), currentHull) != null) return; + if (Hull.FindHull(findPos + new Vector2(0.0f, Submarine.GridSize.Y * 4.0f * i), currentHull) != null) return; } - Vector2 ragdollSpeed = refLimb.LinearVelocity == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(refLimb.LinearVelocity); - SetPosition(refLimb.SimPosition + ConvertUnits.ToSimUnits(currentHull.Submarine.Position)); - character.CursorPosition += currentHull.Submarine.Position; + if (Gap.FindAdjacent(currentHull.ConnectedGaps, findPos, 150.0f) != null) return; + + Teleport(ConvertUnits.ToSimUnits(currentHull.Submarine.Position), currentHull.Submarine.Velocity, true); + } - else if (currentHull == null && newHull != null && newHull.Submarine != null) + else if (currentHull == null && newHull.Submarine != null) { - SetPosition(refLimb.SimPosition - ConvertUnits.ToSimUnits(newHull.Submarine.Position)); - character.CursorPosition -= newHull.Submarine.Position; + Teleport(-ConvertUnits.ToSimUnits(newHull.Submarine.Position), -newHull.Submarine.Velocity, false); } } @@ -593,9 +596,48 @@ namespace Barotrauma character.Submarine = CurrentHull == null ? null : Submarine.Loaded; - UpdateCollisionCategories(); } + + private void Teleport(Vector2 moveAmount, Vector2 velocityChange, bool inToOut) + { + foreach (Limb limb in Limbs) + { + if (limb.body.FarseerBody.ContactList == null) continue; + + ContactEdge ce = limb.body.FarseerBody.ContactList; + while (ce != null && ce.Contact != null) + { + ce.Contact.Enabled = false; + //if (ce.Contact.IsTouching && ce.Contact.Enabled && + // ((inToOut && ce.Contact.FixtureA.Body.UserData is Structure) || (!inToOut && ce.Contact.FixtureA.Body.UserData is Submarine))) + //{ + // Vector2 normal; + // FarseerPhysics.Common.FixedArray2 worldPoints; + // ce.Contact.GetWorldManifold(out normal, out worldPoints); + + // foreach (Limb limb2 in Limbs) + // { + // limb2.body.FarseerBody.ApplyLinearImpulse(limb2.Mass * normal); + // } + + // return false; + //} + ce = ce.Next; + } + } + + foreach (Limb limb in Limbs) + { + limb.body.LinearVelocity += velocityChange; + } + + character.Stun = 0.1f; + character.DisableImpactDamageTimer = 0.25f; + + SetPosition(refLimb.SimPosition + moveAmount); + character.CursorPosition += moveAmount; + } private void UpdateCollisionCategories() { @@ -657,8 +699,8 @@ namespace Barotrauma foreach (Limb limb in Limbs) { //find the room which the limb is in - //the room where the ragdoll is in is used as the "guess", meaning that it's checked first - Hull limbHull = Hull.FindHull(limb.WorldPosition, currentHull); + //the room where the ragdoll is in is used as the "guess", meaning that it's checked first + Hull limbHull = currentHull == null ? null : Hull.FindHull(limb.WorldPosition, currentHull); bool prevInWater = limb.inWater; limb.inWater = false; @@ -734,10 +776,18 @@ namespace Barotrauma foreach (Limb limb in Limbs) { - //check visibility from the new position of RefLimb to the new position of this limb - Vector2 movePos = limb.SimPosition + moveAmount; + if (limb == refLimb) + { + TrySetLimbPosition(limb, simPosition, simPosition, lerp); + } + else + { + //check visibility from the new position of RefLimb to the new position of this limb + Vector2 movePos = limb.SimPosition + moveAmount; + + TrySetLimbPosition(limb, simPosition, movePos, lerp); + } - TrySetLimbPosition(limb, simPosition, movePos, lerp); } } @@ -749,7 +799,6 @@ namespace Barotrauma { Body body = Submarine.CheckVisibility(original, simPosition); - //if there's something in between the limbs if (body != null) { @@ -758,6 +807,8 @@ namespace Barotrauma } } + + if (lerp) { limb.body.TargetPosition = movePos; @@ -766,8 +817,15 @@ namespace Barotrauma } else { - limb.body.SetTransform(movePos, limb.Rotation); + limb.body.SetTransform(movePos, limb.Rotation); + if (limb.pullJoint != null) + { + limb.pullJoint.WorldAnchorB = limb.pullJoint.WorldAnchorA; + limb.pullJoint.Enabled = false; + } } + + } public void SetRotation(float rotation) @@ -832,7 +890,15 @@ namespace Barotrauma correctionMovement = Vector2.Zero; return; } + + if (resetAll) + { + System.Diagnostics.Debug.WriteLine("reset ragdoll limb positions"); + SetPosition(refLimb.body.TargetPosition, dist < 10.0f); + + return; + } if (inWater) { @@ -865,15 +931,7 @@ namespace Barotrauma correctionMovement = Vector2.Lerp(correctionMovement, newCorrectionMovement, 0.5f); if (Math.Abs(correctionMovement.Y) < 0.1f) correctionMovement.Y = 0.0f; - } - - - if (resetAll) - { - System.Diagnostics.Debug.WriteLine("reset ragdoll limb positions"); - - SetPosition(refLimb.body.TargetPosition, true); - } + } } public virtual Vector2 EstimateCurrPosition(Vector2 prevPosition, float timePassed) diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 14e2d0e92..11c96891e 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -314,6 +314,12 @@ namespace Barotrauma private set; } + public float DisableImpactDamageTimer + { + get; + set; + } + public float SpeedMultiplier { get; @@ -989,6 +995,8 @@ namespace Barotrauma networkUpdateSent = false; } + + DisableImpactDamageTimer -= deltaTime; if (needsAir) { @@ -1767,6 +1775,8 @@ namespace Barotrauma if (inSub) { + //AnimController.FindHull(ConvertUnits.ToDisplayUnits(pos) - Submarine.Loaded.WorldPosition); + Hull newHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(pos), AnimController.CurrentHull, false); if (newHull != null) { @@ -1774,10 +1784,14 @@ namespace Barotrauma Submarine = newHull.Submarine; } } + else + { + AnimController.CurrentHull = null; + Submarine = null; + } if (secondaryKeyState) { - cursorPosition = MathUtils.IsValid(relativeCursorPos) ? relativeCursorPos : Vector2.Zero; ViewTarget = viewTargetID == 0 ? this : Entity.FindEntityByID(viewTargetID); if (ViewTarget == null) ViewTarget = this; @@ -1789,7 +1803,7 @@ namespace Barotrauma cursorPosition = Position + new Vector2(1000.0f, 0.0f) * dir; AnimController.TargetDir = dir < 0 ? Direction.Left : Direction.Right; - } + } AnimController.RefLimb.body.TargetPosition = AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime); diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index c6b4d546b..cc59ba827 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -414,14 +414,11 @@ namespace Barotrauma if (burnt > 0.0f) Burnt -= deltaTime; - if (LinearVelocity.X>100.0f) + if (LinearVelocity.X > 500.0f) { //DebugConsole.ThrowError("CHARACTER EXPLODED"); - foreach (Limb limb in character.AnimController.Limbs) - { - limb.body.ResetDynamics(); - limb.body.SetTransform(character.AnimController.RefLimb.SimPosition, 0.0f); - } + body.ResetDynamics(); + body.SetTransform(character.AnimController.RefLimb.SimPosition, 0.0f); } if (inWater) diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index b0b8dc1e8..930cb574c 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -586,6 +586,39 @@ namespace Barotrauma hull2.Oxygen += Math.Sign(totalOxygen * hull2.FullVolume / (totalVolume) - hull2.Oxygen) * Hull.OxygenDistributionSpeed; } + public static Gap FindAdjacent(List gaps, Vector2 worldPos, float allowedOrthogonalDist) + { + foreach (Gap gap in gaps) + { + if (gap.Open == 0.0f || gap.IsRoomToRoom) continue; + + if (gap.ConnectedWall != null) + { + int sectionIndex = gap.ConnectedWall.FindSectionIndex(gap.Position); + if (sectionIndex > -1 && !gap.ConnectedWall.SectionBodyDisabled(sectionIndex)) continue; + } + + if (gap.isHorizontal) + { + if (worldPos.Y < gap.WorldRect.Y && worldPos.Y > gap.WorldRect.Y - gap.WorldRect.Height && + Math.Abs(gap.WorldRect.Center.X - worldPos.X) < allowedOrthogonalDist) + { + return gap; + } + } + else + { + if (worldPos.X > gap.WorldRect.X && worldPos.X < gap.WorldRect.Right && + Math.Abs(gap.WorldRect.Y - gap.WorldRect.Height / 2 - worldPos.Y) < allowedOrthogonalDist) + { + return gap; + } + } + } + + return null; + } + public override void Remove() { base.Remove(); diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 70f2f97dc..69ed2284a 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -431,13 +431,19 @@ namespace Barotrauma if (limb.character.AnimController.IgnorePlatforms) return false; } } + + if (f2.Body.UserData is Limb) + { + var character = ((Limb)f2.Body.UserData).character; + if (character.DisableImpactDamageTimer > 0.0f || ((Limb)f2.Body.UserData).Mass < 100.0f) return true; + } if (!prefab.IsPlatform && prefab.StairDirection == Direction.None) { Vector2 pos = ConvertUnits.ToDisplayUnits(f2.Body.Position); int section = FindSectionIndex(pos); - if (section>0) + if (section > 0) { Vector2 normal = contact.Manifold.LocalNormal; @@ -529,7 +535,7 @@ namespace Barotrauma public AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, float deltaTime, bool playSound = false) { - if (Submarine.Loaded != null && Submarine.Loaded.GodMode) return new AttackResult(0.0f, 0.0f); + if (Submarine.Loaded != null && Submarine.Loaded.GodMode && Submarine == Submarine.Loaded) return new AttackResult(0.0f, 0.0f); if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f); Vector2 transformedPos = position; diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index c9e9d5a6b..18504201e 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -365,7 +365,7 @@ namespace Barotrauma GameMain.World.RayCast((fixture, point, normal, fraction) => { if (fixture == null || - (fixture.CollisionCategories != Physics.CollisionWall && fixture.CollisionCategories != Physics.CollisionLevel)) return -1; + (!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) && !fixture.CollisionCategories.HasFlag(Physics.CollisionLevel))) return -1; if (ignoreLevel && fixture.CollisionCategories == Physics.CollisionLevel) return -1; diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 9a000975a..59d1d7875 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -112,30 +112,41 @@ namespace Barotrauma body = BodyFactory.CreateBody(GameMain.World, this); - foreach (Hull hull in Hull.hullList) + foreach (Structure wall in Structure.WallList) { - Rectangle rect = hull.Rect; - foreach (Structure wall in Structure.WallList) - { - if (!Submarine.RectsOverlap(wall.Rect, hull.Rect)) continue; - - Rectangle wallRect = wall.IsHorizontal ? - new Rectangle(hull.Rect.X, wall.Rect.Y, hull.Rect.Width, wall.Rect.Height) : - new Rectangle(wall.Rect.X, hull.Rect.Y, wall.Rect.Width, hull.Rect.Height); - - rect = Rectangle.Union( - new Rectangle(wallRect.X, wallRect.Y - wallRect.Height, wallRect.Width, wallRect.Height), - new Rectangle(rect.X, rect.Y - rect.Height, rect.Width, rect.Height)); - rect.Y = rect.Y + rect.Height; - } - + Rectangle rect = wall.Rect; FixtureFactory.AttachRectangle( - ConvertUnits.ToSimUnits(rect.Width), - ConvertUnits.ToSimUnits(rect.Height), - 5.0f, - ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)), - body, this); + ConvertUnits.ToSimUnits(rect.Width), + ConvertUnits.ToSimUnits(rect.Height), + 5.0f, + ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)), + body, this); } + + //foreach (Hull hull in Hull.hullList) + //{ + // Rectangle rect = hull.Rect; + // foreach (Structure wall in Structure.WallList) + // { + // if (!Submarine.RectsOverlap(wall.Rect, hull.Rect)) continue; + + // Rectangle wallRect = wall.IsHorizontal ? + // new Rectangle(hull.Rect.X, wall.Rect.Y, hull.Rect.Width, wall.Rect.Height) : + // new Rectangle(wall.Rect.X, hull.Rect.Y, wall.Rect.Width, hull.Rect.Height); + + // rect = Rectangle.Union( + // new Rectangle(wallRect.X, wallRect.Y - wallRect.Height, wallRect.Width, wallRect.Height), + // new Rectangle(rect.X, rect.Y - rect.Height, rect.Width, rect.Height)); + // rect.Y = rect.Y + rect.Height; + // } + + // FixtureFactory.AttachRectangle( + // ConvertUnits.ToSimUnits(rect.Width), + // ConvertUnits.ToSimUnits(rect.Height), + // 5.0f, + // ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)), + // body, this); + //} } @@ -311,7 +322,7 @@ namespace Barotrauma Debug.Assert(intersection != null); //''+ translatedir'' in order to move the character slightly away from the wall - c.AnimController.SetPosition(c.WorldPosition + ConvertUnits.ToSimUnits((Vector2)intersection - limb.WorldPosition) + translateDir); + c.AnimController.SetPosition(ConvertUnits.ToSimUnits(c.WorldPosition + ((Vector2)intersection - limb.WorldPosition)) + translateDir); return; } @@ -432,7 +443,7 @@ namespace Barotrauma FixedArray2 points; contact.GetWorldManifold(out normal2, out points); - Vector2 normalizedVel = limb.character.AnimController.RefLimb.LinearVelocity == Vector2.Zero ? + Vector2 normalizedVel = limb.character.AnimController.RefLimb.LinearVelocity == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(limb.character.AnimController.RefLimb.LinearVelocity); Vector2 targetPos = ConvertUnits.ToDisplayUnits(points[0] - normal2); @@ -441,9 +452,9 @@ namespace Barotrauma if (newHull == null) { - targetPos = ConvertUnits.ToDisplayUnits(points[0] - normalizedVel); + targetPos = ConvertUnits.ToDisplayUnits(points[0] + normalizedVel); - newHull = Hull.FindHull(targetPos, null); + newHull = Hull.FindHull(targetPos, null); if (newHull == null) return true; } @@ -452,41 +463,12 @@ namespace Barotrauma targetPos = limb.character.WorldPosition; - bool gapFound = false; - foreach (Gap gap in gaps) - { - if (gap.Open == 0.0f || gap.IsRoomToRoom) continue; + Gap adjacentGap = Gap.FindAdjacent(gaps, targetPos, 200.0f); - if (gap.ConnectedWall != null) - { - int sectionIndex = gap.ConnectedWall.FindSectionIndex(gap.Position); - if (sectionIndex > -1 && !gap.ConnectedWall.SectionBodyDisabled(sectionIndex)) continue; - } - - if (gap.isHorizontal) - { - if (targetPos.Y < gap.WorldRect.Y && targetPos.Y > gap.WorldRect.Y - gap.WorldRect.Height && - Math.Abs(gap.WorldRect.Center.X-targetPos.X)<200.0f) - { - gapFound = true; - break; - } - } - else - { - if (targetPos.X > gap.WorldRect.X && targetPos.X < gap.WorldRect.Right && - Math.Abs(gap.WorldRect.Y - gap.WorldRect.Height/2 - targetPos.Y) < 200.0f) - { - gapFound = true; - break; - } - } - } - - if (!gapFound) return true; + if (adjacentGap==null) return true; var ragdoll = limb.character.AnimController; - ragdoll.FindHull(newHull.WorldPosition); + ragdoll.FindHull(newHull.WorldPosition, true); return false; }