(5a377a8ee) Unstable v0.9.1000.0
This commit is contained in:
@@ -55,7 +55,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (limbs == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Attempted to access a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this));
|
||||
string errorMsg = "Attempted to access a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this);
|
||||
#if DEBUG || UNSTABLE
|
||||
errorMsg += '\n' + Environment.StackTrace;
|
||||
#endif
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"Ragdoll.Limbs:AccessRemoved",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
@@ -80,7 +84,7 @@ namespace Barotrauma
|
||||
frozen = value;
|
||||
|
||||
Collider.FarseerBody.LinearDamping = frozen ? (1.5f / (float)Timing.Step) : 0.0f;
|
||||
Collider.FarseerBody.AngularDamping = frozen ? (1.5f / (float)Timing.Step) : 0.0f;
|
||||
Collider.FarseerBody.AngularDamping = frozen ? (1.5f / (float)Timing.Step) : PhysicsBody.DefaultAngularDamping;
|
||||
Collider.FarseerBody.IgnoreGravity = frozen;
|
||||
|
||||
//Collider.PhysEnabled = !frozen;
|
||||
@@ -93,12 +97,17 @@ namespace Barotrauma
|
||||
|
||||
private bool simplePhysicsEnabled;
|
||||
|
||||
public Character Character => character;
|
||||
protected Character character;
|
||||
|
||||
protected float strongestImpact;
|
||||
|
||||
private float splashSoundTimer;
|
||||
|
||||
//the ragdoll builds a "tolerance" to the flow force when being pushed by water.
|
||||
//Allows sudden forces (breach, letting water through a door) to heavily push the character around while ensuring flowing water won't make the characters permanently stuck.
|
||||
private float flowForceTolerance, flowStunTolerance;
|
||||
|
||||
//the movement speed of the ragdoll
|
||||
public Vector2 movement;
|
||||
//the target speed towards which movement is interpolated
|
||||
@@ -152,8 +161,8 @@ namespace Barotrauma
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == colliderIndex || collider == null) return;
|
||||
if (value >= collider.Count || value < 0) return;
|
||||
if (value == colliderIndex || collider == null) { return; }
|
||||
if (value >= collider.Count || value < 0) { return; }
|
||||
|
||||
if (collider[colliderIndex].height < collider[value].height)
|
||||
{
|
||||
@@ -161,10 +170,9 @@ namespace Barotrauma
|
||||
pos1.Y -= collider[colliderIndex].height * ColliderHeightFromFloor;
|
||||
Vector2 pos2 = pos1;
|
||||
pos2.Y += collider[value].height * 1.1f;
|
||||
if (GameMain.World.RayCast(pos1, pos2).Any(f => f.CollisionCategories.HasFlag(Physics.CollisionWall))) return;
|
||||
if (GameMain.World.RayCast(pos1, pos2).Any(f => f.CollisionCategories.HasFlag(Physics.CollisionWall))) { return; }
|
||||
}
|
||||
|
||||
|
||||
Vector2 pos = collider[colliderIndex].SimPosition;
|
||||
pos.Y -= collider[colliderIndex].height * 0.5f;
|
||||
pos.Y += collider[value].height * 0.5f;
|
||||
@@ -212,7 +220,7 @@ namespace Barotrauma
|
||||
mainLimb = torso ?? head;
|
||||
if (mainLimb == null)
|
||||
{
|
||||
mainLimb = Limbs.FirstOrDefault();
|
||||
mainLimb = Limbs.FirstOrDefault(l => !l.IsSevered && !l.ignoreCollisions);
|
||||
}
|
||||
}
|
||||
return mainLimb;
|
||||
@@ -234,13 +242,13 @@ namespace Barotrauma
|
||||
get { return simplePhysicsEnabled; }
|
||||
set
|
||||
{
|
||||
if (value == simplePhysicsEnabled) return;
|
||||
if (value == simplePhysicsEnabled) { return; }
|
||||
|
||||
simplePhysicsEnabled = value;
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) continue;
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (limb.body == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Limb has no body! (" + (character != null ? character.Name : "Unknown character") + ", " + limb.type.ToString());
|
||||
@@ -292,8 +300,6 @@ namespace Barotrauma
|
||||
public float ImpactTolerance => RagdollParams.ImpactTolerance;
|
||||
public bool Draggable => RagdollParams.Draggable;
|
||||
public bool CanEnterSubmarine => RagdollParams.CanEnterSubmarine;
|
||||
public bool CanAttackSubmarine => Limbs.Any(l => l.attack != null && l.attack.IsValidTarget(AttackTarget.Structure));
|
||||
public bool CanAttackCharacters => Limbs.Any(l => l.attack != null && l.attack.IsValidTarget(AttackTarget.Character));
|
||||
|
||||
public float Dir => dir == Direction.Left ? -1.0f : 1.0f;
|
||||
|
||||
@@ -320,6 +326,7 @@ namespace Barotrauma
|
||||
Submarine currSubmarine = currentHull?.Submarine;
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
limb.body.Submarine = currSubmarine;
|
||||
}
|
||||
Collider.Submarine = currSubmarine;
|
||||
@@ -373,7 +380,7 @@ namespace Barotrauma
|
||||
foreach (var kvp in items)
|
||||
{
|
||||
int id = kvp.Key.ID;
|
||||
// This can be the case if we manipulate the ragdoll in runtime (husk appendage, limb severance)
|
||||
// This can be the case if we manipulate the ragdoll at runtime (husk appendage, limb removal in the character editor)
|
||||
if (id > limbs.Length - 1) { continue; }
|
||||
var limb = limbs[id];
|
||||
var itemList = kvp.Value;
|
||||
@@ -633,10 +640,7 @@ namespace Barotrauma
|
||||
Vector2 colliderBottom = GetColliderBottom();
|
||||
if (structure.IsPlatform)
|
||||
{
|
||||
if (IgnorePlatforms) { return false; }
|
||||
|
||||
//the collision is ignored if the lowest limb is under the platform
|
||||
//if (lowestLimb==null || lowestLimb.Position.Y < structure.Rect.Y) return false;
|
||||
if (IgnorePlatforms || currentHull == null) { return false; }
|
||||
|
||||
if (colliderBottom.Y < ConvertUnits.ToSimUnits(structure.Rect.Y - 5)) { return false; }
|
||||
if (f1.Body.Position.Y < ConvertUnits.ToSimUnits(structure.Rect.Y - 5)) { return false; }
|
||||
@@ -719,12 +723,14 @@ namespace Barotrauma
|
||||
|
||||
ImpactProjSpecific(impact, f1.Body);
|
||||
}
|
||||
|
||||
public void SeverLimbJoint(LimbJoint limbJoint, bool playSound = true)
|
||||
|
||||
private readonly List<Limb> connectedLimbs = new List<Limb>();
|
||||
private readonly List<LimbJoint> checkedJoints = new List<LimbJoint>();
|
||||
public bool SeverLimbJoint(LimbJoint limbJoint, bool playSound = true)
|
||||
{
|
||||
if (!limbJoint.CanBeSevered || limbJoint.IsSevered)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
limbJoint.IsSevered = true;
|
||||
@@ -737,9 +743,8 @@ namespace Barotrauma
|
||||
limbJoint.LimbA.body.ApplyLinearImpulse(limbDiff * mass, (limbJoint.LimbA.SimPosition + limbJoint.LimbB.SimPosition) / 2.0f);
|
||||
limbJoint.LimbB.body.ApplyLinearImpulse(-limbDiff * mass, (limbJoint.LimbA.SimPosition + limbJoint.LimbB.SimPosition) / 2.0f);
|
||||
|
||||
List<Limb> connectedLimbs = new List<Limb>();
|
||||
List<LimbJoint> checkedJoints = new List<LimbJoint>();
|
||||
|
||||
connectedLimbs.Clear();
|
||||
checkedJoints.Clear();
|
||||
GetConnectedLimbs(connectedLimbs, checkedJoints, MainLimb);
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
@@ -748,11 +753,11 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
SeverLimbJointProjSpecific(limbJoint, playSound: true);
|
||||
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(character, new object[] { NetEntityEvent.Type.Status });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
partial void SeverLimbJointProjSpecific(LimbJoint limbJoint, bool playSound);
|
||||
@@ -763,7 +768,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (LimbJoint joint in LimbJoints)
|
||||
{
|
||||
if (joint.IsSevered || checkedJoints.Contains(joint)) continue;
|
||||
if (joint.IsSevered || checkedJoints.Contains(joint)) { continue; }
|
||||
if (joint.LimbA == limb)
|
||||
{
|
||||
if (!connectedLimbs.Contains(joint.LimbB))
|
||||
@@ -860,7 +865,7 @@ namespace Barotrauma
|
||||
{
|
||||
for (int i = 0; i < Limbs.Length; i++)
|
||||
{
|
||||
if (Limbs[i] == null) continue;
|
||||
if (Limbs[i] == null) { continue; }
|
||||
Limbs[i].PullJointEnabled = false;
|
||||
}
|
||||
}
|
||||
@@ -966,8 +971,8 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
if (character.Position.X < gap.Rect.X || character.Position.X > gap.Rect.Right) continue;
|
||||
if (Math.Sign((gap.Rect.Y - gap.Rect.Height / 2) - (currentHull.Rect.Center.Y - currentHull.Rect.Height / 2)) !=
|
||||
Math.Sign(character.Position.Y - (currentHull.Rect.Center.Y - currentHull.Rect.Height / 2)))
|
||||
if (Math.Sign((gap.Rect.Y - gap.Rect.Height / 2) - (currentHull.Rect.Y - currentHull.Rect.Height / 2)) !=
|
||||
Math.Sign(character.Position.Y - (currentHull.Rect.Y - currentHull.Rect.Height / 2)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -981,8 +986,8 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) continue;
|
||||
if (limb.body.FarseerBody.ContactList == null) continue;
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (limb.body.FarseerBody.ContactList == null) { continue; }
|
||||
|
||||
ContactEdge ce = limb.body.FarseerBody.ContactList;
|
||||
while (ce != null && ce.Contact != null)
|
||||
@@ -994,7 +999,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) continue;
|
||||
if (limb.IsSevered) { continue; }
|
||||
limb.body.LinearVelocity += velocityChange;
|
||||
}
|
||||
|
||||
@@ -1019,15 +1024,15 @@ namespace Barotrauma
|
||||
Category collisionCategory = (IgnorePlatforms) ?
|
||||
wall | Physics.CollisionProjectile | Physics.CollisionStairs
|
||||
: wall | Physics.CollisionProjectile | Physics.CollisionPlatform | Physics.CollisionStairs;
|
||||
|
||||
if (collisionCategory == prevCollisionCategory) return;
|
||||
|
||||
if (collisionCategory == prevCollisionCategory) { return; }
|
||||
prevCollisionCategory = collisionCategory;
|
||||
|
||||
Collider.CollidesWith = collisionCategory | Physics.CollisionItemBlocking;
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.ignoreCollisions || limb.IsSevered) continue;
|
||||
if (limb.ignoreCollisions || limb.IsSevered) { continue; }
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1080,8 +1085,6 @@ namespace Barotrauma
|
||||
CheckDistFromCollider();
|
||||
UpdateCollisionCategories();
|
||||
|
||||
Vector2 flowForce = Vector2.Zero;
|
||||
|
||||
FindHull();
|
||||
PreventOutsideCollision();
|
||||
|
||||
@@ -1103,10 +1106,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
flowForce = GetFlowForce();
|
||||
|
||||
headInWater = false;
|
||||
|
||||
inWater = false;
|
||||
if (currentHull.WaterVolume > currentHull.Volume * 0.95f)
|
||||
{
|
||||
@@ -1128,7 +1128,7 @@ namespace Barotrauma
|
||||
if (lowerHull != null) floorY = ConvertUnits.ToSimUnits(lowerHull.Rect.Y - lowerHull.Rect.Height);
|
||||
}
|
||||
}
|
||||
float standHeight =
|
||||
float standHeight =
|
||||
HeadPosition.HasValue ? HeadPosition.Value :
|
||||
TorsoPosition.HasValue ? TorsoPosition.Value :
|
||||
Collider.GetMaxExtent() * 0.5f;
|
||||
@@ -1139,10 +1139,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (flowForce.LengthSquared() > 0.001f)
|
||||
{
|
||||
Collider.ApplyForce(flowForce, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
UpdateHullFlowForces(deltaTime);
|
||||
|
||||
if (currentHull == null ||
|
||||
currentHull.WaterVolume > currentHull.Volume * 0.95f ||
|
||||
@@ -1151,7 +1148,6 @@ namespace Barotrauma
|
||||
Collider.ApplyWaterForces();
|
||||
}
|
||||
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
//find the room which the limb is in
|
||||
@@ -1176,14 +1172,7 @@ namespace Barotrauma
|
||||
if (limb.Position.Y < limbHull.Surface)
|
||||
{
|
||||
limb.inWater = true;
|
||||
|
||||
if (flowForce.LengthSquared() > 0.001f)
|
||||
{
|
||||
limb.body.ApplyForce(flowForce, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
|
||||
surfaceY = limbHull.Surface;
|
||||
|
||||
if (limb.type == LimbType.Head)
|
||||
{
|
||||
headInWater = true;
|
||||
@@ -1228,6 +1217,8 @@ namespace Barotrauma
|
||||
|
||||
private void CheckBodyInRest(float deltaTime)
|
||||
{
|
||||
if (SimplePhysicsEnabled) { return; }
|
||||
|
||||
if (InWater || Collider.LinearVelocity.LengthSquared() > 0.01f || character.SelectedBy != null || !character.IsDead)
|
||||
{
|
||||
bodyInRestTimer = 0.0f;
|
||||
@@ -1253,6 +1244,12 @@ namespace Barotrauma
|
||||
private int validityResets;
|
||||
private bool CheckValidity()
|
||||
{
|
||||
if (limbs == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Attempted to check the validity of a potentially removed ragdoll. Character: " + character.Name + ", id: " + character.ID + ", removed: " + character.Removed + ", ragdoll removed: " + !list.Contains(this));
|
||||
Invalid = true;
|
||||
return false;
|
||||
}
|
||||
bool isColliderValid = CheckValidity(Collider);
|
||||
bool limbsValid = true;
|
||||
foreach (Limb limb in limbs)
|
||||
@@ -1275,8 +1272,8 @@ namespace Barotrauma
|
||||
Collider.SetTransform(Vector2.Zero, 0.0f);
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
limb.body.SetTransform(Collider.SimPosition, 0.0f);
|
||||
limb.body.ResetDynamics();
|
||||
limb.body?.SetTransform(Collider.SimPosition, 0.0f);
|
||||
limb.body?.ResetDynamics();
|
||||
}
|
||||
Frozen = true;
|
||||
}
|
||||
@@ -1350,6 +1347,74 @@ namespace Barotrauma
|
||||
|
||||
partial void Splash(Limb limb, Hull limbHull);
|
||||
|
||||
private void UpdateHullFlowForces(float deltaTime)
|
||||
{
|
||||
if (currentHull == null) { return; }
|
||||
|
||||
const float StunForceThreshold = 5.0f;
|
||||
const float StunDuration = 0.5f;
|
||||
const float ToleranceIncreaseSpeed = 5.0f;
|
||||
const float ToleranceDecreaseSpeed = 1.0f;
|
||||
|
||||
//how much distance to a gap affects the force it exerts on the character
|
||||
const float DistanceFactor = 0.5f;
|
||||
const float ForceMultiplier = 0.035f;
|
||||
|
||||
Vector2 flowForce = Vector2.Zero;
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
if (gap.Open <= 0.0f || !gap.linkedTo.Contains(currentHull) || gap.LerpedFlowForce.LengthSquared() < 0.01f) { continue; }
|
||||
float dist = Vector2.Distance(MainLimb.WorldPosition, gap.WorldPosition) * DistanceFactor;
|
||||
flowForce += Vector2.Normalize(gap.LerpedFlowForce) * (Math.Max(gap.LerpedFlowForce.Length() - dist, 0.0f) * ForceMultiplier);
|
||||
}
|
||||
|
||||
//throwing conscious/moving characters around takes more force -> double the flow force
|
||||
if (character.CanMove) { flowForce *= 2.0f; }
|
||||
|
||||
float flowForceMagnitude = flowForce.Length();
|
||||
float limbMultipier = limbs.Count(l => l.inWater) / (float)limbs.Length;
|
||||
//if the force strong enough, stun the character to let it get thrown around by the water
|
||||
if ((flowForceMagnitude * limbMultipier) - flowStunTolerance > StunForceThreshold)
|
||||
{
|
||||
character.Stun = Math.Max(character.Stun, StunDuration);
|
||||
flowStunTolerance = Math.Max(flowStunTolerance, flowForceMagnitude);
|
||||
}
|
||||
|
||||
if (character == Character.Controlled && inWater && Screen.Selected?.Cam != null)
|
||||
{
|
||||
float shakeStrength = Math.Min(flowForceMagnitude / 10.0f, 5.0f) * limbMultipier;
|
||||
Screen.Selected.Cam.Shake = Math.Max(Screen.Selected.Cam.Shake, shakeStrength);
|
||||
}
|
||||
|
||||
if (flowForceMagnitude > 0.0001f)
|
||||
{
|
||||
flowForce = Vector2.Normalize(flowForce) * Math.Max(flowForceMagnitude - flowForceTolerance, 0.0f);
|
||||
}
|
||||
|
||||
if (flowForceTolerance <= flowForceMagnitude * 1.5f && inWater)
|
||||
{
|
||||
//build up "tolerance" to the flow force
|
||||
//ensures the character won't get permanently stuck by forces, while allowing sudden changes in flow to push the character hard
|
||||
flowForceTolerance += deltaTime * ToleranceIncreaseSpeed;
|
||||
flowStunTolerance = Math.Max(flowStunTolerance, flowForceTolerance);
|
||||
}
|
||||
else
|
||||
{
|
||||
flowForceTolerance = Math.Max(flowForceTolerance - deltaTime * ToleranceDecreaseSpeed, 0.0f);
|
||||
flowStunTolerance = Math.Max(flowStunTolerance - deltaTime * ToleranceDecreaseSpeed, 0.0f);
|
||||
}
|
||||
|
||||
if (flowForce.LengthSquared() > 0.001f)
|
||||
{
|
||||
Collider.ApplyForce(flowForce, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
foreach (Limb limb in limbs)
|
||||
{
|
||||
if (!limb.inWater) { continue; }
|
||||
limb.body.ApplyForce(flowForce, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshFloorY(Limb refLimb = null, bool ignoreStairs = false)
|
||||
{
|
||||
PhysicsBody refBody = refLimb == null ? Collider : refLimb.body;
|
||||
@@ -1487,7 +1552,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) continue;
|
||||
if (limb.IsSevered) { continue; }
|
||||
//check visibility from the new position of the collider to the new position of this limb
|
||||
Vector2 movePos = limb.SimPosition + limbMoveAmount;
|
||||
|
||||
@@ -1551,7 +1616,7 @@ namespace Barotrauma
|
||||
Vector2 forceDir = diff / (float)Math.Sqrt(distSqrd);
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) continue;
|
||||
if (limb.IsSevered) { continue; }
|
||||
limb.body.CollidesWith = Physics.CollisionNone;
|
||||
limb.body.ApplyForce(forceDir * limb.Mass * 10.0f, maxVelocity: 10.0f);
|
||||
}
|
||||
@@ -1597,28 +1662,37 @@ namespace Barotrauma
|
||||
UpdateNetPlayerPositionProjSpecific(deltaTime, lowestSubPos);
|
||||
}
|
||||
|
||||
private Vector2 GetFlowForce()
|
||||
{
|
||||
Vector2 limbPos = Limbs[0].Position;
|
||||
|
||||
Vector2 force = Vector2.Zero;
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
if (gap.Open <= 0.0f || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce.LengthSquared() < 0.01f) continue;
|
||||
|
||||
Vector2 gapPos = gap.SimPosition;
|
||||
float dist = Vector2.Distance(limbPos, gapPos);
|
||||
force += Vector2.Normalize(gap.LerpedFlowForce) * (Math.Max(gap.LerpedFlowForce.Length() - dist, 0.0f) / 500.0f);
|
||||
}
|
||||
return force;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Note that if there are multiple limbs of the same type, only the first of them is found in the dictionary.
|
||||
/// </summary>
|
||||
public Limb GetLimb(LimbType limbType)
|
||||
public Limb GetLimb(LimbType limbType, bool excludeSevered = true)
|
||||
{
|
||||
limbDictionary.TryGetValue(limbType, out Limb limb);
|
||||
Limb limb = null;
|
||||
if (HasMultipleLimbsOfSameType)
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
limbDictionary.TryGetValue(limbType, out limb);
|
||||
if (limb == null)
|
||||
{
|
||||
// No limbs found
|
||||
break;
|
||||
}
|
||||
if (!excludeSevered || !limb.IsSevered)
|
||||
{
|
||||
// Found a valid limb
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
limbDictionary.TryGetValue(limbType, out limb);
|
||||
}
|
||||
if (excludeSevered && limb != null && limb.IsSevered)
|
||||
{
|
||||
limb = null;
|
||||
}
|
||||
return limb;
|
||||
}
|
||||
|
||||
@@ -1661,10 +1735,15 @@ namespace Barotrauma
|
||||
Limb lowestLimb = null;
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (lowestLimb == null)
|
||||
{
|
||||
lowestLimb = limb;
|
||||
}
|
||||
else if (limb.SimPosition.Y < lowestLimb.SimPosition.Y)
|
||||
{
|
||||
lowestLimb = limb;
|
||||
}
|
||||
}
|
||||
|
||||
return lowestLimb;
|
||||
|
||||
Reference in New Issue
Block a user