Build 1.1.4.0

This commit is contained in:
Markus Isberg
2023-03-31 18:40:44 +03:00
parent efba17e0ff
commit 9470edead3
483 changed files with 17487 additions and 8548 deletions
@@ -541,11 +541,11 @@ namespace Barotrauma
float wobbleStrength = 0.0f;
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == heldItem)
{
wobbleStrength += Character.CharacterHealth.GetLimbDamage(rightHand, afflictionType: "damage");
wobbleStrength += Character.CharacterHealth.GetLimbDamage(rightHand, afflictionType: AfflictionPrefab.DamageType);
}
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand) == heldItem)
{
wobbleStrength += Character.CharacterHealth.GetLimbDamage(leftHand, afflictionType: "damage");
wobbleStrength += Character.CharacterHealth.GetLimbDamage(leftHand, afflictionType: AfflictionPrefab.DamageType);
}
if (wobbleStrength <= 0.1f) { return 0.0f; }
wobbleStrength = (float)Math.Min(wobbleStrength, 1.0f);
@@ -135,8 +135,14 @@ namespace Barotrauma
public override void UpdateAnim(float deltaTime)
{
if (Frozen) return;
if (MainLimb == null) { return; }
//wait a bit for the ragdoll to "settle" (for joints to force the limbs to appropriate positions) before starting to animate
if (Timing.TotalTime - character.SpawnTime < 0.1f) { return; }
if (Frozen) { return; }
if (MainLimb == null)
{
ResetState();
return;
}
var mainLimb = MainLimb;
levitatingCollider = !IsHanging;
@@ -164,6 +170,7 @@ namespace Barotrauma
//cannot walk but on dry land -> wiggle around
UpdateDying(deltaTime);
}
ResetState();
return;
}
else
@@ -176,11 +183,17 @@ namespace Barotrauma
{
var lowestLimb = FindLowestLimb();
Collider.SetTransform(new Vector2(
Collider.SimPosition.X,
Math.Max(lowestLimb.SimPosition.Y + (Collider.radius + Collider.height / 2), Collider.SimPosition.Y)),
0.0f);
if (InWater)
{
Collider.SetTransform(new Vector2(Collider.SimPosition.X, MainLimb.SimPosition.Y), 0.0f);
}
else
{
Collider.SetTransform(new Vector2(
Collider.SimPosition.X,
Math.Max(lowestLimb.SimPosition.Y + (Collider.Radius + Collider.Height / 2), Collider.SimPosition.Y)),
0.0f);
}
Collider.Enabled = true;
}
@@ -223,6 +236,7 @@ namespace Barotrauma
if (character.SelectedCharacter != null)
{
DragCharacter(character.SelectedCharacter, deltaTime);
ResetState();
return;
}
if (character.AnimController.AnimationTestPose)
@@ -230,7 +244,11 @@ namespace Barotrauma
ApplyTestPose();
}
//don't flip when simply physics is enabled
if (SimplePhysicsEnabled) { return; }
if (SimplePhysicsEnabled)
{
ResetState();
return;
}
if (!character.IsRemotelyControlled && (character.AIController == null || character.AIController.CanFlip) && !Aiming)
{
@@ -264,43 +282,47 @@ namespace Barotrauma
}
}
if (!CurrentFishAnimation.Flip) { return; }
if (IsStuck) { return; }
if (character.AIController != null && !character.AIController.CanFlip) { return; }
flipCooldown -= deltaTime;
if (TargetDir != Direction.None && TargetDir != dir)
if (!IsStuck && CurrentFishAnimation.Flip && character.AIController is not { CanFlip: false })
{
flipTimer += deltaTime;
// 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)
flipCooldown -= deltaTime;
if (TargetDir != Direction.None && TargetDir != dir)
{
// 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))
flipTimer += deltaTime;
// 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)
{
Mirror(CurrentSwimParams != null ? CurrentSwimParams.MirrorLerp : true);
// 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(CurrentSwimParams != null ? CurrentSwimParams.MirrorLerp : true);
}
flipTimer = 0.0f;
flipCooldown = CurrentFishAnimation.FlipCooldown;
}
}
else
{
flipTimer = 0.0f;
flipCooldown = CurrentFishAnimation.FlipCooldown;
}
}
else
ResetState();
void ResetState()
{
flipTimer = 0.0f;
wasAiming = aiming;
aiming = false;
wasAimingMelee = aimingMelee;
aimingMelee = false;
}
wasAiming = aiming;
aiming = false;
wasAimingMelee = aimingMelee;
aimingMelee = false;
}
private bool CanDrag(Character target)
@@ -458,24 +480,34 @@ namespace Barotrauma
t = MathHelper.Clamp((1 + dot) / 10, 0.01f, 0.1f);
}
}
Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement, t);
if (Collider.BodyType == BodyType.Dynamic)
{
Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement, t);
}
//limbs are disabled when simple physics is enabled, no need to move them
if (SimplePhysicsEnabled) { return; }
mainLimb.PullJointEnabled = true;
if (aiming && movement.Length() <= 0.1f)
{
Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
Vector2 diff = (mousePos - (GetLimb(LimbType.Torso) ?? MainLimb).SimPosition) * Dir;
TargetMovement = new Vector2(0.0f, -0.1f);
float newRotation = MathUtils.VectorToAngle(diff);
Collider.SmoothRotate(newRotation, CurrentSwimParams.SteerTorque * character.SpeedMultiplier);
}
if (!isMoving)
if (!isMoving && !CurrentSwimParams.UpdateAnimationWhenNotMoving)
{
WalkPos = MathHelper.SmoothStep(WalkPos, MathHelper.PiOver2, deltaTime * 5);
mainLimb.PullJointWorldAnchorB = Collider.SimPosition;
if (aiming)
{
Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
Vector2 diff = (mousePos - (GetLimb(LimbType.Torso) ?? MainLimb).SimPosition) * Dir;
TargetMovement = new Vector2(0.0f, -0.1f);
float newRotation = MathHelper.WrapAngle(MathUtils.VectorToAngle(diff) - MathHelper.PiOver2 * Dir);
Collider.SmoothRotate(newRotation, CurrentSwimParams.SteerTorque * character.SpeedMultiplier * 2);
if (TorsoAngle.HasValue)
{
Limb torso = GetLimb(LimbType.Torso);
if (torso != null)
{
SmoothRotateWithoutWrapping(torso, newRotation + TorsoAngle.Value * Dir, mainLimb, TorsoTorque * 2);
}
}
}
}
else
{
@@ -688,9 +720,12 @@ namespace Barotrauma
{
movement = MathUtils.SmoothStep(movement, TargetMovement, 0.2f);
Collider.LinearVelocity = new Vector2(
movement.X,
Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y);
if (Collider.BodyType == BodyType.Dynamic)
{
Collider.LinearVelocity = new Vector2(
movement.X,
Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y);
}
//limbs are disabled when simple physics is enabled, no need to move them
if (SimplePhysicsEnabled) { return; }
@@ -170,7 +170,7 @@ namespace Barotrauma
{
get
{
float shoulderHeight = Collider.height / 2.0f;
float shoulderHeight = Collider.Height / 2.0f;
if (inWater)
{
shoulderHeight += 0.4f;
@@ -308,7 +308,7 @@ namespace Barotrauma
Collider.SetTransform(new Vector2(
Collider.SimPosition.X,
Math.Max(lowestLimb.SimPosition.Y + (Collider.radius + Collider.height / 2), Collider.SimPosition.Y)),
Math.Max(lowestLimb.SimPosition.Y + (Collider.Radius + Collider.Height / 2), Collider.SimPosition.Y)),
Collider.Rotation);
Collider.FarseerBody.ResetDynamics();
@@ -459,7 +459,8 @@ namespace Barotrauma
void UpdateStanding()
{
if (CurrentGroundedParams == null) { return; }
var currentGroundedParams = CurrentGroundedParams;
if (currentGroundedParams == null) { return; }
Vector2 handPos;
Limb leftFoot = GetLimb(LimbType.LeftFoot);
@@ -482,7 +483,7 @@ namespace Barotrauma
walkCycleMultiplier *= 1.5f;
}
float getUpForce = CurrentGroundedParams.GetUpForce / RagdollParams.JointScale;
float getUpForce = currentGroundedParams.GetUpForce / RagdollParams.JointScale;
Vector2 colliderPos = GetColliderBottom();
if (Math.Abs(TargetMovement.X) > 1.0f)
@@ -583,7 +584,7 @@ namespace Barotrauma
}
float stepLift = TargetMovement.X == 0.0f ? 0 :
(float)Math.Sin(WalkPos * CurrentGroundedParams.StepLiftFrequency + MathHelper.Pi * CurrentGroundedParams.StepLiftOffset) * (CurrentGroundedParams.StepLiftAmount / 100);
(float)Math.Sin(WalkPos * currentGroundedParams.StepLiftFrequency + MathHelper.Pi * currentGroundedParams.StepLiftOffset) * (currentGroundedParams.StepLiftAmount / 100);
float y = colliderPos.Y + stepLift;
@@ -598,7 +599,7 @@ namespace Barotrauma
if (!head.Disabled)
{
y = colliderPos.Y + stepLift * CurrentGroundedParams.StepLiftHeadMultiplier;
y = colliderPos.Y + stepLift * currentGroundedParams.StepLiftHeadMultiplier;
if (HeadPosition.HasValue) { y += HeadPosition.Value; }
if (Crouching && !movingHorizontally) { y -= HumanCrouchParams.MoveDownAmountWhenStationary; }
head.PullJointWorldAnchorB =
@@ -615,18 +616,18 @@ namespace Barotrauma
if (TorsoAngle.HasValue && !torso.Disabled)
{
float torsoAngle = TorsoAngle.Value;
float herpesStrength = character.CharacterHealth.GetAfflictionStrength("spaceherpes");
float herpesStrength = character.CharacterHealth.GetAfflictionStrength(AfflictionPrefab.SpaceHerpesType);
if (Crouching && !movingHorizontally && !Aiming) { torsoAngle -= HumanCrouchParams.ExtraTorsoAngleWhenStationary; }
torsoAngle -= herpesStrength / 150.0f;
torso.body.SmoothRotate(torsoAngle * Dir, CurrentGroundedParams.TorsoTorque);
torso.body.SmoothRotate(torsoAngle * Dir, currentGroundedParams.TorsoTorque);
}
if (!head.Disabled)
{
if (!Aiming && CurrentGroundedParams.FixedHeadAngle && HeadAngle.HasValue)
if (!Aiming && currentGroundedParams.FixedHeadAngle && HeadAngle.HasValue)
{
float headAngle = HeadAngle.Value;
if (Crouching && !movingHorizontally) { headAngle -= HumanCrouchParams.ExtraHeadAngleWhenStationary; }
head.body.SmoothRotate(headAngle * Dir, CurrentGroundedParams.HeadTorque);
head.body.SmoothRotate(headAngle * Dir, currentGroundedParams.HeadTorque);
}
else
{
@@ -665,16 +666,16 @@ namespace Barotrauma
if (footPos.Y < 0.0f) { footPos.Y = -0.15f; }
//make the character limp if the feet are damaged
float footAfflictionStrength = character.CharacterHealth.GetAfflictionStrength("damage", foot, true);
float footAfflictionStrength = character.CharacterHealth.GetAfflictionStrength(AfflictionPrefab.DamageType, foot, true);
footPos.X *= MathHelper.Lerp(1.0f, 0.75f, MathHelper.Clamp(footAfflictionStrength / 50.0f, 0.0f, 1.0f));
if (CurrentGroundedParams.FootLiftHorizontalFactor > 0)
if (currentGroundedParams.FootLiftHorizontalFactor > 0)
{
// Calculate the foot y dynamically based on the foot position relative to the waist,
// so that the foot aims higher when it's behind the waist and lower when it's in the front.
float xDiff = (foot.SimPosition.X - waistPos.X + FootMoveOffset.X) * Dir;
float min = MathUtils.InverseLerp(1, 0, CurrentGroundedParams.FootLiftHorizontalFactor);
float max = 1 + MathUtils.InverseLerp(0, 1, CurrentGroundedParams.FootLiftHorizontalFactor);
float min = MathUtils.InverseLerp(1, 0, currentGroundedParams.FootLiftHorizontalFactor);
float max = 1 + MathUtils.InverseLerp(0, 1, currentGroundedParams.FootLiftHorizontalFactor);
float xFactor = MathHelper.Lerp(min, max, MathUtils.InverseLerp(RagdollParams.JointScale, -RagdollParams.JointScale, xDiff));
footPos.Y *= xFactor;
}
@@ -698,19 +699,19 @@ namespace Barotrauma
{
foot.DebugRefPos = colliderPos;
foot.DebugTargetPos = colliderPos + footPos;
MoveLimb(foot, colliderPos + footPos, CurrentGroundedParams.FootMoveStrength);
MoveLimb(foot, colliderPos + footPos, currentGroundedParams.FootMoveStrength);
FootIK(foot, colliderPos + footPos,
CurrentGroundedParams.LegBendTorque, CurrentGroundedParams.FootTorque, CurrentGroundedParams.FootAngleInRadians);
currentGroundedParams.LegBendTorque, currentGroundedParams.FootTorque, currentGroundedParams.FootAngleInRadians);
}
}
//calculate the positions of hands
handPos = torso.SimPosition;
handPos.X = -walkPosX * CurrentGroundedParams.HandMoveAmount.X;
handPos.X = -walkPosX * currentGroundedParams.HandMoveAmount.X;
float lowerY = CurrentGroundedParams.HandClampY;
float lowerY = currentGroundedParams.HandClampY;
handPos.Y = lowerY + (float)(Math.Abs(Math.Sin(WalkPos - Math.PI * 1.5f) * CurrentGroundedParams.HandMoveAmount.Y));
handPos.Y = lowerY + (float)(Math.Abs(Math.Sin(WalkPos - Math.PI * 1.5f) * currentGroundedParams.HandMoveAmount.Y));
Vector2 posAddition = new Vector2(Math.Sign(movement.X) * HandMoveOffset.X, HandMoveOffset.Y);
@@ -718,13 +719,13 @@ namespace Barotrauma
{
HandIK(rightHand,
torso.SimPosition + posAddition + new Vector2(-handPos.X, (Math.Sign(walkPosX) == Math.Sign(Dir)) ? handPos.Y : lowerY),
CurrentGroundedParams.ArmMoveStrength, CurrentGroundedParams.HandMoveStrength);
currentGroundedParams.ArmMoveStrength, currentGroundedParams.HandMoveStrength);
}
if (leftHand != null && !leftHand.Disabled)
{
HandIK(leftHand,
torso.SimPosition + posAddition + new Vector2(handPos.X, (Math.Sign(walkPosX) == Math.Sign(-Dir)) ? handPos.Y : lowerY),
CurrentGroundedParams.ArmMoveStrength, CurrentGroundedParams.HandMoveStrength);
currentGroundedParams.ArmMoveStrength, currentGroundedParams.HandMoveStrength);
}
}
else
@@ -755,8 +756,8 @@ namespace Barotrauma
{
foot.DebugRefPos = colliderPos;
foot.DebugTargetPos = footPos;
float footMoveForce = CurrentGroundedParams.FootMoveStrength;
float legBendTorque = CurrentGroundedParams.LegBendTorque;
float footMoveForce = currentGroundedParams.FootMoveStrength;
float legBendTorque = currentGroundedParams.LegBendTorque;
if (Crouching)
{
// Keeps the pose
@@ -764,7 +765,7 @@ namespace Barotrauma
footMoveForce *= 2;
}
MoveLimb(foot, footPos, footMoveForce);
FootIK(foot, footPos, legBendTorque, CurrentGroundedParams.FootTorque, CurrentGroundedParams.FootAngleInRadians);
FootIK(foot, footPos, legBendTorque, currentGroundedParams.FootTorque, currentGroundedParams.FootAngleInRadians);
}
}
@@ -780,7 +781,7 @@ namespace Barotrauma
var arm = GetLimb(armType);
if (arm != null && Math.Abs(arm.body.AngularVelocity) < 10.0f)
{
arm.body.SmoothRotate(MathHelper.Clamp(-arm.body.AngularVelocity, -0.5f, 0.5f), arm.Mass * 50.0f * CurrentGroundedParams.ArmMoveStrength);
arm.body.SmoothRotate(MathHelper.Clamp(-arm.body.AngularVelocity, -0.5f, 0.5f), arm.Mass * 50.0f * currentGroundedParams.ArmMoveStrength);
}
//get the elbow to a neutral rotation
@@ -791,14 +792,14 @@ namespace Barotrauma
if (elbow != null)
{
float diff = elbow.JointAngle - (Dir > 0 ? elbow.LowerLimit : elbow.UpperLimit);
forearm.body.ApplyTorque(MathHelper.Clamp(-diff, -MathHelper.PiOver2, MathHelper.PiOver2) * forearm.Mass * 100.0f * CurrentGroundedParams.ArmMoveStrength);
forearm.body.ApplyTorque(MathHelper.Clamp(-diff, -MathHelper.PiOver2, MathHelper.PiOver2) * forearm.Mass * 100.0f * currentGroundedParams.ArmMoveStrength);
}
}
// Try to keep the wrist straight
LimbJoint wrist = GetJointBetweenLimbs(foreArmType, hand.type);
if (wrist != null)
{
hand.body.ApplyTorque(MathHelper.Clamp(-wrist.JointAngle, -MathHelper.PiOver2, MathHelper.PiOver2) * hand.Mass * 100f * CurrentGroundedParams.HandMoveStrength);
hand.body.ApplyTorque(MathHelper.Clamp(-wrist.JointAngle, -MathHelper.PiOver2, MathHelper.PiOver2) * hand.Mass * 100f * currentGroundedParams.HandMoveStrength);
}
}
}
@@ -840,14 +841,11 @@ namespace Barotrauma
if (head == null) { return; }
if (torso == null) { return; }
const float DisableMovementAboveSurfaceThreshold = 50.0f;
if (currentHull != null && character.CurrentHull != null)
{
float surfacePos = GetSurfaceY();
float surfaceThreshold = ConvertUnits.ToDisplayUnits(Collider.SimPosition.Y + 1.0f);
surfaceLimiter = Math.Max(1.0f, surfaceThreshold - surfacePos);
if (surfaceLimiter > DisableMovementAboveSurfaceThreshold) { return; }
}
Limb leftHand = GetLimb(LimbType.LeftHand);
@@ -917,6 +915,7 @@ namespace Barotrauma
RotateHead(head);
}
const float DisableMovementAboveSurfaceThreshold = 50.0f;
//dont try to move upwards if head is already out of water
if (surfaceLimiter > 1.0f && TargetMovement.Y > 0.0f)
{
@@ -936,8 +935,8 @@ namespace Barotrauma
//turn head above the water
head.body.ApplyTorque(Dir);
}
movement.Y *= Math.Max(0, 1.0f - ((surfaceLimiter - 1.0f) / DisableMovementAboveSurfaceThreshold));
movement.Y = movement.Y * (1.0f - ((surfaceLimiter - 1.0f) / DisableMovementAboveSurfaceThreshold));
}
bool isNotRemote = true;
@@ -956,7 +955,13 @@ namespace Barotrauma
t = MathHelper.Clamp((1 + dot) / 10, 0.01f, 0.1f);
}
}
Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement, t);
Vector2 targetVelocity = movement;
//if we're too high above the surface, don't touch the vertical velocity of the collider unless we're heading down
if (surfaceLimiter > DisableMovementAboveSurfaceThreshold)
{
targetVelocity.Y = Math.Min(Collider.LinearVelocity.Y, movement.Y);
};
Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, targetVelocity, t);
}
WalkPos += movement.Length();
@@ -1130,7 +1135,7 @@ namespace Barotrauma
ladderSimPos -= currentHull.Submarine.SimPosition;
}
float bottomPos = Collider.SimPosition.Y - ColliderHeightFromFloor - Collider.radius - Collider.height / 2.0f;
float bottomPos = Collider.SimPosition.Y - ColliderHeightFromFloor - Collider.Radius - Collider.Height / 2.0f;
float torsoPos = TorsoPosition ?? 0;
MoveLimb(torso, new Vector2(ladderSimPos.X - 0.35f * Dir, bottomPos + torsoPos), 10.5f);
float headPos = HeadPosition ?? 0;
@@ -1225,7 +1230,7 @@ namespace Barotrauma
if (character.SimPosition.Y > ladderSimPos.Y) { climbForce.Y = Math.Min(0.0f, climbForce.Y); }
//reached the bottom -> can't go further down
float minHeightFromFloor = ColliderHeightFromFloor / 2 + Collider.height;
float minHeightFromFloor = ColliderHeightFromFloor / 2 + Collider.Height;
if (floorFixture != null &&
!floorFixture.CollisionCategories.HasFlag(Physics.CollisionStairs) &&
!floorFixture.CollisionCategories.HasFlag(Physics.CollisionPlatform) &&
@@ -1524,13 +1529,15 @@ namespace Barotrauma
Limb leftHand = GetLimb(LimbType.LeftHand);
Limb rightHand = GetLimb(LimbType.RightHand);
Limb targetLeftHand = target.AnimController.GetLimb(LimbType.LeftForearm);
if (targetLeftHand == null) { targetLeftHand = target.AnimController.GetLimb(LimbType.Torso); }
if (targetLeftHand == null) { targetLeftHand = target.AnimController.MainLimb; }
Limb targetLeftHand =
target.AnimController.GetLimb(LimbType.LeftForearm) ??
target.AnimController.GetLimb(LimbType.Torso) ??
target.AnimController.MainLimb;
Limb targetRightHand = target.AnimController.GetLimb(LimbType.RightForearm);
if (targetRightHand == null) { targetRightHand = target.AnimController.GetLimb(LimbType.Torso); }
if (targetRightHand == null) { targetRightHand = target.AnimController.MainLimb; }
Limb targetRightHand =
target.AnimController.GetLimb(LimbType.RightForearm) ??
target.AnimController.GetLimb(LimbType.Torso) ??
target.AnimController.MainLimb;
if (!target.AllowInput)
{
@@ -1546,10 +1553,7 @@ namespace Barotrauma
return;
}
Limb targetTorso = target.AnimController.GetLimb(LimbType.Torso);
if (targetTorso == null)
{
targetTorso = target.AnimController.MainLimb;
}
targetTorso ??= target.AnimController.MainLimb;
if (target.AnimController.Dir != Dir)
{
target.AnimController.Flip();
@@ -173,18 +173,18 @@ namespace Barotrauma
if (value == colliderIndex || collider == null) { return; }
if (value >= collider.Count || value < 0) { return; }
if (collider[colliderIndex].height < collider[value].height)
if (collider[colliderIndex].Height < collider[value].Height)
{
Vector2 pos1 = collider[colliderIndex].SimPosition;
pos1.Y -= collider[colliderIndex].height * ColliderHeightFromFloor;
pos1.Y -= collider[colliderIndex].Height * ColliderHeightFromFloor;
Vector2 pos2 = pos1;
pos2.Y += collider[value].height * 1.1f;
pos2.Y += collider[value].Height * 1.1f;
if (GameMain.World.RayCast(pos1, pos2).Any(f => f.CollisionCategories.HasFlag(Physics.CollisionWall) && !(f.Body.UserData is Submarine))) { return; }
}
Vector2 pos = collider[colliderIndex].SimPosition;
pos.Y -= collider[colliderIndex].height * 0.5f;
pos.Y += collider[value].height * 0.5f;
pos.Y -= collider[colliderIndex].Height * 0.5f;
pos.Y += collider[value].Height * 0.5f;
collider[value].SetTransform(pos, collider[colliderIndex].Rotation);
collider[value].LinearVelocity = collider[colliderIndex].LinearVelocity;
@@ -575,6 +575,10 @@ namespace Barotrauma
protected void AddLimb(LimbParams limbParams)
{
if (limbParams.ID < 0 || limbParams.ID > 255)
{
throw new Exception($"Invalid limb params in limb \"{limbParams.Type}\". \"{limbParams.ID}\" is not a valid limb ID.");
}
byte ID = Convert.ToByte(limbParams.ID);
Limb limb = new Limb(this, character, limbParams);
limb.body.FarseerBody.OnCollision += OnLimbCollision;
@@ -680,6 +684,10 @@ namespace Barotrauma
}
return true;
}
else if (character.Submarine != null && structure.Submarine != null && character.Submarine != structure.Submarine)
{
return false;
}
Vector2 colliderBottom = GetColliderBottom();
if (structure.IsPlatform)
@@ -1189,7 +1197,7 @@ namespace Barotrauma
{
inWater = false;
headInWater = false;
RefreshFloorY(ignoreStairs: Stairs == null);
RefreshFloorY(deltaTime, ignoreStairs: Stairs == null);
}
//ragdoll isn't in any room -> it's in the water
else if (currentHull == null)
@@ -1201,10 +1209,12 @@ namespace Barotrauma
{
headInWater = false;
inWater = false;
RefreshFloorY(ignoreStairs: Stairs == null);
RefreshFloorY(deltaTime, ignoreStairs: Stairs == null);
if (currentHull.WaterPercentage > 0.001f)
{
float waterSurface = ConvertUnits.ToSimUnits(GetSurfaceY());
(float waterSurfaceDisplayUnits, float ceilingDisplayUnits) = GetWaterSurfaceAndCeilingY();
float waterSurfaceY = ConvertUnits.ToSimUnits(waterSurfaceDisplayUnits);
float ceilingY = ConvertUnits.ToSimUnits(ceilingDisplayUnits);
if (targetMovement.Y < 0.0f)
{
Vector2 colliderBottom = GetColliderBottom();
@@ -1214,13 +1224,21 @@ namespace Barotrauma
{
//set floorY to the position of the floor in the hull below the character
var lowerHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(colliderBottom), useWorldCoordinates: false);
if (lowerHull != null) floorY = ConvertUnits.ToSimUnits(lowerHull.Rect.Y - lowerHull.Rect.Height);
if (lowerHull != null)
{
floorY = ConvertUnits.ToSimUnits(lowerHull.Rect.Y - lowerHull.Rect.Height);
}
}
}
float standHeight = HeadPosition ?? TorsoPosition ?? Collider.GetMaxExtent() * 0.5f;
if (Collider.SimPosition.Y < waterSurface && waterSurface - floorY > standHeight * 0.8f)
if (Collider.SimPosition.Y < waterSurfaceY)
{
inWater = true;
//too deep to stand up, or not enough room to stand up
if (waterSurfaceY - floorY > standHeight * 0.8f ||
ceilingY - floorY < standHeight * 0.8f)
{
inWater = true;
}
}
}
}
@@ -1281,21 +1299,32 @@ namespace Barotrauma
limb.Update(deltaTime);
}
if (!inWater && character.AllowInput && levitatingCollider && Collider.LinearVelocity.Y > -ImpactTolerance && onGround)
if (!inWater && character.AllowInput && levitatingCollider)
{
float targetY = standOnFloorY + ((float)Math.Abs(Math.Cos(Collider.Rotation)) * Collider.height * 0.5f) + Collider.radius + ColliderHeightFromFloor;
if (Math.Abs(Collider.SimPosition.Y - targetY) > 0.01f && onGround)
if (onGround && Collider.LinearVelocity.Y > -ImpactTolerance)
{
if (Stairs != null)
float targetY = standOnFloorY + ((float)Math.Abs(Math.Cos(Collider.Rotation)) * Collider.Height * 0.5f) + Collider.Radius + ColliderHeightFromFloor;
if (Math.Abs(Collider.SimPosition.Y - targetY) > 0.01f)
{
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X,
(targetY < Collider.SimPosition.Y ? Math.Sign(targetY - Collider.SimPosition.Y) : (targetY - Collider.SimPosition.Y)) * 5.0f);
if (Stairs != null)
{
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X,
(targetY < Collider.SimPosition.Y ? Math.Sign(targetY - Collider.SimPosition.Y) : (targetY - Collider.SimPosition.Y)) * 5.0f);
}
else
{
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X, (targetY - Collider.SimPosition.Y) * 5.0f);
}
}
else
}
else
{
// Falling -> ragdoll briefly if we are not moving at all, because we are probably stuck.
if (Collider.LinearVelocity == Vector2.Zero)
{
Collider.LinearVelocity = new Vector2(Collider.LinearVelocity.X, (targetY - Collider.SimPosition.Y) * 5.0f);
character.IsRagdolled = true;
}
}
}
}
UpdateProjSpecific(deltaTime, cam);
forceNotStanding = false;
@@ -1525,15 +1554,24 @@ namespace Barotrauma
lastFloorCheckPos = Vector2.Zero;
}
private void RefreshFloorY(Limb refLimb = null, bool ignoreStairs = false)
// Force check floor y at least once a second so that we'll drop through gaps that we are standing upon.
private const float FloorYStaleTime = 1;
private float floorYCheckTimer;
private void RefreshFloorY(float deltaTime, Limb refLimb = null, bool ignoreStairs = false)
{
floorYCheckTimer -= deltaTime;
PhysicsBody refBody = refLimb == null ? Collider : refLimb.body;
if (Vector2.DistanceSquared(lastFloorCheckPos, refBody.SimPosition) > 0.1f * 0.1f || lastFloorCheckIgnoreStairs != ignoreStairs || lastFloorCheckIgnorePlatforms != IgnorePlatforms)
if (floorYCheckTimer < 0 ||
lastFloorCheckIgnoreStairs != ignoreStairs ||
lastFloorCheckIgnorePlatforms != IgnorePlatforms ||
Vector2.DistanceSquared(lastFloorCheckPos, refBody.SimPosition) > 0.1f * 0.1f)
{
floorY = GetFloorY(refBody.SimPosition, ignoreStairs);
lastFloorCheckPos = refBody.SimPosition;
lastFloorCheckIgnoreStairs = ignoreStairs;
lastFloorCheckIgnorePlatforms = IgnorePlatforms;
// Add some randomness to prevent all stationary characters doing the checks at the same frame.
floorYCheckTimer = FloorYStaleTime * Rand.Range(0.9f, 1.1f);
}
}
@@ -1616,7 +1654,7 @@ namespace Barotrauma
{
floorFixture = standOnFloorFixture;
standOnFloorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * standOnFloorFraction;
if (rayStart.Y - standOnFloorY < Collider.height * 0.5f + Collider.radius + ColliderHeightFromFloor * 1.2f)
if (rayStart.Y - standOnFloorY < Collider.Height * 0.5f + Collider.Radius + ColliderHeightFromFloor * 1.2f)
{
onGround = true;
if (standOnFloorFixture.CollisionCategories == Physics.CollisionStairs)
@@ -1655,22 +1693,34 @@ namespace Barotrauma
}
}
/// <summary>
/// Get the position of the surface of water at the position of the character, in display units (taking into account connected hulls above the hull the character is in)
/// </summary>
public float GetSurfaceY()
{
return GetWaterSurfaceAndCeilingY().WaterSurfaceY;
}
/// <summary>
/// Get the position of the surface of water and the ceiling (= upper edge of the hull) at the position of the character, in display units (taking into account connected hulls above the hull the character is in).
/// </summary>
private (float WaterSurfaceY, float CeilingY) GetWaterSurfaceAndCeilingY()
{
//check both hulls: the hull whose coordinate space the ragdoll is in, and the hull whose bounds the character's origin actually is inside
if (currentHull == null || character.CurrentHull == null)
{
return float.PositiveInfinity;
return (float.PositiveInfinity, float.PositiveInfinity);
}
float surfacePos = currentHull.Surface;
float surfaceY = currentHull.Surface;
float ceilingY = currentHull.Rect.Y;
float surfaceThreshold = ConvertUnits.ToDisplayUnits(Collider.SimPosition.Y + 1.0f);
//if the hull is almost full of water, check if there's a water-filled hull above it
//and use its water surface instead of the current hull's
if (currentHull.Rect.Y - currentHull.Surface < 5.0f)
{
GetSurfacePos(currentHull, ref surfacePos);
void GetSurfacePos(Hull hull, ref float prevSurfacePos)
{
GetSurfacePos(currentHull, ref surfaceY, ref ceilingY);
void GetSurfacePos(Hull hull, ref float prevSurfacePos, ref float ceilingPos)
{
if (prevSurfacePos > surfaceThreshold) { return; }
foreach (Gap gap in hull.ConnectedGaps)
@@ -1681,6 +1731,7 @@ namespace Barotrauma
//if the gap is above us and leads outside, there's no surface to limit the movement
if (!gap.IsRoomToRoom && gap.Position.Y > hull.Position.Y)
{
ceilingPos += 100000.0f;
prevSurfacePos += 100000.0f;
return;
}
@@ -1689,15 +1740,16 @@ namespace Barotrauma
{
if (linkedTo is Hull otherHull && otherHull != hull && otherHull != currentHull)
{
prevSurfacePos = Math.Max(surfacePos, otherHull.Surface);
GetSurfacePos(otherHull, ref prevSurfacePos);
prevSurfacePos = Math.Max(surfaceY, otherHull.Surface);
ceilingPos = Math.Max(ceilingPos, otherHull.Rect.Y);
GetSurfacePos(otherHull, ref prevSurfacePos, ref ceilingPos);
break;
}
}
}
}
}
return surfacePos;
return (surfaceY, ceilingY);
}
public void SetPosition(Vector2 simPosition, bool lerp = false, bool ignorePlatforms = true, bool forceMainLimbToCollider = false, bool detachProjectiles = true)
@@ -1803,22 +1855,36 @@ namespace Barotrauma
private bool collisionsDisabled;
private double lastObstacleRayCastTime;
protected void CheckDistFromCollider()
{
float allowedDist = Math.Max(Math.Max(Collider.radius, Collider.width), Collider.height) * 2.0f;
float allowedDist = Math.Max(Math.Max(Collider.Radius, Collider.Width), Collider.Height) * 2.0f;
allowedDist = Math.Max(allowedDist, 1.0f);
float resetDist = allowedDist * 5.0f;
float obstacleCheckDist = 0.3f;
Vector2 diff = Collider.SimPosition - MainLimb.SimPosition;
float distSqrd = diff.LengthSquared();
if (distSqrd > resetDist * resetDist)
bool shouldReset = distSqrd > resetDist * resetDist;
if (!shouldReset && distSqrd > obstacleCheckDist * obstacleCheckDist)
{
if (Timing.TotalTime > lastObstacleRayCastTime + 1 &&
Submarine.PickBody(Collider.SimPosition, MainLimb.SimPosition, collisionCategory: Physics.CollisionWall) != null)
{
shouldReset = true;
lastObstacleRayCastTime = Timing.TotalTime;
}
}
if (shouldReset)
{
//ragdoll way too far, reset position
SetPosition(Collider.SimPosition, lerp: true, forceMainLimbToCollider: true);
}
if (distSqrd > allowedDist * allowedDist)
else if (distSqrd > allowedDist * allowedDist)
{
//ragdoll too far from the collider, disable collisions until it's close enough
//(in case the ragdoll has gotten stuck somewhere)
@@ -1840,7 +1906,7 @@ namespace Barotrauma
collisionsDisabled = false;
//force collision categories to be updated
prevCollisionCategory = Category.None;
}
}
}
partial void UpdateNetPlayerPositionProjSpecific(float deltaTime, float lowestSubPos);