(5a377a8ee) Unstable v0.9.1000.0
This commit is contained in:
@@ -76,7 +76,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (InWater || !CanWalk)
|
||||
{
|
||||
return TargetMovement.Length() > (SwimSlowParams.MovementSpeed + SwimFastParams.MovementSpeed) / 2.0f;
|
||||
float avg = (SwimSlowParams.MovementSpeed + SwimFastParams.MovementSpeed) / 2.0f;
|
||||
return TargetMovement.LengthSquared() > avg * avg;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+45
-19
@@ -213,7 +213,12 @@ namespace Barotrauma
|
||||
UpdateWalkAnim(deltaTime);
|
||||
}
|
||||
|
||||
//don't flip or drag when simply physics is enabled
|
||||
if (character.SelectedCharacter != null)
|
||||
{
|
||||
DragCharacter(character.SelectedCharacter, deltaTime);
|
||||
}
|
||||
|
||||
//don't flip when simply physics is enabled
|
||||
if (SimplePhysicsEnabled) { return; }
|
||||
|
||||
if (!character.IsRemotePlayer && (character.AIController == null || character.AIController.CanFlip))
|
||||
@@ -248,29 +253,33 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (character.SelectedCharacter != null)
|
||||
{
|
||||
DragCharacter(character.SelectedCharacter, deltaTime);
|
||||
}
|
||||
|
||||
if (!CurrentFishAnimation.Flip) { return; }
|
||||
if (IsStuck) { return; }
|
||||
if (character.AIController != null && !character.AIController.CanFlip) { return; }
|
||||
|
||||
flipCooldown -= deltaTime;
|
||||
|
||||
if (TargetDir != Direction.None && TargetDir != dir)
|
||||
if (TargetDir != Direction.None && TargetDir != dir)
|
||||
{
|
||||
flipTimer += deltaTime;
|
||||
if ((flipTimer > 0.5f && flipCooldown <= 0.0f) || character.IsRemotePlayer)
|
||||
// Speed reductions are not taken into account here. It's intentional: an ai character cannot flip if it's heavily paralyzed (for example).
|
||||
float requiredSpeed = CurrentAnimationParams.MovementSpeed / 2;
|
||||
if (CurrentHull != null)
|
||||
{
|
||||
// Enemy movement speeds are halved inside submarines
|
||||
requiredSpeed /= 2;
|
||||
}
|
||||
bool isMovingFastEnough = Math.Abs(MainLimb.LinearVelocity.X) > requiredSpeed;
|
||||
bool isTryingToMoveHorizontally = Math.Abs(TargetMovement.X) > Math.Abs(TargetMovement.Y);
|
||||
if ((flipTimer > CurrentFishAnimation.FlipDelay && flipCooldown <= 0.0f && ((isMovingFastEnough && isTryingToMoveHorizontally) || IsMovingBackwards))
|
||||
|| character.IsRemotePlayer)
|
||||
{
|
||||
Flip();
|
||||
if (!inWater || (CurrentSwimParams != null && CurrentSwimParams.Mirror))
|
||||
{
|
||||
Mirror();
|
||||
Mirror(CurrentSwimParams != null ? CurrentSwimParams.MirrorLerp : true);
|
||||
}
|
||||
flipTimer = 0.0f;
|
||||
flipCooldown = 1.0f;
|
||||
flipCooldown = CurrentFishAnimation.FlipCooldown;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -295,7 +304,7 @@ namespace Barotrauma
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
//stop dragging if there's something between the pull limb and the target
|
||||
Vector2 sourceSimPos = mouthLimb.SimPosition;
|
||||
Vector2 sourceSimPos = SimplePhysicsEnabled ? character.SimPosition : mouthLimb.SimPosition;
|
||||
Vector2 targetSimPos = target.SimPosition;
|
||||
if (character.Submarine != null && character.SelectedCharacter.Submarine == null)
|
||||
{
|
||||
@@ -317,7 +326,7 @@ namespace Barotrauma
|
||||
float eatSpeed = dmg / ((float)Math.Sqrt(Math.Max(target.Mass, 1)) * 10);
|
||||
eatTimer += deltaTime * eatSpeed;
|
||||
|
||||
Vector2 mouthPos = GetMouthPosition().Value;
|
||||
Vector2 mouthPos = SimplePhysicsEnabled ? character.SimPosition : GetMouthPosition().Value;
|
||||
Vector2 attackSimPosition = character.Submarine == null ? ConvertUnits.ToSimUnits(target.WorldPosition) : target.SimPosition;
|
||||
|
||||
Vector2 limbDiff = attackSimPosition - mouthPos;
|
||||
@@ -525,6 +534,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (var limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (Math.Abs(limb.Params.ConstantTorque) > 0)
|
||||
{
|
||||
limb.body.SmoothRotate(movementAngle + MathHelper.ToRadians(limb.Params.ConstantAngle) * Dir, limb.Params.ConstantTorque, wrapAngle: true);
|
||||
@@ -550,10 +560,12 @@ namespace Barotrauma
|
||||
|
||||
for (int i = 0; i < Limbs.Length; i++)
|
||||
{
|
||||
if (Limbs[i].SteerForce <= 0.0f) { continue; }
|
||||
var limb = Limbs[i];
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (limb.SteerForce <= 0.0f) { continue; }
|
||||
if (!Collider.PhysEnabled) { continue; }
|
||||
Vector2 pullPos = Limbs[i].PullJointWorldAnchorA;
|
||||
Limbs[i].body.ApplyForce(movement * Limbs[i].SteerForce * Limbs[i].Mass * Math.Max(character.SpeedMultiplier, 1), pullPos);
|
||||
Vector2 pullPos = limb.PullJointWorldAnchorA;
|
||||
limb.body.ApplyForce(movement * limb.SteerForce * limb.Mass * Math.Max(character.SpeedMultiplier, 1), pullPos);
|
||||
}
|
||||
|
||||
Vector2 mainLimbDiff = mainLimb.PullJointWorldAnchorB - mainLimb.SimPosition;
|
||||
@@ -604,6 +616,14 @@ namespace Barotrauma
|
||||
float stepLift = TargetMovement.X == 0.0f ? 0 :
|
||||
(float)Math.Sin(WalkPos * CurrentGroundedParams.StepLiftFrequency + MathHelper.Pi * CurrentGroundedParams.StepLiftOffset) * (CurrentGroundedParams.StepLiftAmount / 100);
|
||||
|
||||
float limpAmount = character.GetLegPenalty();
|
||||
if (limpAmount > 0)
|
||||
{
|
||||
float walkPosX = (float)Math.Cos(WalkPos);
|
||||
//make the footpos oscillate when limping
|
||||
limpAmount = Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * Math.Min(Math.Abs(TargetMovement.X), 0.3f) * Dir;
|
||||
}
|
||||
|
||||
Limb torso = GetLimb(LimbType.Torso);
|
||||
if (torso != null)
|
||||
{
|
||||
@@ -613,7 +633,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (TorsoPosition.HasValue)
|
||||
{
|
||||
Vector2 pos = colliderBottom + new Vector2(0, TorsoPosition.Value + stepLift);
|
||||
Vector2 pos = colliderBottom + new Vector2(limpAmount, TorsoPosition.Value + stepLift);
|
||||
|
||||
if (torso != mainLimb)
|
||||
{
|
||||
@@ -635,7 +655,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (HeadPosition.HasValue)
|
||||
{
|
||||
Vector2 pos = colliderBottom + new Vector2(0, HeadPosition.Value + stepLift * CurrentGroundedParams.StepLiftHeadMultiplier);
|
||||
Vector2 pos = colliderBottom + new Vector2(limpAmount, HeadPosition.Value + stepLift * CurrentGroundedParams.StepLiftHeadMultiplier);
|
||||
|
||||
if (head != mainLimb)
|
||||
{
|
||||
@@ -670,6 +690,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (Math.Abs(limb.Params.ConstantTorque) > 0)
|
||||
{
|
||||
limb.body.SmoothRotate(movementAngle + MathHelper.ToRadians(limb.Params.ConstantAngle) * Dir, limb.Params.ConstantTorque, wrapAngle: true);
|
||||
@@ -766,6 +787,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
#if CLIENT
|
||||
if (limb.LightSource != null)
|
||||
{
|
||||
@@ -821,6 +843,7 @@ namespace Barotrauma
|
||||
base.Flip();
|
||||
foreach (Limb l in Limbs)
|
||||
{
|
||||
if (l.IsSevered) { continue; }
|
||||
if (!l.DoesFlip) { continue; }
|
||||
if (RagdollParams.IsSpritesheetOrientationHorizontal)
|
||||
{
|
||||
@@ -838,10 +861,13 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb l in Limbs)
|
||||
{
|
||||
if (l.IsSevered) { continue; }
|
||||
|
||||
TrySetLimbPosition(l,
|
||||
centerOfMass,
|
||||
new Vector2(centerOfMass.X - (l.SimPosition.X - centerOfMass.X), l.SimPosition.Y),
|
||||
lerp);
|
||||
|
||||
l.body.PositionSmoothingFactor = 0.8f;
|
||||
|
||||
if (!l.DoesFlip) { continue; }
|
||||
@@ -862,7 +888,7 @@ namespace Barotrauma
|
||||
if (diff < 100.0f)
|
||||
{
|
||||
character.SelectedCharacter.AnimController.SetPosition(
|
||||
new Vector2(centerOfMass.X - diff, character.SelectedCharacter.SimPosition.Y), lerp: true);
|
||||
new Vector2(centerOfMass.X - diff, character.SelectedCharacter.SimPosition.Y), lerp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+54
-30
@@ -323,7 +323,14 @@ namespace Barotrauma
|
||||
|
||||
levitatingCollider = true;
|
||||
ColliderIndex = Crouching ? 1 : 0;
|
||||
if (!Crouching && ColliderIndex == 1) Crouching = true;
|
||||
if (character.SelectedConstruction?.GetComponent<Controller>()?.ControlCharacterPose ?? false)
|
||||
{
|
||||
Crouching = false;
|
||||
}
|
||||
else if (!Crouching && ColliderIndex == 1)
|
||||
{
|
||||
Crouching = true;
|
||||
}
|
||||
|
||||
//stun (= disable the animations) if the ragdoll receives a large enough impact
|
||||
if (strongestImpact > 0.0f)
|
||||
@@ -441,7 +448,7 @@ namespace Barotrauma
|
||||
for (int i = -1; i < 2; i += 2)
|
||||
{
|
||||
Vector2 footPos = GetColliderBottom();
|
||||
footPos = new Vector2(waist.SimPosition.X + Math.Sign(StepSize.Value.X * i) * Dir * 0.3f, footPos.Y - 0.1f * RagdollParams.JointScale);
|
||||
footPos = new Vector2(waist.SimPosition.X + Math.Sign(WalkParams.StepSize.X * i) * Dir * 0.3f, footPos.Y - 0.1f * RagdollParams.JointScale);
|
||||
var foot = i == -1 ? rightFoot : leftFoot;
|
||||
MoveLimb(foot, footPos, Math.Abs(foot.SimPosition.X - footPos.X) * 100.0f, true);
|
||||
}
|
||||
@@ -481,7 +488,7 @@ namespace Barotrauma
|
||||
|
||||
swimmingStateLockTimer -= deltaTime;
|
||||
|
||||
if (forceStanding)
|
||||
if (forceStanding || character.AnimController.AnimationTestPose)
|
||||
{
|
||||
swimming = false;
|
||||
}
|
||||
@@ -542,12 +549,6 @@ namespace Barotrauma
|
||||
Limb leftLeg = GetLimb(LimbType.LeftLeg);
|
||||
Limb rightLeg = GetLimb(LimbType.RightLeg);
|
||||
|
||||
float limpAmount =
|
||||
character.CharacterHealth.GetAfflictionStrength("damage", leftFoot, true) +
|
||||
character.CharacterHealth.GetAfflictionStrength("damage", rightFoot, true) +
|
||||
character.CharacterHealth.GetAfflictionStrength("spaceherpes");
|
||||
limpAmount = MathHelper.Clamp(limpAmount / 100.0f, 0.0f, 1.0f);
|
||||
|
||||
float walkCycleMultiplier = 1.0f;
|
||||
if (Stairs != null)
|
||||
{
|
||||
@@ -582,6 +583,11 @@ namespace Barotrauma
|
||||
stepSize.Y *= walkPosY;
|
||||
|
||||
float footMid = colliderPos.X;
|
||||
|
||||
var herpes = character.CharacterHealth.GetAffliction("spaceherpes", false);
|
||||
float herpesAmount = herpes == null ? 0 : herpes.Strength / herpes.Prefab.MaxStrength;
|
||||
float legDamage = character.GetLegPenalty(startSum: -0.1f) * 1.1f;
|
||||
float limpAmount = MathHelper.Lerp(0, 1, legDamage + herpesAmount);
|
||||
if (limpAmount > 0.0f)
|
||||
{
|
||||
//make the footpos oscillate when limping
|
||||
@@ -652,6 +658,7 @@ namespace Barotrauma
|
||||
(float)Math.Sin(WalkPos * CurrentGroundedParams.StepLiftFrequency + MathHelper.Pi * CurrentGroundedParams.StepLiftOffset) * (CurrentGroundedParams.StepLiftAmount / 100);
|
||||
|
||||
float y = colliderPos.Y + stepLift;
|
||||
|
||||
if (TorsoPosition.HasValue)
|
||||
{
|
||||
y += TorsoPosition.Value;
|
||||
@@ -690,6 +697,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
MoveLimb(limb, limb.SimPosition + move, 15.0f, true);
|
||||
}
|
||||
|
||||
@@ -947,8 +955,6 @@ namespace Barotrauma
|
||||
|
||||
torso.body.MoveToPos(Collider.SimPosition + new Vector2((float)Math.Sin(-Collider.Rotation), (float)Math.Cos(-Collider.Rotation)) * 0.4f, 5.0f);
|
||||
|
||||
if (TargetMovement == Vector2.Zero) { return; }
|
||||
|
||||
movement = MathUtils.SmoothStep(movement, TargetMovement, 0.3f);
|
||||
|
||||
if (TorsoAngle.HasValue)
|
||||
@@ -1001,29 +1007,31 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
WalkPos += movement.Length();
|
||||
legCyclePos += Vector2.Normalize(movement).Length();
|
||||
legCyclePos += Math.Min(movement.LengthSquared() + Collider.AngularVelocity, 1.0f);
|
||||
handCyclePos += MathHelper.ToRadians(CurrentSwimParams.HandCycleSpeed) * Math.Sign(movement.X);
|
||||
|
||||
var waist = GetLimb(LimbType.Waist);
|
||||
footPos = waist == null ? Vector2.Zero : waist.SimPosition - new Vector2((float)Math.Sin(-Collider.Rotation), (float)Math.Cos(-Collider.Rotation)) * (upperLegLength + lowerLegLength);
|
||||
Vector2 transformedFootPos = new Vector2((float)Math.Sin(legCyclePos / CurrentSwimParams.LegCycleLength / character.SpeedMultiplier) * CurrentSwimParams.LegMoveAmount, 0.0f);
|
||||
Vector2 transformedFootPos = new Vector2((float)Math.Sin(legCyclePos / CurrentSwimParams.LegCycleLength) * CurrentSwimParams.LegMoveAmount, 0.0f);
|
||||
transformedFootPos = Vector2.Transform(transformedFootPos, Matrix.CreateRotationZ(Collider.Rotation));
|
||||
|
||||
float torque = CurrentSwimParams.FootRotateStrength * character.SpeedMultiplier * (1.2f - character.GetLegPenalty());
|
||||
if (rightFoot != null && !rightFoot.Disabled)
|
||||
{
|
||||
FootIK(rightFoot, footPos - transformedFootPos, CurrentSwimParams.FootRotateStrength, CurrentSwimParams.FootRotateStrength, CurrentSwimParams.FootAngleInRadians);
|
||||
FootIK(rightFoot, footPos - transformedFootPos, torque, torque, CurrentSwimParams.FootAngleInRadians);
|
||||
}
|
||||
if (leftFoot != null && !leftFoot.Disabled)
|
||||
{
|
||||
FootIK(leftFoot, footPos + transformedFootPos, CurrentSwimParams.FootRotateStrength, CurrentSwimParams.FootRotateStrength, CurrentSwimParams.FootAngleInRadians);
|
||||
FootIK(leftFoot, footPos + transformedFootPos, torque, torque, CurrentSwimParams.FootAngleInRadians);
|
||||
}
|
||||
|
||||
handPos = (torso.SimPosition + head.SimPosition) / 2.0f;
|
||||
|
||||
//at the surface, not moving sideways -> hands just float around
|
||||
if (!headInWater && TargetMovement.X == 0.0f && TargetMovement.Y > 0)
|
||||
//at the surface, not moving sideways OR not moving at all
|
||||
// -> hands just float around
|
||||
if ((!headInWater && TargetMovement.X == 0.0f && TargetMovement.Y > 0) || TargetMovement.LengthSquared() < 0.001f)
|
||||
{
|
||||
handPos.X = handPos.X + Dir * 0.6f;
|
||||
handPos += MathUtils.RotatePoint(Vector2.UnitX * Dir * 0.6f, torso.Rotation);
|
||||
|
||||
float wobbleAmount = 0.1f;
|
||||
|
||||
@@ -1060,7 +1068,7 @@ namespace Barotrauma
|
||||
rightHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, rightHandPos.X) : Math.Min(-0.3f, rightHandPos.X);
|
||||
rightHandPos = Vector2.Transform(rightHandPos, rotationMatrix);
|
||||
|
||||
HandIK(rightHand, handPos + rightHandPos, CurrentSwimParams.HandMoveStrength * character.SpeedMultiplier);
|
||||
HandIK(rightHand, handPos + rightHandPos, CurrentSwimParams.HandMoveStrength * character.SpeedMultiplier * (1 - Character.GetRightHandPenalty()));
|
||||
}
|
||||
|
||||
if (leftHand != null && !leftHand.Disabled)
|
||||
@@ -1069,7 +1077,7 @@ namespace Barotrauma
|
||||
leftHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, leftHandPos.X) : Math.Min(-0.3f, leftHandPos.X);
|
||||
leftHandPos = Vector2.Transform(leftHandPos, rotationMatrix);
|
||||
|
||||
HandIK(leftHand, handPos + leftHandPos, CurrentSwimParams.HandMoveStrength * character.SpeedMultiplier);
|
||||
HandIK(leftHand, handPos + leftHandPos, CurrentSwimParams.HandMoveStrength * character.SpeedMultiplier * (1 - Character.GetLeftHandPenalty()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1251,31 +1259,39 @@ namespace Barotrauma
|
||||
|
||||
Limb head = GetLimb(LimbType.Head);
|
||||
Limb torso = GetLimb(LimbType.Torso);
|
||||
|
||||
//if the head is moving, try to protect it with the hands
|
||||
if (head.LinearVelocity.LengthSquared() > 1.0f && !head.IsSevered)
|
||||
|
||||
if (head != null && head.LinearVelocity.LengthSquared() > 1.0f && !head.IsSevered)
|
||||
{
|
||||
//if the head is moving, try to protect it with the hands
|
||||
Limb leftHand = GetLimb(LimbType.LeftHand);
|
||||
Limb rightHand = GetLimb(LimbType.RightHand);
|
||||
|
||||
//move hands in front of the head in the direction of the movement
|
||||
Vector2 protectPos = head.SimPosition + Vector2.Normalize(head.LinearVelocity);
|
||||
if (!rightHand.IsSevered) HandIK(rightHand, protectPos, strength * 0.1f);
|
||||
if (!leftHand.IsSevered) HandIK(leftHand, protectPos, strength * 0.1f);
|
||||
if (rightHand != null && !rightHand.IsSevered)
|
||||
{
|
||||
HandIK(rightHand, protectPos, strength * 0.1f);
|
||||
}
|
||||
if (leftHand != null && !leftHand.IsSevered)
|
||||
{
|
||||
HandIK(leftHand, protectPos, strength * 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
if (torso == null) { return; }
|
||||
//attempt to make legs stay in a straight line with the torso to prevent the character from doing a split
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
var thigh = i == 0 ? GetLimb(LimbType.LeftThigh) : GetLimb(LimbType.RightThigh);
|
||||
if (thigh.IsSevered) continue;
|
||||
if (thigh == null) { continue; }
|
||||
if (thigh.IsSevered) { continue; }
|
||||
|
||||
float thighDiff = Math.Abs(MathUtils.GetShortestAngle(torso.Rotation, thigh.Rotation));
|
||||
float thighTorque = thighDiff * thigh.Mass * Math.Sign(torso.Rotation - thigh.Rotation) * 5.0f;
|
||||
thigh.body.ApplyTorque(thighTorque * strength);
|
||||
|
||||
var leg = i == 0 ? GetLimb(LimbType.LeftLeg) : GetLimb(LimbType.RightLeg);
|
||||
if (leg.IsSevered) continue;
|
||||
if (leg == null || leg.IsSevered) { continue; }
|
||||
float legDiff = Math.Abs(MathUtils.GetShortestAngle(torso.Rotation, leg.Rotation));
|
||||
float legTorque = legDiff * leg.Mass * Math.Sign(torso.Rotation - leg.Rotation) * 5.0f;
|
||||
leg.body.ApplyTorque(legTorque * strength);
|
||||
@@ -1410,7 +1426,7 @@ namespace Barotrauma
|
||||
SteamAchievementManager.OnCharacterRevived(target, character);
|
||||
lastReviveTime = (float)Timing.TotalTime;
|
||||
#if SERVER
|
||||
GameMain.Server?.KarmaManager?.OnCharacterHealthChanged(target, character, damage: Math.Min(prevVitality - target.Vitality, 0.0f));
|
||||
GameMain.Server?.KarmaManager?.OnCharacterHealthChanged(target, character, damage: Math.Min(prevVitality - target.Vitality, 0.0f), stun: 0.0f);
|
||||
#endif
|
||||
//reset attacker, we don't want the character to start attacking us
|
||||
//because we caused a bit of damage to them during CPR
|
||||
@@ -1540,6 +1556,11 @@ namespace Barotrauma
|
||||
{
|
||||
sourceSimPos -= character.SelectedCharacter.Submarine.SimPosition;
|
||||
}
|
||||
else if (character.Submarine != null && character.SelectedCharacter.Submarine != null && character.Submarine != character.SelectedCharacter.Submarine)
|
||||
{
|
||||
targetSimPos += character.SelectedCharacter.Submarine.SimPosition;
|
||||
targetSimPos -= character.Submarine.SimPosition;
|
||||
}
|
||||
var body = Submarine.CheckVisibility(sourceSimPos, targetSimPos, ignoreSubs: true);
|
||||
if (body != null)
|
||||
{
|
||||
@@ -1553,8 +1574,8 @@ namespace Barotrauma
|
||||
|
||||
Vector2 diff = ConvertUnits.ToSimUnits(targetLimb.WorldPosition - pullLimb.WorldPosition);
|
||||
|
||||
Vector2 targetAnchor = targetLimb.SimPosition;
|
||||
float targetForce = 0.0f;
|
||||
Vector2 targetAnchor;
|
||||
float targetForce;
|
||||
pullLimb.PullJointEnabled = true;
|
||||
if (targetLimb.type == LimbType.Torso || targetLimb == target.AnimController.MainLimb)
|
||||
{
|
||||
@@ -1624,6 +1645,7 @@ namespace Barotrauma
|
||||
|
||||
if (!target.AllowInput)
|
||||
{
|
||||
target.AnimController.Stairs = Stairs;
|
||||
target.AnimController.IgnorePlatforms = IgnorePlatforms;
|
||||
target.AnimController.TargetMovement = TargetMovement;
|
||||
}
|
||||
@@ -1981,6 +2003,8 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
|
||||
bool mirror = false;
|
||||
bool flipAngle = false;
|
||||
bool wrapAngle = false;
|
||||
|
||||
@@ -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