diff --git a/Subsurface/Content/Characters/Human/human.xml b/Subsurface/Content/Characters/Human/human.xml index 4388d847d..021f592ef 100644 --- a/Subsurface/Content/Characters/Human/human.xml +++ b/Subsurface/Content/Characters/Human/human.xml @@ -8,10 +8,10 @@ walkanimspeed="4.58" movementlerp="0.4" legtorque="15.0" - thightorque="-5.0"> + thightorque="-5.0" + swimspeed="2.0"> - - + diff --git a/Subsurface/Content/Characters/Husk/husk.xml b/Subsurface/Content/Characters/Husk/husk.xml index e3cbf0e71..d7ba207a7 100644 --- a/Subsurface/Content/Characters/Husk/husk.xml +++ b/Subsurface/Content/Characters/Husk/husk.xml @@ -11,8 +11,10 @@ movementlerp="0.4" legtorque="15.0" thightorque="-5.0" - walkspeed="2.0" - swimspeed="2.0"> + walkspeed="1.2" + swimspeed="2.5"> + + diff --git a/Subsurface/Source/Characters/AI/HumanAIController.cs b/Subsurface/Source/Characters/AI/HumanAIController.cs index 9ab385454..68b2e0102 100644 --- a/Subsurface/Source/Characters/AI/HumanAIController.cs +++ b/Subsurface/Source/Characters/AI/HumanAIController.cs @@ -71,36 +71,21 @@ namespace Barotrauma steeringManager.Update(moveSpeed); - Character.AnimController.IgnorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && + bool ignorePlatforms = Character.AnimController.TargetMovement.Y < -0.5f && (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); var currPath = (steeringManager as IndoorsSteeringManager).CurrentPath; if (currPath != null && currPath.CurrentNode != null) { - if (currPath.CurrentNode.WorldPosition.Y < Character.WorldPosition.Y - 200) + if (currPath.CurrentNode.SimPosition.Y < Character.AnimController.GetColliderBottom().Y) { - Character.AnimController.IgnorePlatforms = true; + ignorePlatforms = true; } - - //if (Character.AnimController.Stairs != null) - //{ - // float yDiff = currPath.CurrentNode.WorldPosition.Y - Character.WorldPosition.Y; - - // if (Math.Abs(yDiff) > 20.0f) - // { - // int dir = Math.Sign(yDiff); - - // float movement = Character.AnimController.Stairs.StairDirection == Direction.Right ? - // dir * Character.AnimController.TargetMovement.Length() : -dir * Character.AnimController.TargetMovement.Length(); - - // steeringManager.SteeringManual(deltaTime, new Vector2(movement*2, 0.0f)); - // } - //} } + Character.AnimController.IgnorePlatforms = ignorePlatforms; (Character.AnimController as HumanoidAnimController).Crouching = false; - if (!Character.AnimController.InWater) { Character.AnimController.TargetMovement = new Vector2( diff --git a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs index 928487bd9..aeaf5feb9 100644 --- a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs @@ -88,6 +88,13 @@ namespace Barotrauma Vector2 diff = DiffToCurrentNode(); + var collider = character.AnimController.Collider; + //if not in water and the waypoint is between the top and bottom of the collider, no need to move vertically + if (!character.AnimController.InWater && diff.Y < collider.height / 2 + collider.radius) + { + diff.Y = 0.0f; + } + if (diff == Vector2.Zero) return -host.Steering; return Vector2.Normalize(diff) * speed; @@ -95,7 +102,7 @@ namespace Barotrauma private Vector2 DiffToCurrentNode() { - if (currentPath == null || currentPath.Finished) return Vector2.Zero; + if (currentPath == null || currentPath.Finished || currentPath.Unreachable) return Vector2.Zero; if (currentPath.Finished) { diff --git a/Subsurface/Source/Characters/AI/PathFinder.cs b/Subsurface/Source/Characters/AI/PathFinder.cs index 984cd01fe..90b8639ed 100644 --- a/Subsurface/Source/Characters/AI/PathFinder.cs +++ b/Subsurface/Source/Characters/AI/PathFinder.cs @@ -168,7 +168,10 @@ namespace Barotrauma //if searching for a path inside the sub, make sure the waypoint is visible if (insideSubmarine) { - var body = Submarine.CheckVisibility(start, node.Waypoint.SimPosition); + var body = Submarine.PickBody( + start, node.Waypoint.SimPosition, null, + Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionStairs | Physics.CollisionPlatform); + if (body != null && body.UserData is Structure) continue; } diff --git a/Subsurface/Source/Characters/AI/SteeringManager.cs b/Subsurface/Source/Characters/AI/SteeringManager.cs index 86c21af93..4c0b6aee3 100644 --- a/Subsurface/Source/Characters/AI/SteeringManager.cs +++ b/Subsurface/Source/Characters/AI/SteeringManager.cs @@ -62,6 +62,13 @@ namespace Barotrauma public virtual void Update(float speed = 1.0f) { + if (steering == Vector2.Zero || !MathUtils.IsValid(steering)) + { + steering = Vector2.Zero; + host.Steering = Vector2.Zero; + return; + } + float steeringSpeed = steering.Length(); if (steeringSpeed>speed) { diff --git a/Subsurface/Source/Characters/Animation/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs index ef06e64e3..812fd6e9c 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -430,6 +430,7 @@ namespace Barotrauma l.body.SetTransform(l.SimPosition, -l.body.Rotation); } + } public override Vector2 EstimateCurrPosition(Vector2 prevPosition, float timePassed) @@ -443,38 +444,14 @@ namespace Barotrauma private void Mirror() { - //float leftX = Limbs[0].SimPosition.X, rightX = Limbs[0].SimPosition.X; - //for (int i = 1; i < Limbs.Count(); i++ ) - //{ - // if (Limbs[i].SimPosition.X < leftX) - // { - // leftX = Limbs[i].SimPosition.X; - // } - // else if (Limbs[i].SimPosition.X > rightX) - // { - // rightX = Limbs[i].SimPosition.X; - // } - //} - - float midX = GetCenterOfMass().X; + Vector2 centerOfMass = GetCenterOfMass(); foreach (Limb l in Limbs) { - Vector2 newPos = new Vector2(midX - (l.SimPosition.X - midX), l.SimPosition.Y); - - if (Submarine.CheckVisibility(l.SimPosition, newPos) != null) - { - Vector2 diff = newPos - l.SimPosition; - - l.body.SetTransform( - l.SimPosition + Submarine.LastPickedFraction * diff * 0.8f, l.body.Rotation); - } - else - { - l.body.SetTransform(newPos, l.body.Rotation); - } - - + TrySetLimbPosition(l, + centerOfMass, + new Vector2(centerOfMass.X - (l.SimPosition.X - centerOfMass.X), l.SimPosition.Y), + true); } } diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index a3b8e6118..37f3afef9 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -215,7 +215,7 @@ namespace Barotrauma if (onFloorTimer <= 0.0f) { onGround = false; - if (GetLimb(LimbType.Torso).inWater) inWater = true; + //if (GetLimb(LimbType.Torso).inWater) inWater = true; //TODO: joku järkevämpi systeemi //if (!inWater && lastTimeOnFloor + 200 < gameTime.TotalGameTime.Milliseconds) // stunTimer = Math.Max(stunTimer, (float)gameTime.TotalGameTime.TotalMilliseconds + 100.0f); @@ -227,13 +227,34 @@ namespace Barotrauma //re-enable collider (unless swimming) - if (!collider.FarseerBody.Enabled && !swimming) + if (!collider.FarseerBody.Enabled) { var lowestLimb = FindLowestLimb(); - collider.SetTransform(lowestLimb.SimPosition + Vector2.UnitY * (collider.radius + collider.height / 2), 0.0f); + collider.SetTransform(new Vector2( + collider.SimPosition.X, + Math.Max(lowestLimb.SimPosition.Y + (collider.radius + collider.height / 2), collider.SimPosition.Y)), + 0.0f); collider.FarseerBody.Enabled = true; } + if (swimming) + { + collider.FarseerBody.FixedRotation = false; + } + else if (!collider.FarseerBody.FixedRotation) + { + if (Math.Abs(MathUtils.GetShortestAngle(collider.Rotation, 0.0f)) > 0.001f) + { + collider.AngularVelocity = MathUtils.GetShortestAngle(collider.Rotation, 0.0f) * 60.0f; + collider.FarseerBody.FixedRotation = false; + } + else + { + collider.FarseerBody.FixedRotation = true; + } + } + + if (character.LockHands) { var leftHand = GetLimb(LimbType.LeftHand); @@ -368,7 +389,6 @@ namespace Barotrauma } Vector2 colliderPos = GetColliderBottom(); - if (Math.Abs(TargetMovement.X) > 1.0f) { int limbsInWater = 0; @@ -630,14 +650,16 @@ namespace Barotrauma Limb head = GetLimb(LimbType.Head); Limb torso = GetLimb(LimbType.Torso); - collider.FarseerBody.Enabled = false; - collider.SetTransform(torso.SimPosition, 0.0f); + //collider.FarseerBody.Enabled = false; + //collider.SetTransform(torso.SimPosition, 0.0f); - if (currentHull != null && (currentHull.Rect.Y - currentHull.Surface > 50.0f) && !head.inWater) + // float colliderTop = collider.SimPosition.Y + (float)Math.Cos(collider.Rotation) * (collider.radius + collider.height / 2); + + if (currentHull != null && (currentHull.Rect.Y - currentHull.Surface > 50.0f)) { - surfaceLimiter = (ConvertUnits.ToDisplayUnits(head.SimPosition.Y) - surfaceY); + surfaceLimiter = (ConvertUnits.ToDisplayUnits(collider.SimPosition.Y + 0.4f) - surfaceY); surfaceLimiter = Math.Max(1.0f, surfaceLimiter); - if (surfaceLimiter > 20.0f) return; + if (surfaceLimiter > 50.0f) return; } Limb leftHand = GetLimb(LimbType.LeftHand); @@ -645,9 +667,8 @@ namespace Barotrauma Limb leftFoot = GetLimb(LimbType.LeftFoot); Limb rightFoot = GetLimb(LimbType.RightFoot); - - - float rotation = MathHelper.WrapAngle(torso.Rotation); + + float rotation = MathHelper.WrapAngle(collider.Rotation); rotation = MathHelper.ToDegrees(rotation); if (rotation < 0.0f) rotation += 360; @@ -666,7 +687,10 @@ namespace Barotrauma { if (!aiming) { - torso.body.SmoothRotate(MathUtils.VectorToAngle(TargetMovement) - MathHelper.PiOver2); + float newRotation = MathUtils.VectorToAngle(TargetMovement) - MathHelper.PiOver2; + collider.SmoothRotate(newRotation, 5.0f); + //torso.body.SmoothRotate(newRotation); + } } else @@ -678,23 +702,34 @@ namespace Barotrauma TargetMovement = new Vector2(0.0f, -0.1f); - torso.body.SmoothRotate(MathUtils.VectorToAngle(diff)); + float newRotation = MathUtils.VectorToAngle(diff); + collider.SmoothRotate(newRotation, 5.0f); } } + torso.body.SmoothRotate(collider.Rotation); + 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 * swimSpeed, 0.3f); + movement = MathUtils.SmoothStep(movement, TargetMovement, 0.3f); //dont try to move upwards if head is already out of water if (surfaceLimiter > 1.0f && TargetMovement.Y > 0.0f) { if (TargetMovement.X == 0.0f) { - head.body.ApplyForce(head.Mass * new Vector2(-Dir * 5.1f, -5.0f)); - torso.body.ApplyForce(torso.Mass * new Vector2(-Dir * 5.1f, -15.0f)); - leftFoot.body.ApplyForce(leftFoot.Mass * new Vector2(0.0f, -80.0f)); - rightFoot.body.ApplyForce(rightFoot.Mass * new Vector2(0.0f, -80.0f)); + //pull head above water + head.body.SmoothRotate(0.0f, 5.0f); + + + walkPos += 0.05f; + + //push feet downwards + //leftFoot.body.ApplyForce(leftFoot.Mass * new Vector2(0.0f, -50.0f)); + // rightFoot.body.ApplyForce(rightFoot.Mass * new Vector2(0.0f, -50.0f)); + + } else { @@ -703,23 +738,17 @@ namespace Barotrauma * Math.Sign(TargetMovement.X), Math.Max(TargetMovement.Y, TargetMovement.Y * 0.2f)); - head.body.ApplyTorque(Dir * 0.1f); + //turn head above the water + head.body.ApplyTorque(Dir); } movement.Y = movement.Y - (surfaceLimiter - 1.0f) * 0.01f; } - movement.Y -= 0.05f; - - head.body.ApplyForce((new Vector2(movement.X, - movement.Y / surfaceLimiter + 0.2f) - head.body.LinearVelocity * 0.2f) * - 30.0f * head.body.Mass); - - torso.body.ApplyForce((new Vector2(movement.X, - movement.Y / surfaceLimiter + 0.2f) - torso.body.LinearVelocity * 0.2f) * 10.0f * torso.body.Mass); - + collider.LinearVelocity = Vector2.Lerp(collider.LinearVelocity, movement * swimSpeed, movementLerp); + walkPos += movement.Length() * 0.15f; - footPos = (leftFoot.SimPosition + rightFoot.SimPosition) / 2.0f; + footPos = collider.SimPosition - new Vector2((float)Math.Sin(-collider.Rotation), (float)Math.Cos(-collider.Rotation)) * 0.4f; var rightThigh = GetLimb(LimbType.RightThigh); var leftThigh = GetLimb(LimbType.LeftThigh); @@ -730,41 +759,32 @@ namespace Barotrauma Vector2 transformedFootPos = new Vector2((float)Math.Sin(walkPos) * 0.5f, 0.0f); transformedFootPos = Vector2.Transform( transformedFootPos, - Matrix.CreateRotationZ(torso.body.Rotation)); + Matrix.CreateRotationZ(collider.Rotation)); - if (Math.Abs(MathUtils.GetShortestAngle(torso.Rotation, rightThigh.Rotation)) < 0.3f) - { - MoveLimb(rightFoot, footPos - transformedFootPos, 1.0f); - } - if (Math.Abs(MathUtils.GetShortestAngle(torso.Rotation, leftThigh.Rotation)) < 0.3f) - { - MoveLimb(leftFoot, footPos + transformedFootPos, 1.0f); - } + MoveLimb(rightFoot, footPos - transformedFootPos, 1.0f); + MoveLimb(leftFoot, footPos + transformedFootPos, 1.0f); handPos = (torso.SimPosition + head.SimPosition) / 2.0f; - //if (!rightHand.Disabled) rightHand.body.ApplyTorque(leftHand.body.Mass * Dir); - //if (!leftHand.Disabled) leftHand.body.ApplyTorque(leftHand.body.Mass * Dir); - //at the surface, not moving sideways -> hands just float around if (!headInWater && TargetMovement.X == 0.0f && TargetMovement.Y > 0) { handPos.X = handPos.X + Dir * 0.6f; - float wobbleAmount = 0.05f; + float wobbleAmount = 0.1f; if (!rightHand.Disabled) { MoveLimb(rightHand, new Vector2( handPos.X + (float)Math.Sin(walkPos / 1.5f) * wobbleAmount, - handPos.Y + (float)Math.Sin(walkPos / 3.5f) * wobbleAmount - 0.0f), 1.5f); + handPos.Y + (float)Math.Sin(walkPos / 3.5f) * wobbleAmount - 0.25f), 1.5f); } if (!leftHand.Disabled) { MoveLimb(leftHand, new Vector2( handPos.X + (float)Math.Sin(walkPos / 2.0f) * wobbleAmount, - handPos.Y + (float)Math.Sin(walkPos / 3.0f) * wobbleAmount - 0.0f), 1.5f); + handPos.Y + (float)Math.Sin(walkPos / 3.0f) * wobbleAmount - 0.25f), 1.5f); } return; @@ -772,8 +792,8 @@ namespace Barotrauma handPos += head.LinearVelocity * 0.1f; - float handCyclePos = walkPos / 2.0f; - float handPosX = (float)Math.Cos(handCyclePos * Dir) * 0.4f; + float handCyclePos = walkPos / 3.0f * -Dir; + float handPosX = (float)Math.Cos(handCyclePos) * 0.4f; float handPosY = (float)Math.Sin(handCyclePos) * 1.0f; handPosY = MathHelper.Clamp(handPosY, -0.8f, 0.8f); @@ -782,21 +802,18 @@ namespace Barotrauma if (!rightHand.Disabled) { Vector2 rightHandPos = new Vector2(-handPosX, -handPosY); - rightHandPos.X = (Dir == 1.0f) ? Math.Max(0.2f, rightHandPos.X) : Math.Min(-0.2f, rightHandPos.X); + rightHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, rightHandPos.X) : Math.Min(-0.3f, rightHandPos.X); rightHandPos = Vector2.Transform(rightHandPos, rotationMatrix); - //MoveLimb(rightHand, handPos + rightHandPos, 1.5f); - HandIK(rightHand, handPos + rightHandPos, 0.5f); } if (!leftHand.Disabled) { Vector2 leftHandPos = new Vector2(handPosX, handPosY); - leftHandPos.X = (Dir == 1.0f) ? Math.Max(0.2f, leftHandPos.X) : Math.Min(-0.2f, leftHandPos.X); + leftHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, leftHandPos.X) : Math.Min(-0.3f, leftHandPos.X); leftHandPos = Vector2.Transform(leftHandPos, rotationMatrix); - //MoveLimb(leftHand, handPos + leftHandPos,1.5f); HandIK(leftHand, handPos + leftHandPos, 0.5f); } } @@ -813,10 +830,6 @@ namespace Barotrauma IgnorePlatforms = true; Vector2 tempTargetMovement = TargetMovement; - //if (TargetMovement.Y != 0.0f) - //{ - // tempTargetMovement.Y = Math.Max(Math.Abs(TargetMovement.Y), 0.6f) * Math.Sign(TargetMovement.Y); - //} movement = MathUtils.SmoothStep(movement, tempTargetMovement, 0.3f); Limb leftFoot = GetLimb(LimbType.LeftFoot); diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index ac9c5b529..d60c9640f 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -279,10 +279,11 @@ namespace Barotrauma if (collider == null) { DebugConsole.ThrowError("No collider configured for ''"+character.Name+"''!"); - collider = new PhysicsBody(0.0f, 0.0f, 16.0f, 5.0f); + collider = new PhysicsBody(0.0f, 0.0f, 0.1f, 5.0f); } collider.CollisionCategories = Physics.CollisionCharacter; + collider.FarseerBody.AngularDamping = 5.0f; collider.FarseerBody.FixedRotation = true; collider.FarseerBody.OnCollision += OnLimbCollision; @@ -388,71 +389,30 @@ namespace Barotrauma else if (structure.StairDirection != Direction.None) { stairs = null; - - //--------------- + //don't collider with stairs if + + //1. bottom of the collider is at the bottom of the stairs and the character isn't trying to move upwards float stairBottomPos = ConvertUnits.ToSimUnits(structure.Rect.Y - structure.Rect.Height + 10); if (colliderBottom.Y < stairBottomPos && targetMovement.Y < 0.5f) return false; - //--------------- - + //2. bottom of the collider is at the top of the stairs and the character isn't trying to move downwards if (targetMovement.Y >= 0.0f && colliderBottom.Y >= ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y*5)) return false; - - //--------------- - + + //3. collided with the stairs from below if (contact.Manifold.LocalNormal.Y < 0.0f) return false; - //--------------- - + //4. contact points is above the bottom half of the collider Vector2 normal; FarseerPhysics.Common.FixedArray2 points; - contact.GetWorldManifold(out normal, out points); if (points[0].Y > collider.SimPosition.Y) return false; - //--------------- - + //5. in water if (inWater && targetMovement.Y < 0.5f) return false; //--------------- stairs = structure; - - //float stairPosY = structure.StairDirection == Direction.Right ? - // lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X); - - - //if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY - 10.0f) return false; - - - - //if (targetMovement.Y < 0.5f) - //{ - // if (inWater || lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + 50.0f) - // { - // stairs = null; - // return false; - // } - //} - - - - //if (limb != null)// && (limb.type == LimbType.LeftFoot || limb.type == LimbType.RightFoot)) - //{ - // if (contact.Manifold.LocalNormal.Y >= 0.0f) - // { - // if (limb.SimPosition.Y < lowestLimb.SimPosition.Y+0.2f) - // { - // stairs = structure; - // return true; - // } - - // } - // else - // { - // stairs = null; - // return false; - // } - //} } CalculateImpact(f1, f2, contact); @@ -478,13 +438,11 @@ namespace Barotrauma float impact = Vector2.Dot(velocity, -normal); + float volume = Math.Min(impact, 1.0f); if (f1.Body.UserData is Limb) { Limb limb = (Limb)f1.Body.UserData; - - float volume = stairs == null ? impact / 5.0f : impact; - volume = Math.Min(impact, 1.0f); - + if (impact > 0.5f && limb.HitSound != null && limb.soundTimer <= 0.0f) { limb.soundTimer = Limb.SoundInterval; @@ -496,11 +454,11 @@ namespace Barotrauma if (!character.IsNetworkPlayer || GameMain.Server != null) { character.AddDamage(CauseOfDeath.Damage, impact - 8.0f, null); - + if (impact > 8.0f) SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, collider); strongestImpact = Math.Max(strongestImpact, impact - 8.0f); } - SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, collider); + if (Character.Controlled == character) GameMain.GameScreen.Cam.Shake = strongestImpact; } @@ -532,21 +490,11 @@ namespace Barotrauma if (currentHull != null) pos += currentHull.Submarine.DrawPosition; pos.Y = -pos.Y; GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), Color.Red, true, 0.01f); - - //if (limb.AnimTargetPos == Vector2.Zero) continue; - - //Vector2 pos2 = ConvertUnits.ToDisplayUnits(limb.AnimTargetPos); - //pos2.Y = -pos2.Y; - //GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos2.X, (int)pos2.Y, 5, 5), Color.Blue, true, 0.01f); - - //GUI.DrawLine(spriteBatch, pos, pos2, Color.Green); } limb.body.DebugDraw(spriteBatch, character.Submarine == null ? Color.Cyan : Color.White); } - - - + collider.DebugDraw(spriteBatch, character.Submarine == null ? Color.Cyan : Color.White); foreach (RevoluteJoint joint in limbJoints) @@ -765,8 +713,6 @@ namespace Barotrauma Vector2 flowForce = Vector2.Zero; - //FindLowestLimb(); - FindHull(); splashSoundTimer -= deltaTime; @@ -784,10 +730,26 @@ namespace Barotrauma inWater = false; headInWater = false; + var colliderB = GetColliderBottom().Y; + float surf = ConvertUnits.ToSimUnits(currentHull.Surface); + if (currentHull.Volume > currentHull.FullVolume * 0.95f || - ConvertUnits.ToSimUnits(currentHull.Surface) - GetColliderBottom().Y > HeadPosition * 0.95f) + ConvertUnits.ToSimUnits(currentHull.Surface) - GetFloorY() > HeadPosition * 0.95f) inWater = true; } + + if (flowForce.LengthSquared() > 0.001f) + { + collider.ApplyForce(flowForce); + } + + if (currentHull==null || + currentHull.Volume > currentHull.FullVolume * 0.95f || + ConvertUnits.ToSimUnits(currentHull.Surface) > collider.SimPosition.Y) + { + collider.ApplyWaterForces(); + } + foreach (Limb limb in Limbs) { @@ -809,10 +771,9 @@ namespace Barotrauma { limb.inWater = true; - if (flowForce.Length() > 0.01f) + if (flowForce.LengthSquared() > 0.001f) { limb.body.ApplyForce(flowForce); - if (flowForce.Length() > 15.0f) surfaceY = limbHull.Surface; } surfaceY = limbHull.Surface; @@ -820,7 +781,6 @@ namespace Barotrauma if (limb.type == LimbType.Head) { headInWater = true; - surfaceY = limbHull.Surface; } } //the limb has gone through the surface of the water @@ -828,9 +788,9 @@ namespace Barotrauma { //create a splash particle - GameMain.ParticleManager.CreateParticle("watersplash", + var p = GameMain.ParticleManager.CreateParticle("watersplash", new Vector2(limb.Position.X, limbHull.Surface) + limbHull.Submarine.Position, - new Vector2(0.0f, Math.Abs(-limb.LinearVelocity.Y * 10.0f)), + new Vector2(0.0f, Math.Abs(-limb.LinearVelocity.Y * 20.0f)), 0.0f, limbHull); GameMain.ParticleManager.CreateParticle("bubbles", @@ -860,7 +820,65 @@ namespace Barotrauma } limb.Update(deltaTime); - } + } + } + + private float GetFloorY() + { + Vector2 rayStart = collider.SimPosition; + Vector2 rayEnd = rayStart - new Vector2(0.0f, TorsoPosition); + + var lowestLimb = FindLowestLimb(); + + float closestFraction = 1; + GameMain.World.RayCast((fixture, point, normal, fraction) => + { + switch (fixture.CollisionCategories) + { + case Physics.CollisionStairs: + if (inWater && TargetMovement.Y < 0.5f) return -1; + //Structure structure = fixture.Body.UserData as Structure; + //if (stairs == null && structure != null) + //{ + // if (LowestLimb.SimPosition.Y < structure.SimPosition.Y) + // { + // return -1; + // } + // else + // { + // stairs = structure; + // } + //} + break; + case Physics.CollisionPlatform: + Structure platform = fixture.Body.UserData as Structure; + if (IgnorePlatforms || lowestLimb.Position.Y < platform.Rect.Y) return -1; + break; + case Physics.CollisionWall: + break; + default: + return -1; + } + + if (fraction < closestFraction) + { + closestFraction = fraction; + } + + return closestFraction; + } + , rayStart, rayEnd); + + + if (closestFraction == 1) //raycast didn't hit anything + { + return (currentHull == null) ? -1000.0f : ConvertUnits.ToSimUnits(currentHull.Rect.Y - currentHull.Rect.Height); + } + else + { + return rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction; + } + } public void SetPosition(Vector2 simPosition, bool lerp = false) diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index 3a64d27ae..05e254bb6 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -441,31 +441,7 @@ namespace Barotrauma if (inWater) { - //buoyancy - Vector2 buoyancy = new Vector2(0, Mass * 9.6f); - - //drag - Vector2 velDir = Vector2.Normalize(LinearVelocity); - - Vector2 line = new Vector2((float)Math.Cos(body.Rotation), (float)Math.Sin(body.Rotation)); - line *= ConvertUnits.ToSimUnits(sprite.size.Y); - - Vector2 normal = new Vector2(-line.Y, line.X); - normal = Vector2.Normalize(-normal); - - float dragDot = Math.Abs(Vector2.Dot(normal, velDir)); - Vector2 dragForce = Vector2.Zero; - if (dragDot > 0) - { - float vel = LinearVelocity.Length()*2.0f; - float drag = dragDot * vel * vel - * ConvertUnits.ToSimUnits(sprite.size.Y); - dragForce = Math.Min(drag, Mass*1000.0f) * -velDir; - //if (dragForce.Length() > 100.0f) { } - } - - body.ApplyForce(dragForce + buoyancy); - body.ApplyTorque(body.AngularVelocity * body.Mass * -0.08f); + body.ApplyWaterForces(); } if (character.IsDead) return; diff --git a/Subsurface/Source/Items/Components/Holdable/Propulsion.cs b/Subsurface/Source/Items/Components/Holdable/Propulsion.cs index eb63e15d4..25f730f0d 100644 --- a/Subsurface/Source/Items/Components/Holdable/Propulsion.cs +++ b/Subsurface/Source/Items/Components/Holdable/Propulsion.cs @@ -71,23 +71,18 @@ namespace Barotrauma.Items.Components if (character.AnimController.InWater) character.AnimController.TargetMovement = dir; - if (item.body.Enabled && false) + foreach (Limb limb in character.AnimController.Limbs) { - item.body.ApplyForce(propulsion); + if (limb.WearingItems.Find(w => w.WearableComponent.Item == this.item)==null) continue; + + limb.body.ApplyForce(propulsion); } - else - { - foreach (Limb limb in character.AnimController.Limbs) - { - if (limb.WearingItems.Find(w => w.WearableComponent.Item == this.item)==null) continue; - limb.body.ApplyForce(propulsion); - } + character.AnimController.Collider.ApplyForce(propulsion); - if (character.SelectedItems[0] == item) character.AnimController.GetLimb(LimbType.RightHand).body.ApplyForce(propulsion); - - if (character.SelectedItems[1] == item) character.AnimController.GetLimb(LimbType.LeftHand).body.ApplyForce(propulsion); - } + if (character.SelectedItems[0] == item) character.AnimController.GetLimb(LimbType.RightHand).body.ApplyForce(propulsion); + if (character.SelectedItems[1] == item) character.AnimController.GetLimb(LimbType.LeftHand).body.ApplyForce(propulsion); + if (!string.IsNullOrWhiteSpace(particles)) { diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index 805201bf4..22937b677 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -422,7 +422,6 @@ namespace Barotrauma Structure structure = fixture.Body.UserData as Structure; if (structure != null) { - if (!structure.HasBody) return -1; if (structure.IsPlatform && collisionCategory != null && !((Category)collisionCategory).HasFlag(Physics.CollisionPlatform)) return -1; } diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 91f304f15..0b95234df 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -558,6 +558,8 @@ namespace Barotrauma { limb.body.ApplyLinearImpulse(limb.Mass * impulse); } + + c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse); } foreach (Item item in Item.ItemList) diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index 37bc9b2cf..49644e33c 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -352,6 +352,39 @@ namespace Barotrauma body.ApplyLinearImpulse((deltaPos - vel * 0.5f) * body.Mass, (Vector2)pullPos); } + /// + /// Applies buoyancy, drag and angular drag caused by water + /// + public void ApplyWaterForces() + { + //buoyancy + Vector2 buoyancy = new Vector2(0, Mass * 9.6f); + + //drag + Vector2 velDir = Vector2.Normalize(LinearVelocity); + + Vector2 line = new Vector2((float)Math.Cos(body.Rotation), (float)Math.Sin(body.Rotation)); + line *= Math.Max(height + radius*2, height); + + Vector2 normal = new Vector2(-line.Y, line.X); + normal = Vector2.Normalize(-normal); + + float dragDot = Math.Abs(Vector2.Dot(normal, velDir)); + Vector2 dragForce = Vector2.Zero; + if (dragDot > 0) + { + float vel = LinearVelocity.Length() * 2.0f; + float drag = dragDot * vel * vel + * Math.Max(height + radius * 2, height); + dragForce = Math.Min(drag, Mass * 1000.0f) * -velDir; + //if (dragForce.Length() > 100.0f) { } + } + + body.ApplyForce(dragForce + buoyancy); + body.ApplyTorque(body.AngularVelocity * body.Mass * -0.08f); + } + + public void UpdateDrawPosition() { drawPosition = Timing.Interpolate(prevPosition, body.Position) - offsetFromTargetPos;