diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index 72b956137..ba7a0f353 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -280,7 +280,9 @@ namespace Barotrauma return; } - SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(SimPosition - selectedAiTarget.SimPosition) * 5); + Vector2 escapeDir = Vector2.Normalize(SimPosition - selectedAiTarget.SimPosition); + if (!MathUtils.IsValid(escapeDir)) escapeDir = Vector2.UnitY; + SteeringManager.SteeringManual(deltaTime, escapeDir * 5); SteeringManager.SteeringWander(1.0f); SteeringManager.SteeringAvoid(deltaTime, 2f); } @@ -490,8 +492,10 @@ namespace Barotrauma if (dist < ConvertUnits.ToSimUnits(500.0f)) { + Vector2 attackDir = Vector2.Normalize(Character.SimPosition - attackPosition); + if (!MathUtils.IsValid(attackDir)) attackDir = Vector2.UnitY; steeringManager.SteeringSeek(attackPosition, -0.8f); - steeringManager.SteeringManual(deltaTime, Vector2.Normalize(Character.SimPosition - attackPosition) * (1.0f - (dist / 500.0f))); + steeringManager.SteeringManual(deltaTime, attackDir * (1.0f - (dist / 500.0f))); } steeringManager.SteeringAvoid(deltaTime, 1.0f); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs index 84c807617..423a9ec82 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -63,6 +63,7 @@ namespace Barotrauma character.SetInput(InputType.Aim, false, true); Vector2 enemyDiff = Vector2.Normalize(enemy.Position - character.Position); + if (!MathUtils.IsValid(enemyDiff)) enemyDiff = Rand.Vector(1.0f); float weaponAngle = ((weapon.body.Dir == 1.0f) ? weapon.body.Rotation : weapon.body.Rotation - MathHelper.Pi); Vector2 weaponDir = new Vector2((float)Math.Cos(weaponAngle), (float)Math.Sin(weaponAngle)); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/SteeringManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/SteeringManager.cs index 910c8d8c2..e3d4aac22 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/SteeringManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/SteeringManager.cs @@ -80,9 +80,9 @@ namespace Barotrauma } float steeringSpeed = steering.Length(); - if (steeringSpeed>speed) + if (steeringSpeed > speed) { - steering = Vector2.Normalize(steering) * Math.Abs(speed); + steering = Vector2.Normalize(steering) * Math.Abs(speed); } host.Steering = steering; @@ -97,12 +97,12 @@ namespace Barotrauma targetVel = Vector2.Normalize(targetVel) * speed; Vector2 newSteering = targetVel - host.Steering; - if (newSteering==Vector2.Zero) return Vector2.Zero; + if (newSteering == Vector2.Zero) return Vector2.Zero; float steeringSpeed = (newSteering + host.Steering).Length(); if (steeringSpeed > Math.Abs(speed)) { - newSteering = Vector2.Normalize(newSteering)*Math.Abs(speed); + newSteering = Vector2.Normalize(newSteering) * Math.Abs(speed); } return newSteering; @@ -151,8 +151,7 @@ namespace Barotrauma } else { - Structure closestStructure = closestBody.UserData as Structure; - if (closestStructure != null) + if (closestBody.UserData is Structure closestStructure) { Vector2 obstaclePosition = Submarine.LastPickedPosition; if (closestStructure.IsHorizontal) @@ -166,15 +165,17 @@ namespace Barotrauma avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - obstaclePosition); } - else if (closestBody.UserData is Item) + else if (closestBody.UserData is Item item) { - Item item = (Item)closestBody.UserData; avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - item.SimPosition); } else { avoidSteering = Vector2.Normalize(host.SimPosition - Submarine.LastPickedPosition); } + //failed to normalize (the obstacle to avoid is at the same position as the character?) + // -> move to a random direction + if (!MathUtils.IsValid(avoidSteering)) avoidSteering = Rand.Vector(1.0f); } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs index d2f06b11a..fb5ed6df7 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs @@ -766,10 +766,13 @@ namespace Barotrauma //this is preferable to the cost of using continuous collision detection for the character collider if (newHull != null) { + Vector2 hullDiff = WorldPosition - newHull.WorldPosition; + Vector2 moveDir = hullDiff.LengthSquared() < 0.001f ? Vector2.UnitY : Vector2.Normalize(hullDiff); + //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), + newHull.WorldPosition + moveDir * 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) @@ -1494,7 +1497,7 @@ namespace Barotrauma Vector2 force = Vector2.Zero; foreach (Gap gap in Gap.GapList) { - if (gap.Open <= 0.0f || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce == Vector2.Zero) continue; + if (gap.Open <= 0.0f || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce.LengthSquared() < 0.01f) continue; Vector2 gapPos = gap.SimPosition; float dist = Vector2.Distance(limbPos, gapPos); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Propulsion.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Propulsion.cs index 0d4079573..97a54afc4 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Propulsion.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Propulsion.cs @@ -74,6 +74,8 @@ namespace Barotrauma.Items.Components } Vector2 dir = Vector2.Normalize(character.CursorPosition - character.Position); + //move upwards if the cursor is at the position of the character + if (!MathUtils.IsValid(dir)) dir = Vector2.UnitY; Vector2 propulsion = dir * force; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs index 13c66dde4..4369bbf7a 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs @@ -94,8 +94,9 @@ namespace Barotrauma.Items.Components if (throwPos < -0.0) { - Vector2 throwVector = picker.CursorWorldPosition - picker.WorldPosition; - throwVector = Vector2.Normalize(throwVector); + Vector2 throwVector = Vector2.Normalize(picker.CursorWorldPosition - picker.WorldPosition); + //throw upwards if cursor is at the position of the character + if (!MathUtils.IsValid(throwVector)) throwVector = Vector2.UnitY; GameServer.Log(picker.LogName + " threw " + item.Name, ServerLog.MessageType.ItemInteraction); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs index 9c7dd768c..d7256eaa9 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Controller.cs @@ -116,7 +116,7 @@ namespace Barotrauma.Items.Components else { diff.Y = 0.0f; - if (diff != Vector2.Zero && diff.Length() > 10.0f) + if (diff != Vector2.Zero && diff.LengthSquared() > 10.0f * 10.0f) { character.AnimController.TargetMovement = Vector2.Normalize(diff); character.AnimController.TargetDir = diff.X > 0.0f ? Direction.Right : Direction.Left; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs index 00326b53b..8f9b0e30b 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs @@ -211,8 +211,9 @@ namespace Barotrauma.Items.Components { Vector2 diff = item.Submarine.WorldPosition - (Vector2)intersection; - //far enough -> ignore - if (diff.Length() > avoidRadius) continue; + float dist = diff.Length(); + //far enough or too close to normalize the diff -> ignore + if (dist > avoidRadius || dist < 0.00001f) continue; float dot = item.Submarine.Velocity == Vector2.Zero ? 0.0f : Vector2.Dot(item.Submarine.Velocity, -Vector2.Normalize(diff)); @@ -241,16 +242,15 @@ namespace Barotrauma.Items.Components float otherSize = Math.Max(sub.Borders.Width, sub.Borders.Height); Vector2 diff = item.Submarine.WorldPosition - sub.WorldPosition; - float dist = diff == Vector2.Zero ? 0.0f : diff.Length(); //far enough -> ignore if (dist > thisSize + otherSize) continue; - diff = Vector2.Normalize(diff); + Vector2 dir = dist <= 0.0001f ? Vector2.UnitY : diff / dist; float dot = item.Submarine.Velocity == Vector2.Zero ? - 0.0f : Vector2.Dot(Vector2.Normalize(item.Submarine.Velocity), -Vector2.Normalize(diff)); + 0.0f : Vector2.Dot(Vector2.Normalize(item.Submarine.Velocity), -dir); //heading away -> ignore if (dot < 0.0f) continue; diff --git a/Barotrauma/BarotraumaShared/Source/Map/Explosion.cs b/Barotrauma/BarotraumaShared/Source/Map/Explosion.cs index 121fe5417..3280a3f51 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Explosion.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Explosion.cs @@ -180,6 +180,7 @@ namespace Barotrauma if (limb.WorldPosition != worldPosition && force > 0.0f) { Vector2 limbDiff = Vector2.Normalize(limb.WorldPosition - worldPosition); + if (!MathUtils.IsValid(limbDiff)) limbDiff = Rand.Vector(1.0f); Vector2 impulsePoint = limb.SimPosition - limbDiff * limbRadius; limb.body.ApplyLinearImpulse(limbDiff * distFactor * force, impulsePoint); } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index 7d7ce68e1..2304b34cd 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -919,7 +919,7 @@ namespace Barotrauma ConvertUnits.ToSimUnits(endPos), null, Physics.CollisionLevel) != null) { - position = ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition) + Vector2.Normalize(startPos - endPos)*offsetFromWall; + position = ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition) + Vector2.Normalize(startPos - endPos) * offsetFromWall; break; } diff --git a/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs index 94663b760..22d147ad4 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs @@ -214,7 +214,7 @@ namespace Barotrauma closestSub = Character.Controlled.Submarine; } - bool displace = moveAmount.Length() > 100.0f; + bool displace = moveAmount.LengthSquared() > 100.0f * 100.0f; foreach (Submarine sub in subsToMove) { sub.PhysicsBody.SetTransform(sub.PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(moveAmount), 0.0f); @@ -259,7 +259,7 @@ namespace Barotrauma Vector2 totalForce = CalculateBuoyancy(); - if (Body.LinearVelocity.LengthSquared() > 0.000001f) + if (Body.LinearVelocity.LengthSquared() > 0.0001f) { float dragCoefficient = 0.01f; @@ -285,6 +285,7 @@ namespace Barotrauma worldBorders.Location += MathUtils.ToPoint(ConvertUnits.ToDisplayUnits(Body.SimPosition)); Vector2 translateDir = Vector2.Normalize(subTranslation); + if (!MathUtils.IsValid(translateDir)) translateDir = Vector2.UnitY; foreach (Character c in Character.CharacterList) { @@ -384,7 +385,9 @@ namespace Barotrauma if (f2.UserData is VoronoiCell cell) { - HandleLevelCollision(contact, Vector2.Normalize(ConvertUnits.ToDisplayUnits(Body.SimPosition) - cell.Center)); + Vector2 collisionNormal = Vector2.Normalize(ConvertUnits.ToDisplayUnits(Body.SimPosition) - cell.Center); + if (!MathUtils.IsValid(collisionNormal)) collisionNormal = Rand.Vector(1.0f); + HandleLevelCollision(contact, collisionNormal); return true; } @@ -445,7 +448,9 @@ namespace Barotrauma { if (limb.Mass > 100.0f) { - Vector2 normal = Vector2.Normalize(Body.SimPosition - limb.SimPosition); + Vector2 normal = Vector2.DistanceSquared(Body.SimPosition, limb.SimPosition) < 0.0001f ? + Vector2.UnitY : + Vector2.Normalize(Body.SimPosition - limb.SimPosition); float impact = Math.Min(Vector2.Dot(Velocity - limb.LinearVelocity, -normal), 50.0f) / 5.0f * Math.Min(limb.Mass / 200.0f, 1); @@ -634,7 +639,10 @@ namespace Barotrauma float contactDot = Vector2.Dot(otherSub.PhysicsBody.LinearVelocity, -avgContactNormal); if (contactDot > 0.0f) { - otherSub.PhysicsBody.LinearVelocity -= Vector2.Normalize(otherSub.PhysicsBody.LinearVelocity) * contactDot; + if (otherSub.PhysicsBody.LinearVelocity.LengthSquared() > 0.0001f) + { + otherSub.PhysicsBody.LinearVelocity -= Vector2.Normalize(otherSub.PhysicsBody.LinearVelocity) * contactDot; + } impact = Vector2.Dot(otherSub.Velocity, normal); otherSub.SubBody.ApplyImpact(impact, normal, contact); diff --git a/Barotrauma/BarotraumaShared/Source/Map/TransitionCinematic.cs b/Barotrauma/BarotraumaShared/Source/Map/TransitionCinematic.cs index 60a9a8449..528862426 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/TransitionCinematic.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/TransitionCinematic.cs @@ -89,7 +89,9 @@ namespace Barotrauma foreach (Submarine sub in subs) { if (sub.Position == targetPos) continue; - sub.ApplyForce((Vector2.Normalize(targetPos - sub.Position) * targetSpeed - sub.Velocity) * 500.0f); + Vector2 dir = Vector2.Normalize(targetPos - sub.Position); + if (!MathUtils.IsValid(dir)) continue; + sub.ApplyForce((dir * targetSpeed - sub.Velocity) * 500.0f); } timer += CoroutineManager.UnscaledDeltaTime; diff --git a/Barotrauma/BarotraumaShared/Source/Networking/RespawnManager.cs b/Barotrauma/BarotraumaShared/Source/Networking/RespawnManager.cs index 3189a49e8..f5a526544 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/RespawnManager.cs @@ -362,8 +362,12 @@ namespace Barotrauma.Networking while (Math.Abs(position.Y - respawnShuttle.WorldPosition.Y) > 100.0f) { - Vector2 displayVel = Vector2.Normalize(position - respawnShuttle.WorldPosition) * speed; - respawnShuttle.SubBody.Body.LinearVelocity = ConvertUnits.ToSimUnits(displayVel); + Vector2 diff = position - respawnShuttle.WorldPosition; + if (diff.LengthSquared() > 0.01f) + { + Vector2 displayVel = Vector2.Normalize(diff) * speed; + respawnShuttle.SubBody.Body.LinearVelocity = ConvertUnits.ToSimUnits(displayVel); + } yield return CoroutineStatus.Running; if (respawnShuttle.SubBody == null) yield return CoroutineStatus.Success;