(8e2e6e4da) Physics error prevention: - Use the ApplyForce/ApplyImpulse method overrides that clamp the resulting velocity to a value (in this case NetConfig.MaxPhysicsBodyVelocity, 64 m/s). Without this, explosions and attacks for example could apply arbitrarily large forces to bodies, causing physics errors in Ragdoll.CheckValidity. - Make sure angular velocity still has a sane value after applying an impulse to a specific point of a collider.
This commit is contained in:
@@ -1094,7 +1094,7 @@ namespace Barotrauma
|
||||
|
||||
if (flowForce.LengthSquared() > 0.001f)
|
||||
{
|
||||
Collider.ApplyForce(flowForce);
|
||||
Collider.ApplyForce(flowForce, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
|
||||
if (currentHull == null ||
|
||||
@@ -1132,7 +1132,7 @@ namespace Barotrauma
|
||||
|
||||
if (flowForce.LengthSquared() > 0.001f)
|
||||
{
|
||||
limb.body.ApplyForce(flowForce);
|
||||
limb.body.ApplyForce(flowForce, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
|
||||
surfaceY = limbHull.Surface;
|
||||
|
||||
@@ -2187,7 +2187,7 @@ namespace Barotrauma
|
||||
|
||||
if (limbHit == null) return new AttackResult();
|
||||
|
||||
limbHit.body?.ApplyLinearImpulse(attack.TargetImpulseWorld + attack.TargetForceWorld * deltaTime);
|
||||
limbHit.body?.ApplyLinearImpulse(attack.TargetImpulseWorld + attack.TargetForceWorld * deltaTime, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
#if SERVER
|
||||
if (attacker is Character attackingCharacter && attackingCharacter.AIController == null)
|
||||
{
|
||||
@@ -2273,7 +2273,8 @@ namespace Barotrauma
|
||||
{
|
||||
Vector2 diff = dir;
|
||||
if (diff == Vector2.Zero) diff = Rand.Vector(1.0f);
|
||||
hitLimb.body.ApplyLinearImpulse(Vector2.Normalize(diff) * attackImpulse, hitLimb.SimPosition + ConvertUnits.ToSimUnits(diff));
|
||||
hitLimb.body.ApplyLinearImpulse(Vector2.Normalize(diff) * attackImpulse, hitLimb.SimPosition + ConvertUnits.ToSimUnits(diff),
|
||||
maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
Vector2 simPos = hitLimb.SimPosition + ConvertUnits.ToSimUnits(dir);
|
||||
AttackResult attackResult = hitLimb.AddDamage(simPos, afflictions, playSound);
|
||||
@@ -2362,7 +2363,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
if (diff == Vector2.Zero) { continue; }
|
||||
limb.body.ApplyLinearImpulse(diff * 50.0f);
|
||||
limb.body.ApplyLinearImpulse(diff * 50.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
|
||||
ImplodeFX();
|
||||
|
||||
@@ -8,6 +8,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -625,13 +626,17 @@ namespace Barotrauma
|
||||
|
||||
Limb limb = character.AnimController.Limbs[limbIndex];
|
||||
Vector2 forcePos = limb.pullJoint == null ? limb.body.SimPosition : limb.pullJoint.WorldAnchorA;
|
||||
limb.body.ApplyLinearImpulse(limb.Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos);
|
||||
limb.body.ApplyLinearImpulse(limb.Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos,
|
||||
maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 forcePos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA;
|
||||
body.ApplyLinearImpulse(Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos);
|
||||
body.ApplyLinearImpulse(
|
||||
Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition),
|
||||
forcePos,
|
||||
maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
}
|
||||
return wasHit;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FarseerPhysics;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
@@ -168,7 +169,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
//recoil
|
||||
item.body.ApplyLinearImpulse(
|
||||
new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * item.body.Mass * -50.0f);
|
||||
new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * item.body.Mass * -50.0f,
|
||||
maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
|
||||
item.RemoveContained(projectile.Item);
|
||||
|
||||
|
||||
@@ -106,10 +106,10 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
Character thrower = picker;
|
||||
item.Drop(thrower, createNetworkEvent: GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer);
|
||||
item.body.ApplyLinearImpulse(throwVector * throwForce * item.body.Mass * 3.0f);
|
||||
item.body.ApplyLinearImpulse(throwVector * throwForce * item.body.Mass * 3.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
|
||||
ac.GetLimb(LimbType.Head).body.ApplyLinearImpulse(throwVector*10.0f);
|
||||
ac.GetLimb(LimbType.Torso).body.ApplyLinearImpulse(throwVector * 10.0f);
|
||||
ac.GetLimb(LimbType.Head).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
ac.GetLimb(LimbType.Torso).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
|
||||
Limb rightHand = ac.GetLimb(LimbType.RightHand);
|
||||
item.body.AngularVelocity = rightHand.body.AngularVelocity;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FarseerPhysics;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Contacts;
|
||||
using FarseerPhysics.Dynamics.Joints;
|
||||
@@ -176,7 +177,7 @@ namespace Barotrauma.Items.Components
|
||||
item.Drop(null);
|
||||
|
||||
item.body.Enabled = true;
|
||||
item.body.ApplyLinearImpulse(impulse);
|
||||
item.body.ApplyLinearImpulse(impulse, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
|
||||
item.body.FarseerBody.OnCollision += OnProjectileCollision;
|
||||
item.body.FarseerBody.IsBullet = true;
|
||||
|
||||
@@ -26,6 +26,10 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float blinkTimer;
|
||||
|
||||
private bool itemLoaded;
|
||||
|
||||
private float blinkTimer;
|
||||
|
||||
public PhysicsBody ParentBody;
|
||||
|
||||
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 2048.0f), Serialize(100.0f, true)]
|
||||
|
||||
@@ -1134,7 +1134,7 @@ namespace Barotrauma
|
||||
|
||||
Vector2 drag = body.LinearVelocity * volume;
|
||||
|
||||
body.ApplyForce((uplift - drag) * 10.0f);
|
||||
body.ApplyForce((uplift - drag) * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
|
||||
//apply simple angular drag
|
||||
body.ApplyTorque(body.AngularVelocity * volume * -0.05f);
|
||||
|
||||
@@ -236,8 +236,9 @@ namespace Barotrauma
|
||||
{
|
||||
Vector2 limbDiff = Vector2.Normalize(limb.WorldPosition - worldPosition);
|
||||
if (!MathUtils.IsValid(limbDiff)) limbDiff = Rand.Vector(1.0f);
|
||||
Vector2 impulse = limbDiff * distFactor * force;
|
||||
Vector2 impulsePoint = limb.SimPosition - limbDiff * limbRadius;
|
||||
limb.body.ApplyLinearImpulse(limbDiff * distFactor * force, impulsePoint);
|
||||
limb.body.ApplyLinearImpulse(impulse, impulsePoint, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -561,17 +561,14 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var gap in ConnectedGaps.Where(gap => gap.Open > 0))
|
||||
{
|
||||
//var pos = gap.Position - body.Position;
|
||||
var distance = MathHelper.Max(Vector2.DistanceSquared(item.Position, gap.Position)/1000, 1f);
|
||||
|
||||
//pos.Normalize();
|
||||
item.body.ApplyForce((gap.LerpedFlowForce/distance) * deltaTime);
|
||||
var distance = MathHelper.Max(Vector2.DistanceSquared(item.Position, gap.Position) / 1000, 1f);
|
||||
item.body.ApplyForce((gap.LerpedFlowForce / distance) * deltaTime, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
}
|
||||
|
||||
public void Extinguish(float deltaTime, float amount, Vector2 position)
|
||||
{
|
||||
for (int i = FireSources.Count - 1; i >= 0; i-- )
|
||||
for (int i = FireSources.Count - 1; i >= 0; i--)
|
||||
{
|
||||
FireSources[i].Extinguish(deltaTime, amount, position);
|
||||
}
|
||||
|
||||
@@ -543,19 +543,19 @@ namespace Barotrauma
|
||||
if (ForceVelocityLimit < 1000.0f)
|
||||
body.ApplyForce(Force * currentForceFluctuation * distFactor, ForceVelocityLimit);
|
||||
else
|
||||
body.ApplyForce(Force * currentForceFluctuation * distFactor);
|
||||
body.ApplyForce(Force * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
break;
|
||||
case TriggerForceMode.Acceleration:
|
||||
if (ForceVelocityLimit < 1000.0f)
|
||||
body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor, ForceVelocityLimit);
|
||||
else
|
||||
body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor);
|
||||
body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
break;
|
||||
case TriggerForceMode.Impulse:
|
||||
if (ForceVelocityLimit < 1000.0f)
|
||||
body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, ForceVelocityLimit);
|
||||
body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, maxVelocity: ForceVelocityLimit);
|
||||
else
|
||||
body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor);
|
||||
body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
break;
|
||||
case TriggerForceMode.LimitVelocity:
|
||||
float maxVel = ForceVelocityLimit * currentForceFluctuation * distFactor;
|
||||
@@ -563,7 +563,8 @@ namespace Barotrauma
|
||||
{
|
||||
body.ApplyForce(
|
||||
Vector2.Normalize(-body.LinearVelocity) *
|
||||
Force.Length() * body.Mass * currentForceFluctuation * distFactor);
|
||||
Force.Length() * body.Mass * currentForceFluctuation * distFactor,
|
||||
maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -587,11 +587,16 @@ namespace Barotrauma
|
||||
if (!IsValidValue(impulse / body.Mass, "new velocity")) return;
|
||||
if (!IsValidValue(impulse, "impulse", -1e10f, 1e10f)) return;
|
||||
if (!IsValidValue(maxVelocity, "max velocity")) return;
|
||||
|
||||
float currSpeed = body.LinearVelocity.Length();
|
||||
|
||||
Vector2 velocityAddition = impulse / Mass;
|
||||
Vector2 newVelocity = body.LinearVelocity + velocityAddition;
|
||||
newVelocity = newVelocity.ClampLength(Math.Max(currSpeed, maxVelocity));
|
||||
float newSpeedSqr = newVelocity.LengthSquared();
|
||||
if (newSpeedSqr > maxVelocity * maxVelocity)
|
||||
{
|
||||
newVelocity = newVelocity.ClampLength(maxVelocity);
|
||||
}
|
||||
|
||||
if (!IsValidValue((newVelocity - body.LinearVelocity), "new velocity", -1000.0f, 1000.0f)) return;
|
||||
|
||||
body.ApplyLinearImpulse((newVelocity - body.LinearVelocity) * Mass);
|
||||
}
|
||||
@@ -600,10 +605,36 @@ namespace Barotrauma
|
||||
{
|
||||
if (!IsValidValue(impulse, "impulse", -1e10f, 1e10f)) return;
|
||||
if (!IsValidValue(point, "point")) return;
|
||||
if (!IsValidValue(impulse / body.Mass, "new velocity")) return;
|
||||
if (!IsValidValue(impulse / body.Mass, "new velocity", -1000.0f, 1000.0f)) return;
|
||||
body.ApplyLinearImpulse(impulse, point);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply an impulse to the body without increasing it's velocity above a specific limit.
|
||||
/// </summary>
|
||||
public void ApplyLinearImpulse(Vector2 impulse, Vector2 point, float maxVelocity)
|
||||
{
|
||||
if (!IsValidValue(impulse, "impulse", -1e10f, 1e10f)) return;
|
||||
if (!IsValidValue(point, "point")) return;
|
||||
if (!IsValidValue(maxVelocity, "max velocity")) return;
|
||||
|
||||
Vector2 velocityAddition = impulse / Mass;
|
||||
Vector2 newVelocity = body.LinearVelocity + velocityAddition;
|
||||
float newSpeedSqr = newVelocity.LengthSquared();
|
||||
if (newSpeedSqr > maxVelocity * maxVelocity)
|
||||
{
|
||||
newVelocity = newVelocity.ClampLength(maxVelocity);
|
||||
}
|
||||
|
||||
if (!IsValidValue((newVelocity - body.LinearVelocity), "new velocity", -1000.0f, 1000.0f)) return;
|
||||
|
||||
body.ApplyLinearImpulse((newVelocity - body.LinearVelocity) * Mass, point);
|
||||
body.AngularVelocity = MathHelper.Clamp(
|
||||
body.AngularVelocity,
|
||||
-NetConfig.MaxPhysicsBodyAngularVelocity,
|
||||
NetConfig.MaxPhysicsBodyAngularVelocity);
|
||||
}
|
||||
|
||||
public void ApplyForce(Vector2 force)
|
||||
{
|
||||
if (!IsValidValue(force, "force", -1e10f, 1e10f)) return;
|
||||
@@ -618,11 +649,14 @@ namespace Barotrauma
|
||||
if (!IsValidValue(force, "force", -1e10f, 1e10f)) return;
|
||||
if (!IsValidValue(maxVelocity, "max velocity")) return;
|
||||
|
||||
float currSpeed = body.LinearVelocity.Length();
|
||||
Vector2 velocityAddition = force / Mass * (float)Timing.Step;
|
||||
Vector2 newVelocity = body.LinearVelocity + velocityAddition;
|
||||
newVelocity = newVelocity.ClampLength(Math.Max(currSpeed, maxVelocity));
|
||||
|
||||
|
||||
float newSpeedSqr = newVelocity.LengthSquared();
|
||||
if (newSpeedSqr > maxVelocity * maxVelocity)
|
||||
{
|
||||
newVelocity = newVelocity.ClampLength(maxVelocity);
|
||||
}
|
||||
body.ApplyForce((newVelocity - body.LinearVelocity) * Mass / (float)Timing.Step);
|
||||
}
|
||||
|
||||
@@ -725,17 +759,19 @@ namespace Barotrauma
|
||||
|
||||
Vector2 dragForce = Vector2.Zero;
|
||||
|
||||
if (LinearVelocity.LengthSquared() > 0.00001f)
|
||||
float speedSqr = LinearVelocity.LengthSquared();
|
||||
if (speedSqr > 0.00001f)
|
||||
{
|
||||
//drag
|
||||
Vector2 velDir = Vector2.Normalize(LinearVelocity);
|
||||
float speed = (float)Math.Sqrt(speedSqr);
|
||||
Vector2 velDir = LinearVelocity / speed;
|
||||
|
||||
float vel = LinearVelocity.Length() * 2.0f;
|
||||
float vel = speed * 2.0f;
|
||||
float drag = vel * vel * Math.Max(height + radius * 2, height);
|
||||
dragForce = Math.Min(drag, Mass * 500.0f) * -velDir;
|
||||
dragForce = Math.Min(drag, Mass * 500.0f) * -velDir;
|
||||
}
|
||||
|
||||
ApplyForce(dragForce + buoyancy);
|
||||
ApplyForce(dragForce + buoyancy, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
ApplyTorque(body.AngularVelocity * body.Mass * -0.08f);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user