Added a bunch of checks to make sure a normalized zero vector (= NaN, NaN) is not used in any position/velocity/movement calculations. There were at least three places where it was causing problems according to error reports: when a character that can't enter a sub spawns at the center of a hull and when using an underwater scooter or throwing something while the cursor is at the position of the character, but there were tons of other places as well where it may have potentially caused physics errors.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user