From 641e579e9284188534a4109831f72737c6e39d9c Mon Sep 17 00:00:00 2001 From: Regalis Date: Sat, 22 Oct 2016 15:18:16 +0300 Subject: [PATCH 1/5] Backported animcontroller-overhaul --- .../Factories/BodyFactory.cs | 23 + .../Characters/Charybdis/charybdis.xml | 2 + .../Content/Characters/Coelanth/coelanth.xml | 4 +- .../Content/Characters/Crawler/crawler.xml | 24 +- .../Content/Characters/Endworm/endworm.xml | 14 +- .../Fractalguardian/fractalguardian.xml | 3 +- .../Fractalguardian2/fractalguardian2.xml | 4 +- Subsurface/Content/Characters/Human/human.xml | 6 +- Subsurface/Content/Characters/Husk/husk.xml | 6 +- .../Content/Characters/Mantis/mantis.xml | 2 + .../Content/Characters/Moloch/moloch.xml | 4 +- .../TigerThresher/tigerthresher.xml | 4 +- .../Content/Characters/Watcher/watcher.xml | 15 +- .../Source/Characters/AI/AIController.cs | 2 +- .../Source/Characters/AI/HumanAIController.cs | 23 +- .../Characters/AI/IndoorsSteeringManager.cs | 52 +- .../AI/Objectives/AIObjectiveCombat.cs | 11 +- Subsurface/Source/Characters/AI/PathFinder.cs | 7 +- .../Source/Characters/AI/SteeringManager.cs | 7 + Subsurface/Source/Characters/AICharacter.cs | 20 +- .../Characters/Animation/AnimController.cs | 9 +- .../Animation/FishAnimController.cs | 326 +++------- .../Animation/HumanoidAnimController.cs | 475 ++++++-------- .../Source/Characters/Animation/Ragdoll.cs | 610 +++++++++++------- Subsurface/Source/Characters/Character.cs | 201 ++++-- Subsurface/Source/Characters/Limb.cs | 75 +-- Subsurface/Source/DebugConsole.cs | 2 +- .../Items/Components/Holdable/Pickable.cs | 2 +- .../Items/Components/Holdable/Propulsion.cs | 21 +- .../Items/Components/Machines/Controller.cs | 4 +- .../Source/Items/Components/Projectile.cs | 13 +- Subsurface/Source/Map/Submarine.cs | 1 - Subsurface/Source/Map/SubmarineBody.cs | 9 +- Subsurface/Source/Networking/GameClient.cs | 2 +- Subsurface/Source/Networking/GameServer.cs | 2 +- Subsurface/Source/Physics/Physics.cs | 2 - Subsurface/Source/Physics/PhysicsBody.cs | 166 ++++- .../Source/Screens/EditCharacterScreen.cs | 10 +- Subsurface/Source/Screens/GameScreen.cs | 1 + 39 files changed, 1169 insertions(+), 995 deletions(-) diff --git a/Farseer Physics Engine 3.5/Factories/BodyFactory.cs b/Farseer Physics Engine 3.5/Factories/BodyFactory.cs index 8ef734a6f..2bc288197 100644 --- a/Farseer Physics Engine 3.5/Factories/BodyFactory.cs +++ b/Farseer Physics Engine 3.5/Factories/BodyFactory.cs @@ -192,6 +192,29 @@ namespace FarseerPhysics.Factories return body; } + public static Body CreateCapsuleHorizontal(World world, float width, float endRadius, float density, + object userData = null) + { + //Create the middle rectangle + Vertices rectangle = PolygonTools.CreateRectangle(width / 2, endRadius); + + List list = new List(); + list.Add(rectangle); + + Body body = CreateCompoundPolygon(world, list, density, userData); + body.UserData = userData; + + //Create the two circles + CircleShape topCircle = new CircleShape(endRadius, density); + topCircle.Position = new Vector2(width / 2, 0); + body.CreateFixture(topCircle); + + CircleShape bottomCircle = new CircleShape(endRadius, density); + bottomCircle.Position = new Vector2(-(width / 2), 0); + body.CreateFixture(bottomCircle); + return body; + } + /// /// Creates a rounded rectangle. /// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices) diff --git a/Subsurface/Content/Characters/Charybdis/charybdis.xml b/Subsurface/Content/Characters/Charybdis/charybdis.xml index a1574b013..fa5caf861 100644 --- a/Subsurface/Content/Characters/Charybdis/charybdis.xml +++ b/Subsurface/Content/Characters/Charybdis/charybdis.xml @@ -5,6 +5,8 @@ + + diff --git a/Subsurface/Content/Characters/Coelanth/coelanth.xml b/Subsurface/Content/Characters/Coelanth/coelanth.xml index 02a9f67ab..d32181c38 100644 --- a/Subsurface/Content/Characters/Coelanth/coelanth.xml +++ b/Subsurface/Content/Characters/Coelanth/coelanth.xml @@ -5,8 +5,10 @@ - + + + diff --git a/Subsurface/Content/Characters/Crawler/crawler.xml b/Subsurface/Content/Characters/Crawler/crawler.xml index ca7e38e98..313a7867d 100644 --- a/Subsurface/Content/Characters/Crawler/crawler.xml +++ b/Subsurface/Content/Characters/Crawler/crawler.xml @@ -7,52 +7,54 @@ + + - + - + 0 - + - + - + - + - + - + - + - + diff --git a/Subsurface/Content/Characters/Endworm/endworm.xml b/Subsurface/Content/Characters/Endworm/endworm.xml index 6abd89cdc..157c81d7a 100644 --- a/Subsurface/Content/Characters/Endworm/endworm.xml +++ b/Subsurface/Content/Characters/Endworm/endworm.xml @@ -7,6 +7,8 @@ + + @@ -18,27 +20,27 @@ - + - + - + - + - + - + diff --git a/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml b/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml index c7e2aa8ff..ee99fe1d0 100644 --- a/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml +++ b/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml @@ -6,10 +6,11 @@ + - + diff --git a/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml b/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml index e13311179..c772e9b69 100644 --- a/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml +++ b/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml @@ -6,10 +6,12 @@ + + - + diff --git a/Subsurface/Content/Characters/Human/human.xml b/Subsurface/Content/Characters/Human/human.xml index 1fdb2ec3a..3731b78be 100644 --- a/Subsurface/Content/Characters/Human/human.xml +++ b/Subsurface/Content/Characters/Human/human.xml @@ -8,7 +8,11 @@ walkanimspeed="4.58" movementlerp="0.4" legtorque="15.0" - thightorque="-5.0"> + thightorque="-5.0" + walkspeed="1.5" + 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/Content/Characters/Mantis/mantis.xml b/Subsurface/Content/Characters/Mantis/mantis.xml index c5c53f194..cfcd6f781 100644 --- a/Subsurface/Content/Characters/Mantis/mantis.xml +++ b/Subsurface/Content/Characters/Mantis/mantis.xml @@ -15,6 +15,8 @@ footrotation ="180.0" flip="true"> + + diff --git a/Subsurface/Content/Characters/Moloch/moloch.xml b/Subsurface/Content/Characters/Moloch/moloch.xml index bd7ebcbce..aba30598b 100644 --- a/Subsurface/Content/Characters/Moloch/moloch.xml +++ b/Subsurface/Content/Characters/Moloch/moloch.xml @@ -8,10 +8,12 @@ + + - + diff --git a/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml b/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml index 8cd6014e6..0284b6405 100644 --- a/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml +++ b/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml @@ -5,8 +5,10 @@ - + + + diff --git a/Subsurface/Content/Characters/Watcher/watcher.xml b/Subsurface/Content/Characters/Watcher/watcher.xml index 8c7a24fff..c83554741 100644 --- a/Subsurface/Content/Characters/Watcher/watcher.xml +++ b/Subsurface/Content/Characters/Watcher/watcher.xml @@ -3,30 +3,27 @@ + + - + - + - - + - - + - - - diff --git a/Subsurface/Source/Characters/AI/AIController.cs b/Subsurface/Source/Characters/AI/AIController.cs index 165579fff..9c1ac2aa7 100644 --- a/Subsurface/Source/Characters/AI/AIController.cs +++ b/Subsurface/Source/Characters/AI/AIController.cs @@ -41,7 +41,7 @@ namespace Barotrauma public Vector2 Velocity { - get { return Character.AnimController.RefLimb.LinearVelocity; } + get { return Character.AnimController.Collider.LinearVelocity; } } public AiState State diff --git a/Subsurface/Source/Characters/AI/HumanAIController.cs b/Subsurface/Source/Characters/AI/HumanAIController.cs index 300ceb8ef..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; - } - - if (Character.AnimController.Stairs != null) - { - float yDiff = currPath.CurrentNode.WorldPosition.Y - Character.WorldPosition.Y; - - if (Math.Abs(yDiff)>10.0f) - { - int dir = Math.Sign(yDiff); - - float movement = Character.AnimController.Stairs.StairDirection == Direction.Right ? - dir * Character.AnimController.TargetMovement.Length() : -dir * Character.AnimController.TargetMovement.Length(); - - Character.AnimController.TargetMovement = new Vector2(movement, 0.0f); - } + ignorePlatforms = true; } } + 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 83c22d31b..a377b7ca9 100644 --- a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs @@ -88,6 +88,15 @@ 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 && + character.AnimController.Anim != AnimController.Animation.Climbing && + 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 +104,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) { @@ -111,7 +120,7 @@ namespace Barotrauma if (canOpenDoors && !character.LockHands) CheckDoorsInPath(); float allowedDistance = character.AnimController.InWater ? 1.0f : 0.6f; - if (currentPath.CurrentNode!=null && currentPath.CurrentNode.SimPosition.Y > character.SimPosition.Y+1.0f) allowedDistance*=0.5f; + //if (currentPath.CurrentNode!=null && currentPath.CurrentNode.SimPosition.Y > character.SimPosition.Y+1.0f) allowedDistance*=0.5f; Vector2 pos = host.SimPosition; @@ -139,7 +148,15 @@ namespace Barotrauma } } - currentPath.CheckProgress(pos, allowedDistance); + var collider = character.AnimController.Collider; + + Vector2 colliderBottom = character.AnimController.GetColliderBottom(); + if (Math.Abs(collider.SimPosition.X - currentPath.CurrentNode.SimPosition.X) < collider.radius*2 && + currentPath.CurrentNode.SimPosition.Y > colliderBottom.Y && + currentPath.CurrentNode.SimPosition.Y < colliderBottom.Y + collider.height + collider.radius*2) + { + currentPath.SkipToNextNode(); + } if (currentPath.CurrentNode == null) return Vector2.Zero; @@ -147,20 +164,31 @@ namespace Barotrauma if (character.AnimController.Anim == AnimController.Animation.Climbing) { - float x = currentPath.CurrentNode.SimPosition.X - pos.X; - float y = (currentPath.CurrentNode.SimPosition.Y) - pos.Y; + Vector2 diff = currentPath.CurrentNode.SimPosition - pos; - if (Math.Abs(x) < Math.Abs(y) * 10.0f) + if (currentPath.CurrentNode.Ladders != null) { - x = 0.0f; - } - else if (character.AnimController.LowestLimb != null && hull != null) - { - if (character.AnimController.LowestLimb.Position.Y < hull.Rect.Y - hull.Rect.Height + 10.0f) x = 0.0f; + //climbing ladders -> don't move horizontally + diff.X = 0.0f; + + //at the same height as the waypoint + if (currentPath.CurrentNode.SimPosition.Y > colliderBottom.Y && + currentPath.CurrentNode.SimPosition.Y < colliderBottom.Y + collider.height + collider.radius * 2) + { + float heightFromFloor = character.AnimController.GetColliderBottom().Y - character.AnimController.FloorY; + + //we can safely skip to the next waypoint if the character is at a safe height above the floor, + //or if the next waypoint in the path is also on ladders + if ((heightFromFloor > 0.0f && heightFromFloor < collider.height) || + (currentPath.NextNode != null && currentPath.NextNode.Ladders != null)) + { + currentPath.SkipToNextNode(); + } + } } character.AnimController.IgnorePlatforms = false; - return new Vector2(x,y); + return diff; } return currentPath.CurrentNode.SimPosition - pos; diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveCombat.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveCombat.cs index 5d4cf2216..121756943 100644 --- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -90,11 +90,12 @@ namespace Barotrauma escapeObjective.TryComplete(deltaTime); - if (Vector2.Distance(character.SimPosition, enemy.SimPosition) < 3.0f) - { - character.AIController.SteeringManager.SteeringManual(deltaTime, (character.SimPosition - enemy.SimPosition)*0.1f); - coolDownTimer = CoolDown; - } + //if (Vector2.Distance(character.SimPosition, enemy.SimPosition) < 3.0f) + //{ + // character.AIController.SteeringManager.SteeringManual(deltaTime, + // new Vector2(Math.Sign(character.SimPosition.X - enemy.SimPosition.X), 0.0f)); + // coolDownTimer = CoolDown; + //} } public override bool IsCompleted() diff --git a/Subsurface/Source/Characters/AI/PathFinder.cs b/Subsurface/Source/Characters/AI/PathFinder.cs index 984cd01fe..45dd9a4c5 100644 --- a/Subsurface/Source/Characters/AI/PathFinder.cs +++ b/Subsurface/Source/Characters/AI/PathFinder.cs @@ -168,8 +168,11 @@ 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); - if (body != null && body.UserData is Structure) continue; + var body = Submarine.PickBody( + start, node.Waypoint.SimPosition, null, + Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionStairs | Physics.CollisionPlatform); + + if (body != null && body.UserData is Structure && !((Structure)body.UserData).IsPlatform) continue; } closestDist = dist; 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/AICharacter.cs b/Subsurface/Source/Characters/AICharacter.cs index 1a3613b8b..cf48cf5a9 100644 --- a/Subsurface/Source/Characters/AICharacter.cs +++ b/Subsurface/Source/Characters/AICharacter.cs @@ -95,8 +95,8 @@ namespace Barotrauma return true; case NetworkEventType.ImportantEntityUpdate: - message.Write(AnimController.RefLimb.SimPosition.X); - message.Write(AnimController.RefLimb.SimPosition.Y); + message.Write(AnimController.MainLimb.SimPosition.X); + message.Write(AnimController.MainLimb.SimPosition.Y); //message.Write(AnimController.RefLimb.Rotation); @@ -129,9 +129,9 @@ namespace Barotrauma message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.Y, -1.0f, 1.0f), -1.0f, 1.0f, 4); if (AnimController.CanEnterSubmarine) message.Write(Submarine != null); - - message.Write(AnimController.RefLimb.SimPosition.X); - message.Write(AnimController.RefLimb.SimPosition.Y); + + message.Write(AnimController.MainLimb.SimPosition.X); + message.Write(AnimController.MainLimb.SimPosition.Y); return true; case NetworkEventType.InventoryUpdate: @@ -162,8 +162,8 @@ namespace Barotrauma return base.ReadNetworkData(type, message, sendingTime, out data); case NetworkEventType.ImportantEntityUpdate: - Vector2 limbPos = AnimController.RefLimb.SimPosition; - float rotation = AnimController.RefLimb.Rotation; + Vector2 limbPos = AnimController.MainLimb.SimPosition; + float rotation = AnimController.MainLimb.Rotation; try { @@ -180,9 +180,9 @@ namespace Barotrauma return false; } - if (AnimController.RefLimb.body != null) + if (AnimController.MainLimb.body != null) { - AnimController.RefLimb.body.TargetPosition = limbPos; + AnimController.MainLimb.body.TargetPosition = limbPos; //AnimController.RefLimb.body.TargetRotation = rotation; } @@ -255,7 +255,7 @@ namespace Barotrauma AnimController.TargetDir = (targetDir) ? Direction.Right : Direction.Left; AnimController.TargetMovement = targetMovement; - AnimController.RefLimb.body.TargetPosition = pos; + AnimController.MainLimb.body.TargetPosition = pos; //AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime); if (inSub) diff --git a/Subsurface/Source/Characters/Animation/AnimController.cs b/Subsurface/Source/Characters/Animation/AnimController.cs index 7231ac355..5b9ebc1cc 100644 --- a/Subsurface/Source/Characters/Animation/AnimController.cs +++ b/Subsurface/Source/Characters/Animation/AnimController.cs @@ -1,6 +1,7 @@ using System.Xml.Linq; using FarseerPhysics; using Microsoft.Xna.Framework; +using System.Collections.Generic; namespace Barotrauma { @@ -9,8 +10,6 @@ namespace Barotrauma public enum Animation { None, Climbing, UsingConstruction, Struggle, CPR }; public Animation Anim; - public Direction TargetDir; - protected Character character; protected float walkSpeed, swimSpeed; @@ -25,6 +24,8 @@ namespace Barotrauma protected readonly Vector2 stepSize; protected readonly float legTorque; + + public float StunTimer { get { return stunTimer; } @@ -52,6 +53,8 @@ namespace Barotrauma //impactTolerance = ToolBox.GetAttributeFloat(element, "impacttolerance", 10.0f); legTorque = ToolBox.GetAttributeFloat(element, "legtorque", 0.0f); + + } public virtual void UpdateAnim(float deltaTime) { } @@ -59,5 +62,7 @@ namespace Barotrauma public virtual void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle) { } public virtual void DragCharacter(Character target, LimbType rightHandTarget = LimbType.RightHand, LimbType leftHandTarget = LimbType.LeftHand) { } + + } } diff --git a/Subsurface/Source/Characters/Animation/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs index a800dd0e1..9afc2afb2 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -47,12 +47,34 @@ namespace Barotrauma public override void UpdateAnim(float deltaTime) { - if (character.IsDead) + if (Frozen) return; + + if (character.IsDead || character.IsUnconscious || stunTimer > 0.0f) { - UpdateDying(deltaTime); + collider.PhysEnabled = false; + collider.SetTransform(MainLimb.SimPosition, 0.0f); + + if (stunTimer > 0.0f) + { + stunTimer -= deltaTime; + } + return; } + //re-enable collider + if (!collider.FarseerBody.Enabled) + { + 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); + + collider.FarseerBody.Enabled = true; + } + ResetPullJoints(); if (strongestImpact > 0.0f) @@ -61,31 +83,32 @@ namespace Barotrauma strongestImpact = 0.0f; } - if (stunTimer>0.0f) + + if (inWater) { - //UpdateStruggling(deltaTime); - stunTimer -= deltaTime; - return; + collider.FarseerBody.FixedRotation = false; + UpdateSineAnim(deltaTime); } - else if (SimplePhysicsEnabled) + else if (currentHull != null && CanEnterSubmarine) { - UpdateSimpleAnim(); - } - else - { - if (inWater || RefLimb.inWater) + if (Math.Abs(MathUtils.GetShortestAngle(collider.Rotation, 0.0f)) > 0.001f) { - UpdateSineAnim(deltaTime); + //rotate collider back upright + collider.AngularVelocity = MathUtils.GetShortestAngle(collider.Rotation, 0.0f) * 60.0f; + collider.FarseerBody.FixedRotation = false; } - else if (currentHull != null && CanEnterSubmarine) + else { - UpdateWalkAnim(deltaTime); + collider.FarseerBody.FixedRotation = true; } + + UpdateWalkAnim(deltaTime); } + if (mirror || !inWater) { - if (!character.IsNetworkPlayer) + if (!character.IsRemotePlayer) { //targetDir = (movement.X > 0.0f) ? Direction.Right : Direction.Left; if (targetMovement.X > 0.1f && targetMovement.X > Math.Abs(targetMovement.Y) * 0.5f) @@ -125,10 +148,10 @@ namespace Barotrauma if (TargetDir != dir) { - if (flipTimer>1.0f || character.IsNetworkPlayer) + if (flipTimer>1.0f || character.IsRemotePlayer) { Flip(); - if (mirror) Mirror(); + if (mirror || !inWater) Mirror(); flipTimer = 0.0f; } } @@ -137,11 +160,27 @@ namespace Barotrauma void UpdateSineAnim(float deltaTime) { movement = TargetMovement*swimSpeed; + + Limb torso = GetLimb(LimbType.Torso); + Limb head = GetLimb(LimbType.Head); + + MainLimb.pullJoint.Enabled = true; + MainLimb.pullJoint.WorldAnchorB = collider.SimPosition; + if (movement.LengthSquared() < 0.00001f) return; - if (!inWater) movement.Y = Math.Min(0.0f, movement.Y); - float movementAngle = MathUtils.VectorToAngle(movement) - MathHelper.PiOver2; + + if (rotateTowardsMovement) + { + collider.SmoothRotate(movementAngle, 25.0f); + MainLimb.body.SmoothRotate(movementAngle, 25.0f); + } + else + { + collider.SmoothRotate(HeadAngle * Dir, 25.0f); + MainLimb.body.SmoothRotate(HeadAngle * Dir, 25.0f); + } Limb tail = GetLimb(LimbType.Tail); if (tail != null && waveAmplitude > 0.0f) @@ -151,100 +190,28 @@ namespace Barotrauma float waveRotation = (float)Math.Sin(walkPos / waveLength); tail.body.ApplyTorque(waveRotation * tail.Mass * 100.0f * waveAmplitude); - - //limbs[tailIndex].body.ApplyTorque((Math.Sign(angle) + Math.Max(Math.Min(angle * 10.0f, 10.0f), -10.0f)) * limbs[tailIndex].body.Mass); - //limbs[tailIndex].body.ApplyTorque(-limbs[tailIndex].body.AngularVelocity * 0.5f * limbs[tailIndex].body.Mass); } - Vector2 steerForce = Vector2.Zero; - - Limb head = GetLimb(LimbType.Head); - if (head == null) head = GetLimb(LimbType.Torso); - - if (head != null) - { - float angle = (rotateTowardsMovement) ? - head.body.Rotation+ MathUtils.GetShortestAngle(head.body.Rotation, movementAngle) : - HeadAngle*Dir; - - - head.body.SmoothRotate(angle, 25.0f); - //rotate head towards the angle of movement - //float torque = (Math.Sign(angle)*10.0f + MathHelper.Clamp(angle * 10.0f, -10.0f, 10.0f)); - //angular drag - //torque -= head.body.AngularVelocity * 0.5f; - //head.body.ApplyTorque(torque * head.body.Mass); - - - //the movement vector if going to the direction of the head - //Vector2 headMovement = new Vector2( - // (float)Math.Cos(head.body.Rotation - MathHelper.PiOver2), - // (float)Math.Sin(head.body.Rotation - MathHelper.PiOver2)); - //headMovement *= movement.Length(); - - //the movement angle is between direction of the head and the direction - //where the Character is actually trying to go - - //current * (float)alpha + previous * (1.0f - (float)alpha); - - - steerForce = (movement+correctionMovement) * 50.0f - head.LinearVelocity * 30.0f; - // force += (headMovement - movement) * Math.Min(head.LinearVelocity.Length()/movement.Length(), 1.0f); - - if (!inWater) steerForce.Y = 0.0f; - } for (int i = 0; i < Limbs.Count(); i++) { - if (steerForce != Vector2.Zero) - { - Vector2 pullPos = Limbs[i].pullJoint == null ? Limbs[i].SimPosition : Limbs[i].pullJoint.WorldAnchorA; - Limbs[i].body.ApplyForce(steerForce * Limbs[i].SteerForce * Limbs[i].Mass, pullPos); + Vector2 pullPos = Limbs[i].pullJoint == null ? Limbs[i].SimPosition : Limbs[i].pullJoint.WorldAnchorA; + Limbs[i].body.ApplyForce(movement * Limbs[i].SteerForce * Limbs[i].Mass, pullPos); - } - - if (Limbs[i].type != LimbType.Torso) continue; + if (Limbs[i] == MainLimb) continue; - float dist = (Limbs[0].SimPosition - Limbs[i].SimPosition).Length(); + float dist = (MainLimb.SimPosition - Limbs[i].SimPosition).Length(); - Vector2 limbPos = Limbs[0].SimPosition - Vector2.Normalize(movement) * dist; + Vector2 limbPos = MainLimb.SimPosition - Vector2.Normalize(movement) * dist; Limbs[i].body.ApplyForce(((limbPos - Limbs[i].SimPosition) * 3.0f - Limbs[i].LinearVelocity * 3.0f) * Limbs[i].Mass); } - - if (!inWater) - { - UpdateWalkAnim(deltaTime); - } - else - { - floorY = Limbs[0].SimPosition.Y; - } - } - - void UpdateSimpleAnim() - { - movement = MathUtils.SmoothStep(movement, TargetMovement*swimSpeed, 1.0f); - if (movement == Vector2.Zero) return; - - float movementAngle = MathUtils.VectorToAngle(movement) - MathHelper.PiOver2; - RefLimb.body.SmoothRotate( - (rotateTowardsMovement) ? - RefLimb.body.Rotation + MathUtils.GetShortestAngle(RefLimb.body.Rotation, movementAngle) : - HeadAngle*Dir); - - RefLimb.body.LinearVelocity = movement; - - //RefLimb.body.SmoothRotate(0.0f); - - foreach (Limb l in Limbs) - { - if (l == RefLimb) continue; - l.body.SetTransform(RefLimb.SimPosition, RefLimb.Rotation); - } + collider.LinearVelocity = Vector2.Lerp(collider.LinearVelocity, movement, 0.5f); + + floorY = Limbs[0].SimPosition.Y; } - + void UpdateWalkAnim(float deltaTime) { movement = MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, 0.2f); @@ -252,102 +219,30 @@ namespace Barotrauma IgnorePlatforms = (TargetMovement.Y < -Math.Abs(TargetMovement.X)); - Limb colliderLimb; - float colliderHeight; - - Limb torso = GetLimb(LimbType.Torso); - Limb head = GetLimb(LimbType.Head); - - if (torso != null) + float mainLimbHeight, mainLimbAngle; + if (MainLimb.type == LimbType.Torso) { - colliderLimb = torso; - colliderHeight = TorsoPosition; - - colliderLimb.body.SmoothRotate(TorsoAngle * Dir, 10.0f); + mainLimbHeight = TorsoPosition; + mainLimbAngle = torsoAngle; } else { - colliderLimb = head; - colliderHeight = HeadPosition; - - if (onGround) colliderLimb.body.SmoothRotate(HeadAngle * Dir, 100.0f); + mainLimbHeight = HeadPosition; + mainLimbAngle = headAngle; } + + MainLimb.body.SmoothRotate(mainLimbAngle * Dir, 50.0f); - Vector2 colliderPos = colliderLimb.SimPosition; + collider.LinearVelocity = new Vector2( + movement.X, + collider.LinearVelocity.Y > 0.0f ? collider.LinearVelocity.Y * 0.5f : collider.LinearVelocity.Y); - Vector2 rayStart = colliderPos; - Vector2 rayEnd = rayStart - new Vector2(0.0f, colliderHeight); - if (stairs != null) rayEnd.Y -= 0.5f; + MainLimb.MoveToPos(GetColliderBottom() + Vector2.UnitY * mainLimbHeight, 10.0f); + + MainLimb.pullJoint.Enabled = true; + MainLimb.pullJoint.WorldAnchorB = GetColliderBottom() + Vector2.UnitY * mainLimbHeight; - //do a raytrace straight down from the torso to figure - //out whether the ragdoll is standing on ground - float closestFraction = 1; - //Structure closestStructure = null; - - 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; - } - - onGround = true; - if (fraction < closestFraction) - { - closestFraction = fraction; - } - onFloorTimer = 0.05f; - return closestFraction; - } , rayStart, rayEnd); - - //the ragdoll "stays on ground" for 50 millisecs after separation - if (onFloorTimer <= 0.0f) - { - onGround = false; - } - else - { - onFloorTimer -= deltaTime; - } - - if (!onGround) return; - - if (closestFraction == 1) //raycast didn't hit anything - floorY = (currentHull == null) ? -1000.0f : ConvertUnits.ToSimUnits(currentHull.Rect.Y - currentHull.Rect.Height); - else - floorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction; - - - if (Math.Abs(colliderPos.Y - floorY) < colliderHeight * 1.2f) - { - colliderLimb.Move(new Vector2(colliderPos.X + movement.X * 0.2f, floorY + colliderHeight), 5.0f); - } - - float walkCycleSpeed = head.LinearVelocity.X * 0.05f; - - walkPos -= walkCycleSpeed; + walkPos -= MainLimb.LinearVelocity.X * 0.05f; Vector2 transformedStepSize = new Vector2( (float)Math.Cos(walkPos) * stepSize.X * 3.0f, @@ -359,7 +254,7 @@ namespace Barotrauma { case LimbType.LeftFoot: case LimbType.RightFoot: - Vector2 footPos = new Vector2(limb.SimPosition.X, colliderPos.Y - colliderHeight); + Vector2 footPos = new Vector2(limb.SimPosition.X, MainLimb.SimPosition.Y - mainLimbHeight); if (limb.RefJointIndex>-1) { @@ -371,25 +266,25 @@ namespace Barotrauma if (limb.type == LimbType.LeftFoot) { - limb.Move(footPos +new Vector2( + limb.MoveToPos(footPos +new Vector2( transformedStepSize.X + movement.X * 0.1f, (transformedStepSize.Y > 0.0f) ? transformedStepSize.Y : 0.0f), 8.0f); } else if (limb.type == LimbType.RightFoot) { - limb.Move(footPos +new Vector2( + limb.MoveToPos(footPos + new Vector2( -transformedStepSize.X + movement.X * 0.1f, (-transformedStepSize.Y > 0.0f) ? -transformedStepSize.Y : 0.0f), 8.0f); } - if (footRotation!=null) limb.body.SmoothRotate((float)footRotation*Dir, 50.0f); + if (footRotation != null) limb.body.SmoothRotate((float)footRotation * Dir, 50.0f); break; case LimbType.LeftLeg: case LimbType.RightLeg: - if (legTorque!=0.0f) limb.body.ApplyTorque(limb.Mass*legTorque*Dir); + if (legTorque != 0.0f) limb.body.ApplyTorque(limb.Mass * legTorque * Dir); break; } } @@ -428,49 +323,16 @@ namespace Barotrauma } } - public override Vector2 EstimateCurrPosition(Vector2 prevPosition, float timePassed) - { - timePassed = MathHelper.Clamp(timePassed, 0.0f, 1.0f); - - Vector2 currPosition = prevPosition + targetMovement * timePassed; - - return currPosition; - } - 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 76ec4a25b..8a99f86f9 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -44,10 +44,10 @@ namespace Barotrauma { get { - return Crouching ? base.TorsoAngle+0.5f : base.TorsoAngle; + return Crouching ? base.TorsoAngle + 0.5f : base.TorsoAngle; } } - + public HumanoidAnimController(Character character, XElement element) : base(character, element) { @@ -61,111 +61,68 @@ namespace Barotrauma public override void UpdateAnim(float deltaTime) { - if (character.IsDead) return; - - Vector2 colliderPos = GetLimb(LimbType.Torso).SimPosition; - - //if (inWater) stairs = null; - - if (onFloorTimer <= 0.0f && !SimplePhysicsEnabled) - { - Vector2 rayStart = colliderPos; // at the bottom of the player sprite - Vector2 rayEnd = rayStart - new Vector2(0.0f, TorsoPosition); - if (stairs != null) rayEnd.Y -= 0.5f; - //do a raytrace straight down from the torso to figure - //out whether the ragdoll is standing on ground - float closestFraction = 1; - Structure closestStructure = null; - 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; - } - - onGround = true; - if (fraction < closestFraction) - { - closestFraction = fraction; - - Structure structure = fixture.Body.UserData as Structure; - if (structure != null) closestStructure = structure; - } - onFloorTimer = 0.05f; - return closestFraction; - } - , rayStart, rayEnd); - - if (closestStructure != null && closestStructure.StairDirection != Direction.None) - { - stairs = closestStructure; - } - else - { - stairs = null; - } - - if (closestFraction == 1) //raycast didn't hit anything - { - floorY = (currentHull == null) ? -1000.0f : ConvertUnits.ToSimUnits(currentHull.Rect.Y - currentHull.Rect.Height); - } - else - { - floorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction; - } - } - - - //the ragdoll "stays on ground" for 50 millisecs after separation - if (onFloorTimer <= 0.0f) - { - onGround = false; - 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); - } - else - { - onFloorTimer -= deltaTime; - } + if (Frozen) return; + if (character.IsDead || character.IsUnconscious || stunTimer > 0.0f) + { + collider.PhysEnabled = false; + collider.SetTransform(GetLimb(LimbType.Torso).SimPosition, 0.0f); + + if (stunTimer > 0) + { + stunTimer -= deltaTime; + } + + return; + } + //stun (= disable the animations) if the ragdoll receives a large enough impact if (strongestImpact > 0.0f) { character.StartStun(MathHelper.Min(strongestImpact * 0.5f, 5.0f)); - } - strongestImpact = 0.0f; - - - if (stunTimer > 0) - { - stunTimer -= deltaTime; + strongestImpact = 0.0f; return; } + + if (!character.IsRemotePlayer || true) + { + //re-enable collider + if (!collider.FarseerBody.Enabled) + { + 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); + + 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) + { + //rotate collider back upright + collider.AngularVelocity = MathUtils.GetShortestAngle(collider.Rotation, 0.0f) * 60.0f; + collider.FarseerBody.FixedRotation = false; + } + else + { + collider.FarseerBody.FixedRotation = true; + } + } + } + else + { + collider.FarseerBody.Enabled = false; + } + if (character.LockHands) { var leftHand = GetLimb(LimbType.LeftHand); @@ -178,37 +135,31 @@ namespace Barotrauma Vector2 midPos = waist.SimPosition; - + Matrix torsoTransform = Matrix.CreateRotationZ(waist.Rotation); - midPos += Vector2.Transform(new Vector2(-0.3f*Dir,-0.2f), torsoTransform); + midPos += Vector2.Transform(new Vector2(-0.3f * Dir, -0.2f), torsoTransform); if (rightHand.pullJoint.Enabled) midPos = (midPos + rightHand.pullJoint.WorldAnchorB) / 2.0f; HandIK(rightHand, midPos); HandIK(leftHand, midPos); - - //rightHand.pullJoint.Enabled = true; - //rightHand.pullJoint.WorldAnchorB = midPos; - - //rightHand.pullJoint.Enabled = true; - //rightHand.pullJoint.WorldAnchorB = midPos; } else { - if (Anim != Animation.UsingConstruction) ResetPullJoints(); + if (Anim != Animation.UsingConstruction) ResetPullJoints(); } - + if (SimplePhysicsEnabled) { UpdateStandingSimple(); return; } - - + + switch (Anim) { case Animation.Climbing: @@ -223,12 +174,12 @@ namespace Barotrauma default: if (character.SelectedCharacter != null) DragCharacter(character.SelectedCharacter); - + //0.5 second delay for switching between swimming and walking //prevents rapid switches between swimming/walking if the water level is fluctuating around the minimum swimming depth if (inWater) { - inWaterTimer = Math.Max(inWaterTimer+deltaTime, 0.5f); + inWaterTimer = Math.Max(inWaterTimer + deltaTime, 0.5f); if (inWaterTimer >= 1.0f) swimming = true; } else @@ -257,6 +208,7 @@ namespace Barotrauma } aiming = false; + if (character.IsRemotePlayer && GameMain.Server == null) collider.LinearVelocity = Vector2.Zero; } @@ -267,21 +219,21 @@ namespace Barotrauma //if you're allergic to magic numbers, stop reading now - Limb leftFoot = GetLimb(LimbType.LeftFoot); - Limb rightFoot = GetLimb(LimbType.RightFoot); - Limb head = GetLimb(LimbType.Head); - Limb torso = GetLimb(LimbType.Torso); + Limb leftFoot = GetLimb(LimbType.LeftFoot); + Limb rightFoot = GetLimb(LimbType.RightFoot); + Limb head = GetLimb(LimbType.Head); + Limb torso = GetLimb(LimbType.Torso); - Limb waist = GetLimb(LimbType.Waist); + Limb waist = GetLimb(LimbType.Waist); - Limb leftHand = GetLimb(LimbType.LeftHand); - Limb rightHand = GetLimb(LimbType.RightHand); + Limb leftHand = GetLimb(LimbType.LeftHand); + Limb rightHand = GetLimb(LimbType.RightHand); + + Limb leftLeg = GetLimb(LimbType.LeftLeg); + Limb rightLeg = GetLimb(LimbType.RightLeg); - Limb leftLeg = GetLimb(LimbType.LeftLeg); - Limb rightLeg = GetLimb(LimbType.RightLeg); - float getUpSpeed = 0.3f; - float walkCycleSpeed = head.LinearVelocity.X * walkAnimSpeed; + float walkCycleSpeed = movement.X * walkAnimSpeed; if (stairs != null) { TargetMovement = new Vector2(MathHelper.Clamp(TargetMovement.X, -1.5f, 1.5f), TargetMovement.Y); @@ -290,17 +242,11 @@ namespace Barotrauma TargetMovement.X < 0.0f && stairs.StairDirection == Direction.Left) { TargetMovement *= 1.7f; - walkCycleSpeed *= 1.7f; + //walkCycleSpeed *= 1.0f; } - else - { - TargetMovement /= 1.0f; - walkCycleSpeed *= 1.5f; - } } - Vector2 colliderPos = new Vector2(torso.SimPosition.X, floorY); - + Vector2 colliderPos = GetColliderBottom(); if (Math.Abs(TargetMovement.X) > 1.0f) { int limbsInWater = 0; @@ -312,24 +258,27 @@ namespace Barotrauma float slowdownFactor = (float)limbsInWater / (float)Limbs.Count(); float maxSpeed = Math.Max(TargetMovement.Length() - slowdownFactor, 1.0f); - // if (character.SelectedCharacter!=null) maxSpeed = Math.Min(maxSpeed, 1.0f); + // if (character.SelectedCharacter!=null) maxSpeed = Math.Min(maxSpeed, 1.0f); TargetMovement = Vector2.Normalize(TargetMovement) * maxSpeed; } float walkPosX = (float)Math.Cos(walkPos); float walkPosY = (float)Math.Sin(walkPos); - float runningModifier = (float)Math.Max(Math.Min(Math.Abs(TargetMovement.X),3.0f) / 1.5f, 1.0); + float runningModifier = (float)Math.Max(Math.Min(Math.Abs(TargetMovement.X), 3.0f) / 1.5f, 1.0); Vector2 stepSize = new Vector2( this.stepSize.X * walkPosX * runningModifier, this.stepSize.Y * walkPosY * runningModifier * runningModifier); if (Crouching) stepSize *= 0.5f; - - float footMid = waist.SimPosition.X;// (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f; - - movement = MathUtils.SmoothStep(movement, TargetMovement*walkSpeed, movementLerp); + + float footMid = colliderPos.X;// (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f; + + movement = overrideTargetMovement == Vector2.Zero ? + MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, movementLerp) : + overrideTargetMovement; + movement.Y = 0.0f; for (int i = 0; i < 2; i++) @@ -354,17 +303,12 @@ namespace Barotrauma } } - if (LowestLimb == null) return; - - if (!onGround || (LowestLimb.SimPosition.Y - floorY > 0.5f && stairs == null)) return; - - //float? ceilingY = null; - //if (Submarine.PickBody(head.SimPosition, head.SimPosition + Vector2.UnitY, null, Physics.CollisionWall)!=null) - //{ - // ceilingY = Submarine.LastPickedPosition.Y; - - // if (ceilingY - floorY < HeadPosition) Crouching = true; - //} + if (onGround && (!character.IsRemotePlayer || GameMain.Server != null)) + { + collider.LinearVelocity = new Vector2( + movement.X, + collider.LinearVelocity.Y > 0.0f ? collider.LinearVelocity.Y * 0.5f : collider.LinearVelocity.Y); + } getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f); @@ -374,32 +318,43 @@ namespace Barotrauma if (stairs != null) { - if (LowestLimb.SimPosition.Y < stairs.SimPosition.Y) IgnorePlatforms = true; - torso.pullJoint.WorldAnchorB = new Vector2( - MathHelper.SmoothStep(torso.SimPosition.X, footMid + movement.X * 0.35f, getUpSpeed * 0.8f), + MathHelper.SmoothStep(torso.SimPosition.X, footMid + movement.X * 0.25f, getUpSpeed * 0.8f), MathHelper.SmoothStep(torso.SimPosition.Y, colliderPos.Y + TorsoPosition - Math.Abs(walkPosX * 0.05f), getUpSpeed * 2.0f)); head.pullJoint.WorldAnchorB = new Vector2( - MathHelper.SmoothStep(head.SimPosition.X, footMid + movement.X * (Crouching ? 1.0f : 0.4f), getUpSpeed * 0.8f), + MathHelper.SmoothStep(head.SimPosition.X, footMid + movement.X * (Crouching ? 0.6f : 0.25f), getUpSpeed * 0.8f), MathHelper.SmoothStep(head.SimPosition.Y, colliderPos.Y + HeadPosition - Math.Abs(walkPosX * 0.05f), getUpSpeed * 2.0f)); waist.pullJoint.WorldAnchorB = waist.SimPosition;// +movement * 0.3f; } else { + if (!onGround) movement = Vector2.Zero; + torso.pullJoint.WorldAnchorB = MathUtils.SmoothStep(torso.SimPosition, - new Vector2(footMid + movement.X * 0.3f, colliderPos.Y + TorsoPosition), getUpSpeed); + new Vector2(footMid + movement.X * 0.2f, colliderPos.Y + TorsoPosition), getUpSpeed); head.pullJoint.WorldAnchorB = MathUtils.SmoothStep(head.SimPosition, - new Vector2(footMid + movement.X * (Crouching && Math.Sign(movement.X)==Math.Sign(Dir) ? 1.0f : 0.3f), colliderPos.Y + HeadPosition), getUpSpeed*1.2f); + new Vector2(footMid + movement.X * (Crouching && Math.Sign(movement.X) == Math.Sign(Dir) ? 0.6f : 0.2f), colliderPos.Y + HeadPosition), getUpSpeed * 1.2f); - waist.pullJoint.WorldAnchorB = waist.SimPosition + movement * 0.1f; + waist.pullJoint.WorldAnchorB = waist.SimPosition + movement * 0.06f; } + if (!onGround) + { + Vector2 move = torso.pullJoint.WorldAnchorB - torso.SimPosition; + + foreach (Limb limb in Limbs) + { + MoveLimb(limb, limb.SimPosition+move, 15.0f, true); + } + + return; + } //moving horizontally if (TargetMovement.X != 0.0f) @@ -461,7 +416,7 @@ namespace Barotrauma HandIK(rightHand, torso.SimPosition + posAddition + new Vector2( -handPos.X, - (Math.Sign(walkPosX) == Math.Sign(Dir)) ? handPos.Y : lowerY), 0.7f*runningModifier); + (Math.Sign(walkPosX) == Math.Sign(Dir)) ? handPos.Y : lowerY), 0.7f * runningModifier); } if (!leftHand.Disabled) @@ -506,7 +461,7 @@ namespace Barotrauma var leftArm = GetLimb(LimbType.LeftArm); leftArm.body.SmoothRotate(0.0f, 20.0f); } - } + } } @@ -520,17 +475,18 @@ namespace Barotrauma movement = Vector2.Normalize(movement); } - RefLimb.pullJoint.Enabled = true; - RefLimb.pullJoint.WorldAnchorB = - RefLimb.SimPosition + movement * 0.15f; + return; + //RefLimb.pullJoint.Enabled = true; + //RefLimb.pullJoint.WorldAnchorB = + // RefLimb.SimPosition + movement * 0.15f; - RefLimb.body.SmoothRotate(0.0f); + //RefLimb.body.SmoothRotate(0.0f); - foreach (Limb l in Limbs) - { - if (l == RefLimb) continue; - l.body.SetTransform(RefLimb.SimPosition, RefLimb.Rotation); - } + //foreach (Limb l in Limbs) + //{ + // if (l == RefLimb) continue; + // l.body.SetTransform(RefLimb.SimPosition, RefLimb.Rotation); + //} //new Vector2(movement.X, floorY + HeadPosition), 0.5f); } @@ -543,26 +499,26 @@ namespace Barotrauma float surfaceLimiter = 1.0f; Limb head = GetLimb(LimbType.Head); - - if (currentHull != null && (currentHull.Rect.Y - currentHull.Surface > 50.0f) && !head.inWater) + Limb torso = GetLimb(LimbType.Torso); + + 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 torso = GetLimb(LimbType.Torso); Limb leftHand = GetLimb(LimbType.LeftHand); Limb rightHand = GetLimb(LimbType.RightHand); 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; - if (!character.IsNetworkPlayer && !aiming) + if (!character.IsRemotePlayer && !aiming) { if (rotation > 20 && rotation < 170) TargetDir = Direction.Left; @@ -577,7 +533,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 @@ -589,23 +548,27 @@ 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; } else { @@ -614,23 +577,20 @@ 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); - + if (!character.IsRemotePlayer || GameMain.Server != null) + { + 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); @@ -641,41 +601,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; @@ -683,8 +634,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); @@ -693,21 +644,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); } } @@ -724,10 +672,9 @@ 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); - //} + + tempTargetMovement.Y = Math.Min(tempTargetMovement.Y, 1.0f); + movement = MathUtils.SmoothStep(movement, tempTargetMovement, 0.3f); Limb leftFoot = GetLimb(LimbType.LeftFoot); @@ -746,7 +693,7 @@ namespace Barotrauma float stepHeight = ConvertUnits.ToSimUnits(30.0f); - if (currentHull==null && character.SelectedConstruction.Submarine!=null) + if (currentHull == null && character.SelectedConstruction.Submarine != null) { ladderSimPos += character.SelectedConstruction.Submarine.SimPosition; } @@ -754,26 +701,32 @@ namespace Barotrauma { ladderSimPos += character.SelectedConstruction.Submarine.SimPosition - currentHull.Submarine.SimPosition; } - - MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, head.SimPosition.Y + 0.05f), 10.5f); - MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, torso.SimPosition.Y), 10.5f); - MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, waist.SimPosition.Y), 10.5f); + MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, collider.SimPosition.Y + 0.7f), 10.5f); + MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, collider.SimPosition.Y+0.5f), 10.5f); + MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, collider.SimPosition.Y+0.4f), 10.5f); + + if (!character.IsRemotePlayer) + { + collider.MoveToPos(new Vector2(ladderSimPos.X - 0.2f * Dir, collider.SimPosition.Y), 10.5f); + } + + bool slide = targetMovement.Y < -1.1f; Vector2 handPos = new Vector2( ladderSimPos.X, - head.SimPosition.Y + movement.Y * 0.1f - ladderSimPos.Y); + collider.SimPosition.Y + 0.6f + movement.Y * 0.1f - ladderSimPos.Y); handPos.Y = Math.Min(-0.5f, handPos.Y); MoveLimb(leftHand, new Vector2(handPos.X, - MathUtils.Round(handPos.Y - stepHeight, stepHeight * 2.0f) + stepHeight + ladderSimPos.Y), + (slide ? handPos.Y : MathUtils.Round(handPos.Y - stepHeight, stepHeight * 2.0f) + stepHeight) + ladderSimPos.Y), 5.2f); MoveLimb(rightHand, new Vector2(handPos.X, - MathUtils.Round(handPos.Y, stepHeight * 2.0f) + ladderSimPos.Y), + (slide ? handPos.Y : MathUtils.Round(handPos.Y, stepHeight * 2.0f)) + ladderSimPos.Y), 5.2f); leftHand.body.ApplyTorque(Dir * 2.0f); @@ -781,18 +734,18 @@ namespace Barotrauma Vector2 footPos = new Vector2( handPos.X - Dir * 0.05f, - head.SimPosition.Y - stepHeight * 2.7f - ladderSimPos.Y - 0.7f); + collider.SimPosition.Y + 0.7f - stepHeight * 2.7f - ladderSimPos.Y - 0.7f); //if (movement.Y < 0) footPos.Y += 0.05f; MoveLimb(leftFoot, new Vector2(footPos.X, - MathUtils.Round(footPos.Y + stepHeight, stepHeight * 2.0f) - stepHeight + ladderSimPos.Y), + (slide ? footPos.Y : MathUtils.Round(footPos.Y + stepHeight, stepHeight * 2.0f) - stepHeight) + ladderSimPos.Y), 15.5f, true); MoveLimb(rightFoot, new Vector2(footPos.X, - MathUtils.Round(footPos.Y, stepHeight * 2.0f) + ladderSimPos.Y), + (slide ? footPos.Y : MathUtils.Round(footPos.Y, stepHeight * 2.0f)) + ladderSimPos.Y), 15.5f, true); //apply torque to the legs to make the knees bend @@ -802,18 +755,19 @@ namespace Barotrauma leftLeg.body.ApplyTorque(Dir * -8.0f); rightLeg.body.ApplyTorque(Dir * -8.0f); - //apply forces to the head and the torso to move the Character up/down float movementFactor = (handPos.Y / stepHeight) * (float)Math.PI; movementFactor = 0.8f + (float)Math.Abs(Math.Sin(movementFactor)); - Vector2 subSpeed = currentHull != null || character.SelectedConstruction.Submarine == null + Vector2 subSpeed = currentHull != null || character.SelectedConstruction.Submarine == null ? Vector2.Zero : character.SelectedConstruction.Submarine.Velocity; - Vector2 climbForce = new Vector2(0.0f, movement.Y + (inWater ? -0.05f : 0.6f)) * movementFactor; - if (climbForce.Y > 0.5f) climbForce.Y = Math.Max(climbForce.Y, 1.3f); - torso.body.ApplyForce((climbForce * 40.0f + subSpeed*50.0f) * torso.Mass); - head.body.SmoothRotate(0.0f); + Vector2 climbForce = new Vector2(0.0f, movement.Y + 0.3f) * movementFactor; + //if (climbForce.Y > 0.5f) climbForce.Y = Math.Max(climbForce.Y, 1.3f); + //apply forces to the collider to move the Character up/down + collider.ApplyForce((climbForce * 20.0f + subSpeed * 50.0f) * collider.Mass); + head.body.SmoothRotate(0.0f); + if (!character.SelectedConstruction.Prefab.Triggers.Any()) { character.SelectedConstruction = null; @@ -824,7 +778,7 @@ namespace Barotrauma trigger = character.SelectedConstruction.TransformTrigger(trigger); bool notClimbing = false; - if (character.IsNetworkPlayer) + if (character.IsRemotePlayer) { notClimbing = character.IsKeyDown(InputType.Left) || character.IsKeyDown(InputType.Right); } @@ -861,15 +815,15 @@ namespace Barotrauma targetMovement = new Vector2(diff.X, 0.0f); TargetDir = headDiff.X > 0.0f ? Direction.Right : Direction.Left; - + UpdateStanding(); - Vector2 handPos = character.SelectedCharacter.AnimController.GetLimb(LimbType.Torso).SimPosition + Vector2.UnitY*0.2f; + Vector2 handPos = character.SelectedCharacter.AnimController.GetLimb(LimbType.Torso).SimPosition + Vector2.UnitY * 0.2f; Grab(handPos, handPos); float yPos = (float)Math.Sin(cprAnimState) * 0.1f; - cprAnimState += deltaTime*8.0f; + cprAnimState += deltaTime * 8.0f; var head = GetLimb(LimbType.Head); head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos); @@ -879,7 +833,7 @@ namespace Barotrauma //RefLimb.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X - Math.Sign(headDiff.X) * 0.5f, targetHead.SimPosition.Y + 0.4f + yPos); //head.pullJoint.Enabled = true; - + //DragCharacter(character.SelectedCharacter, LimbType.Torso, LimbType.Head); } @@ -941,15 +895,15 @@ namespace Barotrauma //only grab with one hand when swimming leftHand.Disabled = true; if (!inWater) rightHand.Disabled = true; - - for (int i = 0; i < 2; i++ ) - { - LimbType type = i == 0 ? leftHandTarget: rightHandTarget; - Limb targetLimb = target.AnimController.GetLimb(type); - - Limb pullLimb = GetLimb(i == 0 ? LimbType.LeftHand: LimbType.RightHand); - if (i==1 && inWater) + for (int i = 0; i < 2; i++) + { + LimbType type = i == 0 ? leftHandTarget : rightHandTarget; + Limb targetLimb = target.AnimController.GetLimb(type); + + Limb pullLimb = GetLimb(i == 0 ? LimbType.LeftHand : LimbType.RightHand); + + if (i == 1 && inWater) { targetLimb.pullJoint.Enabled = false; } @@ -976,7 +930,7 @@ namespace Barotrauma } else if (target is AICharacter) { - target.AnimController.TargetMovement = Vector2.Lerp(target.AnimController.TargetMovement, (character.SimPosition + Vector2.UnitX*Dir) - target.SimPosition, 0.5f); + target.AnimController.TargetMovement = Vector2.Lerp(target.AnimController.TargetMovement, (character.SimPosition + Vector2.UnitX * Dir) - target.SimPosition, 0.5f); } } @@ -989,7 +943,7 @@ namespace Barotrauma pullLimb.Disabled = true; pullLimb.pullJoint.Enabled = true; - pullLimb.pullJoint.WorldAnchorB = (i==0) ? rightHandPos : leftHandPos; + pullLimb.pullJoint.WorldAnchorB = (i == 0) ? rightHandPos : leftHandPos; pullLimb.pullJoint.MaxForce = 500.0f; } @@ -1084,7 +1038,7 @@ namespace Barotrauma item.body.ResetDynamics(); - Vector2 currItemPos = (character.SelectedItems[0]==item) ? + Vector2 currItemPos = (character.SelectedItems[0] == item) ? rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0] : leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1]; item.SetTransform(currItemPos, itemAngle); @@ -1129,17 +1083,6 @@ namespace Barotrauma hand.body.SmoothRotate((ang2 + handAngle * Dir), 100.0f * force); } - public override Vector2 EstimateCurrPosition(Vector2 prevPosition, float timePassed) - { - timePassed = MathHelper.Clamp(timePassed, 0.0f, 1.0f); - - Vector2 targetMovement = character.GetTargetMovement(); - - Vector2 currPosition = prevPosition + targetMovement * timePassed/500.0f; - - return currPosition; - } - public override void Flip() { base.Flip(); @@ -1199,7 +1142,7 @@ namespace Barotrauma Vector2 position = limb.SimPosition; - if ((limb.pullJoint==null || !limb.pullJoint.Enabled) && mirror) + if ((limb.pullJoint == null || !limb.pullJoint.Enabled) && mirror) { difference = limb.body.SimPosition - torso.SimPosition; difference = Vector2.Transform(difference, torsoTransform); @@ -1213,11 +1156,11 @@ namespace Barotrauma float angle = flipAngle ? -limb.body.Rotation : limb.body.Rotation; if (wrapAngle) angle = MathUtils.WrapAnglePi(angle); - TrySetLimbPosition(limb, RefLimb.SimPosition, position); + TrySetLimbPosition(limb, collider.SimPosition, position); limb.body.SetTransform(limb.body.SimPosition, angle); } } - + } } diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 9d075e79f..939d8a15d 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -9,6 +9,7 @@ using FarseerPhysics.Dynamics.Joints; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Barotrauma.Networking; +using Lidgren.Network; namespace Barotrauma { @@ -19,6 +20,25 @@ namespace Barotrauma protected Hull currentHull; public Limb[] Limbs; + + private bool frozen; + public bool Frozen + { + get { return frozen; } + set + { + if (frozen == value) return; + + frozen = value; + + foreach (Limb l in Limbs) + { + l.body.PhysEnabled = !frozen; + } + collider.PhysEnabled = !frozen; + } + } + private Dictionary limbDictionary; public RevoluteJoint[] limbJoints; @@ -26,8 +46,6 @@ namespace Barotrauma private Character character; - private Limb lowestLimb; - protected float strongestImpact; public float headPosition, headAngle; @@ -44,7 +62,7 @@ namespace Barotrauma //a movement vector that overrides targetmovement if trying to steer //a Character to the position sent by server in multiplayer mode - protected Vector2 correctionMovement; + protected Vector2 overrideTargetMovement; protected float floorY; protected float surfaceY; @@ -52,25 +70,20 @@ namespace Barotrauma protected bool inWater, headInWater; public bool onGround; private bool ignorePlatforms; - - private Limb refLimb; - + protected Structure stairs; protected Direction dir; - //private byte ID; - - public Limb LowestLimb - { - get { return lowestLimb; } - } + public Direction TargetDir; - public Limb RefLimb + protected PhysicsBody collider; + + public PhysicsBody Collider { get { - return refLimb; + return collider; } } @@ -85,6 +98,22 @@ namespace Barotrauma private set; } + public Limb MainLimb + { + get; + private set; + } + + public Vector2 WorldPosition + { + get + { + return character.Submarine == null ? + ConvertUnits.ToDisplayUnits(collider.SimPosition) : + ConvertUnits.ToDisplayUnits(collider.SimPosition) + character.Submarine.Position; + } + } + public bool SimplePhysicsEnabled { get { return simplePhysicsEnabled; } @@ -104,7 +133,13 @@ namespace Barotrauma joint.Enabled = !simplePhysicsEnabled; } - refLimb.body.Enabled = true; + if (!simplePhysicsEnabled) + { + foreach (Limb limb in Limbs) + { + limb.body.SetTransform(collider.SimPosition, collider.Rotation); + } + } } } @@ -112,7 +147,7 @@ namespace Barotrauma { get { - return (correctionMovement == Vector2.Zero) ? targetMovement : correctionMovement; + return (overrideTargetMovement == Vector2.Zero) ? targetMovement : overrideTargetMovement; } set { @@ -167,10 +202,12 @@ namespace Barotrauma if (value == currentHull) return; currentHull = value; + Submarine currSubmarine = currentHull == null ? null : currentHull.Submarine; foreach (Limb limb in Limbs) { - limb.body.Submarine = currentHull == null ? null : currentHull.Submarine; + limb.body.Submarine = currSubmarine; } + collider.Submarine = currSubmarine; } } @@ -208,18 +245,17 @@ namespace Barotrauma float scale = ToolBox.GetAttributeFloat(element, "scale", 1.0f); - //int limbAmount = ; Limbs = new Limb[element.Elements("limb").Count()]; limbJoints = new RevoluteJoint[element.Elements("joint").Count()]; limbDictionary = new Dictionary(); - headPosition = ToolBox.GetAttributeFloat(element, "headposition", 50.0f); - headPosition = ConvertUnits.ToSimUnits(headPosition); - headAngle = MathHelper.ToRadians(ToolBox.GetAttributeFloat(element, "headangle", 0.0f)); + headPosition = ToolBox.GetAttributeFloat(element, "headposition", 50.0f); + headPosition = ConvertUnits.ToSimUnits(headPosition); + headAngle = MathHelper.ToRadians(ToolBox.GetAttributeFloat(element, "headangle", 0.0f)); - torsoPosition = ToolBox.GetAttributeFloat(element, "torsoposition", 50.0f); - torsoPosition = ConvertUnits.ToSimUnits(torsoPosition); - torsoAngle = MathHelper.ToRadians(ToolBox.GetAttributeFloat(element, "torsoangle", 0.0f)); + torsoPosition = ToolBox.GetAttributeFloat(element, "torsoposition", 50.0f); + torsoPosition = ConvertUnits.ToSimUnits(torsoPosition); + torsoAngle = MathHelper.ToRadians(ToolBox.GetAttributeFloat(element, "torsoangle", 0.0f)); CanEnterSubmarine = ToolBox.GetAttributeBool(element, "canentersubmarine", true); @@ -241,20 +277,30 @@ namespace Barotrauma case "joint": AddJoint(subElement, scale); + break; + case "collider": + collider = new PhysicsBody(subElement, scale); + collider.FarseerBody.FixedRotation = true; break; } - } - refLimb = GetLimb(LimbType.Torso); - if (refLimb == null) refLimb = GetLimb(LimbType.Head); - if (refLimb == null) DebugConsole.ThrowError("Character \"" + character + "\" doesn't have a head or torso!"); + if (collider == null) + { + DebugConsole.ThrowError("No collider configured for ''"+character.Name+"''!"); + collider = new PhysicsBody(0.0f, 0.0f, 0.5f, 5.0f); + collider.BodyType = BodyType.Dynamic; + } + + collider.CollisionCategories = Physics.CollisionCharacter; + collider.FarseerBody.AngularDamping = 5.0f; + collider.FarseerBody.FixedRotation = true; + collider.FarseerBody.OnCollision += OnLimbCollision; UpdateCollisionCategories(); foreach (var joint in limbJoints) { - joint.BodyB.SetTransform( joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB)*0.1f, (joint.LowerLimit + joint.UpperLimit) / 2.0f); @@ -274,7 +320,10 @@ namespace Barotrauma limb.sprite.Depth = startDepth + limb.sprite.Depth * 0.0001f; } - FindLowestLimb(); + Limb torso = GetLimb(LimbType.Torso); + Limb head = GetLimb(LimbType.Head); + + MainLimb = torso == null ? head : torso; } public void AddJoint(XElement subElement, float scale = 1.0f) @@ -341,61 +390,51 @@ namespace Barotrauma CalculateImpact(f1, f2, contact); return true; } + + 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 (lowestLimb==null || lowestLimb.Position.Y < structure.Rect.Y) 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; + } - else if (structure.StairDirection != Direction.None && lowestLimb != null) + else if (structure.StairDirection != Direction.None) { - float stairPosY = structure.StairDirection == Direction.Right ? - lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X); + stairs = null; + //don't collider with stairs if - if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY - 10.0f) return false; - + //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; - - if (targetMovement.Y < 0.5f) - { - if (inWater || lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + 50.0f) - { - stairs = null; - return false; - } - } - - //if (targetMovement.Y >= 0.0f && lowestLimb.SimPosition.Y > ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y * 8.0f)) - //{ - // //stairs = null; - // //return false; - //} - - Limb limb = f1.Body.UserData as Limb; - 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; - } + //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; - } - else - { - stairs = null; - 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; } - CalculateImpact(f1, f2, contact); + return true; } @@ -405,39 +444,40 @@ namespace Barotrauma Vector2 normal = contact.Manifold.LocalNormal; - Vector2 avgVelocity = Vector2.Zero; - foreach (Limb limb in Limbs) - { - avgVelocity += limb.LinearVelocity; - } + //Vector2 avgVelocity = Vector2.Zero; + //foreach (Limb limb in Limbs) + //{ + // avgVelocity += limb.LinearVelocity; + //} - avgVelocity = avgVelocity / Limbs.Count(); + Vector2 velocity = f1.Body.LinearVelocity; - if (character.Submarine == null && f2.Body.UserData is Submarine) avgVelocity -= ((Submarine)f2.Body.UserData).Velocity; + if (character.Submarine == null && f2.Body.UserData is Submarine) velocity -= ((Submarine)f2.Body.UserData).Velocity; - float impact = Vector2.Dot(avgVelocity, -normal); - - Limb l = (Limb)f1.Body.UserData; + float impact = Vector2.Dot(velocity, -normal); - float volume = stairs == null ? impact / 5.0f : impact; - volume = Math.Min(impact, 1.0f); - - if (impact > 0.5f && l.HitSound != null && l.soundTimer <= 0.0f) + float volume = Math.Min(impact, 1.0f); + if (f1.Body.UserData is Limb) { - l.soundTimer = Limb.SoundInterval; - l.HitSound.Play(volume, impact * 250.0f, l.WorldPosition); - } - - if (impact > l.impactTolerance) - { - if (!character.IsNetworkPlayer || GameMain.Server != null) + Limb limb = (Limb)f1.Body.UserData; + + if (impact > 0.5f && limb.HitSound != null && limb.soundTimer <= 0.0f) { - character.AddDamage(CauseOfDeath.Damage, impact - l.impactTolerance * 0.1f, null); - - strongestImpact = Math.Max(strongestImpact, impact - l.impactTolerance); + limb.soundTimer = Limb.SoundInterval; + limb.HitSound.Play(volume, impact * 250.0f, limb.WorldPosition); } - - SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, l.body); + } + else if (f1.Body == collider.FarseerBody) + { + if (!character.IsRemotePlayer || GameMain.Server != null) + { + if (impact > 8.0f) + { + character.AddDamage(CauseOfDeath.Damage, impact - 8.0f, null); + SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, collider); + strongestImpact = Math.Max(strongestImpact, impact - 8.0f); + } + } if (Character.Controlled == character) GameMain.GameScreen.Cam.Shake = strongestImpact; } @@ -446,6 +486,8 @@ namespace Barotrauma public virtual void Draw(SpriteBatch spriteBatch) { if (simplePhysicsEnabled) return; + + collider.UpdateDrawPosition(); foreach (Limb limb in Limbs) { @@ -467,17 +509,13 @@ 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, inWater ? Color.Cyan : Color.White); } + collider.DebugDraw(spriteBatch, inWater ? Color.SkyBlue : Color.Gray); + foreach (RevoluteJoint joint in limbJoints) { Vector2 pos = ConvertUnits.ToDisplayUnits(joint.WorldAnchorA); @@ -496,13 +534,35 @@ namespace Barotrauma pos.Y = -pos.Y; GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 10, (int)pos.Y - 10, 20, 20), Color.Cyan, false, 0.01f); - GUI.DrawLine(spriteBatch, pos, new Vector2(limb.WorldPosition.X, -limb.WorldPosition.Y), limb == RefLimb ? Color.Orange : Color.Cyan); + GUI.DrawLine(spriteBatch, pos, new Vector2(limb.WorldPosition.X, -limb.WorldPosition.Y), Color.Cyan); + } + } + + if (character.MemPos.Count > 1) + { + Vector2 prevPos = ConvertUnits.ToDisplayUnits(character.MemPos[0].Position); + if (currentHull != null) prevPos += currentHull.Submarine.DrawPosition; + prevPos.Y = -prevPos.Y; + + for (int i = 1; i < character.MemPos.Count; i++ ) + { + Vector2 currPos = ConvertUnits.ToDisplayUnits(character.MemPos[i].Position); + if (currentHull != null) currPos += currentHull.Submarine.DrawPosition; + currPos.Y = -currPos.Y; + + GUI.DrawRectangle(spriteBatch, new Rectangle((int)currPos.X - 3, (int)currPos.Y - 3, 6, 6), Color.Cyan*0.6f, true, 0.01f); + GUI.DrawLine(spriteBatch, prevPos, currPos, Color.Cyan*0.6f, 0, 3); + + prevPos = currPos; } } if (ignorePlatforms) { - GUI.DrawLine(spriteBatch, new Vector2(refLimb.WorldPosition.X, -refLimb.WorldPosition.Y), new Vector2(refLimb.WorldPosition.X, -refLimb.WorldPosition.Y+50), Color.Orange, 0, 5); + GUI.DrawLine(spriteBatch, + new Vector2(collider.DrawPosition.X, -collider.DrawPosition.Y), + new Vector2(collider.DrawPosition.X, -collider.DrawPosition.Y + 50), + Color.Orange, 0, 5); } } @@ -555,20 +615,16 @@ namespace Barotrauma return centerOfMass; } - - - /// - /// - /// + /// if false, force is applied to the position of pullJoint protected void MoveLimb(Limb limb, Vector2 pos, float amount, bool pullFromCenter = false) { - limb.Move(pos, amount, pullFromCenter); + limb.MoveToPos(pos, amount, pullFromCenter); } public void ResetPullJoints() { - for (int i = 0; i < Limbs.Count(); i++) + for (int i = 0; i < Limbs.Length; i++) { if (Limbs[i] == null || Limbs[i].pullJoint == null) continue; Limbs[i].pullJoint.Enabled = false; @@ -590,7 +646,7 @@ namespace Barotrauma return; } - Vector2 findPos = worldPosition==null ? refLimb.WorldPosition : (Vector2)worldPosition; + Vector2 findPos = worldPosition==null ? this.WorldPosition : (Vector2)worldPosition; Hull newHull = Hull.FindHull(findPos, currentHull); @@ -642,7 +698,6 @@ namespace Barotrauma while (ce != null && ce.Contact != null) { ce.Contact.Enabled = false; - ce = ce.Next; } } @@ -655,10 +710,10 @@ namespace Barotrauma //character.Stun = 0.1f; character.DisableImpactDamageTimer = 0.25f; - SetPosition(refLimb.SimPosition + moveAmount); + SetPosition(collider.SimPosition + moveAmount); character.CursorPosition += moveAmount; } - + private void UpdateCollisionCategories() { Category wall = currentHull == null ? @@ -669,6 +724,8 @@ namespace Barotrauma wall | Physics.CollisionProjectile | Physics.CollisionStairs : wall | Physics.CollisionProjectile | Physics.CollisionPlatform | Physics.CollisionStairs; + collider.CollidesWith = collisionCategory; + foreach (Limb limb in Limbs) { if (limb.ignoreCollisions) continue; @@ -686,14 +743,13 @@ namespace Barotrauma public void Update(Camera cam, float deltaTime) { - if (!character.Enabled) return; + if (!character.Enabled || Frozen) return; - UpdateNetPlayerPosition(); + UpdateNetPlayerPosition(deltaTime); + CheckDistFromCollider(); Vector2 flowForce = Vector2.Zero; - FindLowestLimb(); - FindHull(); splashSoundTimer -= deltaTime; @@ -711,10 +767,27 @@ namespace Barotrauma inWater = false; headInWater = false; + float waterSurface = ConvertUnits.ToSimUnits(currentHull.Surface); + + float floorY = GetFloorY(); + if (currentHull.Volume > currentHull.FullVolume * 0.95f || - ConvertUnits.ToSimUnits(currentHull.Surface) - floorY > HeadPosition * 0.95f) + (waterSurface - floorY > HeadPosition * 0.95f && collider.SimPosition.Y < waterSurface)) 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) { @@ -736,10 +809,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; @@ -747,7 +819,6 @@ namespace Barotrauma if (limb.type == LimbType.Head) { headInWater = true; - surfaceY = limbHull.Surface; } } //the limb has gone through the surface of the water @@ -755,9 +826,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", @@ -787,27 +858,133 @@ namespace Barotrauma } limb.Update(deltaTime); - } + } + + + bool onStairs = stairs != null; + stairs = null; + + var contacts = collider.FarseerBody.ContactList; + while (collider.FarseerBody.Enabled && contacts != null && contacts.Contact != null) + { + if (contacts.Contact.Enabled && contacts.Contact.IsTouching) + { + Vector2 normal; + FarseerPhysics.Common.FixedArray2 points; + + contacts.Contact.GetWorldManifold(out normal, out points); + + switch (contacts.Contact.FixtureA.CollisionCategories) + { + case Physics.CollisionStairs: + Structure structure = contacts.Contact.FixtureA.Body.UserData as Structure; + if (structure != null && onStairs) + { + stairs = structure; + } + break; + } + // case Physics.CollisionPlatform: + // Structure platform = contacts.Contact.FixtureA.Body.UserData as Structure; + // if (IgnorePlatforms || colliderBottom.Y < ConvertUnits.ToSimUnits(platform.Rect.Y - 15)) + // { + // contacts = contacts.Next; + // continue; + // } + // break; + // case Physics.CollisionWall: + // break; + // default: + // contacts = contacts.Next; + // continue; + //} + + + if (points[0].Y < collider.SimPosition.Y) + { + floorY = Math.Max(floorY, points[0].Y); + + onGround = true; + onFloorTimer = 0.1f; + } + + + } + + contacts = contacts.Next; + } + + //the ragdoll "stays on ground" for 50 millisecs after separation + if (onFloorTimer <= 0.0f) + { + onGround = false; + } + else + { + onFloorTimer -= 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; + 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) { - Vector2 moveAmount = simPosition - refLimb.SimPosition; + Vector2 moveAmount = simPosition - collider.SimPosition; + + collider.SetTransform(simPosition, collider.Rotation); foreach (Limb limb in Limbs) { - if (limb == refLimb) - { - TrySetLimbPosition(limb, simPosition, simPosition, lerp); - } - else - { - //check visibility from the new position of RefLimb to the new position of this limb - Vector2 movePos = limb.SimPosition + moveAmount; - - TrySetLimbPosition(limb, simPosition, movePos, lerp); - } + //check visibility from the new position of the collider to the new position of this limb + Vector2 movePos = limb.SimPosition + moveAmount; + TrySetLimbPosition(limb, simPosition, movePos, lerp); } } @@ -846,118 +1023,72 @@ namespace Barotrauma } } - public void SetRotation(float rotation) + + private bool collisionsDisabled; + + protected void CheckDistFromCollider() { - float rotateAmount = rotation - refLimb.Rotation; + float allowedDist = Math.Max(Math.Max(collider.radius, collider.width), collider.height) * 2.0f; - Matrix rotationMatrix = Matrix.CreateRotationZ(rotateAmount); - - refLimb.body.SetTransform(refLimb.SimPosition, rotation); - - foreach (Limb limb in Limbs) + //if the ragdoll is too far from the collider, disable collisions until it's close enough + //(in case the ragdoll has gotten stuck somewhere) + if (Vector2.Distance(collider.SimPosition, MainLimb.SimPosition) > allowedDist) { - if (limb == refLimb) continue; + if (!collisionsDisabled) + { + foreach (Limb limb in Limbs) + { + limb.body.CollidesWith = Physics.CollisionNone; + limb.body.ResetDynamics(); + } + } - Vector2 newPos = limb.SimPosition - refLimb.SimPosition; - newPos = Vector2.Transform(newPos, rotationMatrix); + collisionsDisabled = true; + } + else if (collisionsDisabled) + { + //set the position of the ragdoll to make sure limbs don't get stuck inside walls when re-enabling collisions + SetPosition(collider.SimPosition, true); - TrySetLimbPosition(limb, refLimb.SimPosition, refLimb.SimPosition + newPos); - limb.body.SetTransform(limb.SimPosition, limb.Rotation + rotateAmount); + UpdateCollisionCategories(); + collisionsDisabled = false; } } - - private void UpdateNetPlayerPosition() + + private void UpdateNetPlayerPosition(float deltaTime) { - if (refLimb.body.TargetPosition == Vector2.Zero) + if (GameMain.NetworkMember == null) return; + + if (character == GameMain.NetworkMember.Character) { - correctionMovement = Vector2.Zero; - return; - } + //if (character.MemPos.Count < 2) return; - //if the limb is closer than alloweddistance, just ignore the difference - float allowedDistance = NetConfig.AllowedRagdollDistance * ((inWater) ? 2.0f : 1.0f); + //PosInfo serverPos = character.MemPos.Last(); - if (currentHull == null) - { - var overLappingHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(refLimb.body.TargetPosition), null, true); + //int localPosIndex = character.MemLocalPos.FindIndex(m => m.ID == serverPos.ID); + //if (localPosIndex > -1) + //{ + // PosInfo localPos = character.MemLocalPos[localPosIndex]; - if (overLappingHull != null) - { - Submarine.PickBody(refLimb.SimPosition, refLimb.body.TargetPosition, null, Physics.CollisionWall); - - refLimb.body.TargetPosition = refLimb.SimPosition + (refLimb.body.TargetPosition - refLimb.SimPosition) * Submarine.LastPickedFraction * 0.9f; - } - } + // if (Vector2.Distance(localPos.Position, serverPos.Position) > 0.1f) + // { + // //collider.SetTransform(collider.SimPosition + (pos.Position - remotePos), collider.Rotation); + // collider.SetTransform(serverPos.Position, collider.Rotation); + // // character.MemLocalPos.RemoveRange(localPosIndex, character.MemLocalPos.Count - localPosIndex); + // } + //} - float dist = Vector2.Distance(refLimb.body.SimPosition, refLimb.body.TargetPosition); - - //if the limb is further away than resetdistance, all limbs are immediately snapped to their targetpositions - bool resetAll = dist > NetConfig.ResetRagdollDistance; - Vector2 diff = (refLimb.body.TargetPosition - refLimb.body.SimPosition); - - if (diff == Vector2.Zero || diff.Length() < allowedDistance) - { - refLimb.body.TargetPosition = Vector2.Zero; - foreach (Limb limb in Limbs) - { - limb.body.TargetPosition = Vector2.Zero; - } - - correctionMovement = Vector2.Zero; - return; - } - - if (resetAll) - { - System.Diagnostics.Debug.WriteLine("reset ragdoll limb positions"); - - SetPosition(refLimb.body.TargetPosition, dist < 10.0f); - - return; - } - - if (inWater) - { - if (targetMovement.LengthSquared() > 0.01f) - { - correctionMovement = - Vector2.Lerp(targetMovement, Vector2.Normalize(diff) * MathHelper.Clamp(dist * 5.0f, 0.1f, 5.0f), 0.2f); - - } - else - { - refLimb.body.LinearVelocity = Vector2.Lerp( - refLimb.LinearVelocity, - Vector2.Normalize(diff) * MathHelper.Clamp(dist, 0.0f, 5.0f), - 0.2f); - } + //if (character.MemLocalPos.Count > 120) character.MemLocalPos.RemoveRange(0, character.MemLocalPos.Count - 120); + //character.MemPos.Clear(); } else { - //clamp the magnitude of the correction movement between 0.5f - 5.0f - Vector2 newCorrectionMovement = Vector2.Normalize(diff) * MathHelper.Clamp(dist * 2.0f, 0.5f, 5.0f); - - //heading in the right direction -> use the \"normal\" movement if it's faster than correctionMovement - //i.e. the character is close to the targetposition but the character is still running - if (Math.Sign(targetMovement.X) == Math.Sign(newCorrectionMovement.X)) - { - newCorrectionMovement.X = Math.Max(Math.Abs(targetMovement.X), Math.Abs(newCorrectionMovement.X)) * Math.Sign(targetMovement.X); - } - - correctionMovement = Vector2.Lerp(correctionMovement, newCorrectionMovement, 0.5f); - - if (Math.Abs(correctionMovement.Y) < 0.1f) correctionMovement.Y = 0.0f; + collider.CorrectPosition(character.MemPos, deltaTime, out overrideTargetMovement); } } - - public virtual Vector2 EstimateCurrPosition(Vector2 prevPosition, float timePassed) - { - return prevPosition; - } - - + private Vector2 GetFlowForce() { Vector2 limbPos = ConvertUnits.ToDisplayUnits(Limbs[0].SimPosition); @@ -985,11 +1116,16 @@ namespace Barotrauma limbDictionary.TryGetValue(limbType, out limb); return limb; } - - public void FindLowestLimb() + + + public Vector2 GetColliderBottom() { - //find the lowest limb - lowestLimb = null; + return collider.SimPosition - Vector2.UnitY * (collider.height / 2 + collider.radius); + } + + public Limb FindLowestLimb() + { + Limb lowestLimb = null; foreach (Limb limb in Limbs) { if (lowestLimb == null) @@ -997,6 +1133,8 @@ namespace Barotrauma else if (limb.SimPosition.Y < lowestLimb.SimPosition.Y) lowestLimb = limb; } + + return lowestLimb; } public void Remove() diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index a9d4da231..1e6543c59 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -14,13 +14,50 @@ using System.Xml.Linq; namespace Barotrauma { - + struct PosInfo + { + public readonly Vector2 Position; + public readonly Direction Direction; + + public readonly float Timestamp; + public readonly UInt32 ID; + + public PosInfo(Vector2 pos, Direction dir, float time) + { + Position = pos; + Direction = dir; + Timestamp = time; + + ID = 0; + } + + public PosInfo(Vector2 pos, Direction dir, UInt32 ID) + { + Position = pos; + Direction = dir; + this.ID = ID; + + Timestamp = 0.0f; + } + } + class Character : Entity, IDamageable, IPropertyObject { public static List CharacterList = new List(); public static bool DisableControls; + private UInt32 netStateID; + public UInt32 NetStateID + { + get { return netStateID; } + } + + List memPos = new List(); + + private bool networkUpdateSent; + List memLocalPos = new List(); + //the Character that the player is currently controlling private static Character controlled; @@ -61,9 +98,7 @@ namespace Barotrauma public Hull PreviousHull = null; public Hull CurrentHull = null; - public readonly bool IsNetworkPlayer; - - private bool networkUpdateSent; + public readonly bool IsRemotePlayer; private CharacterInventory inventory; @@ -199,6 +234,17 @@ namespace Barotrauma get { return Submarine == null ? cursorPosition : cursorPosition + Submarine.Position; } } + public List MemPos + { + get { return memPos; } + } + + + public List MemLocalPos + { + get { return memLocalPos; } + } + public Character ClosestCharacter { get { return closestCharacter; } @@ -289,6 +335,7 @@ namespace Barotrauma set { if (!MathUtils.IsValid(value)) return; + health = MathHelper.Clamp(value, minHealth, maxHealth); } } @@ -416,28 +463,28 @@ namespace Barotrauma public override Vector2 SimPosition { - get { return AnimController.RefLimb.SimPosition; } + get { return AnimController.Collider.SimPosition; } } public override Vector2 Position { - get { return AnimController.RefLimb.Position; } + get { return ConvertUnits.ToDisplayUnits(SimPosition); } } public override Vector2 DrawPosition { - get { return AnimController.RefLimb.body.DrawPosition; } + get { return AnimController.MainLimb.body.DrawPosition; } } public delegate void OnDeathHandler(Character character, CauseOfDeath causeOfDeath); public OnDeathHandler OnDeath; - public static Character Create(CharacterInfo characterInfo, Vector2 position, bool isNetworkPlayer = false, bool hasAi=true) + public static Character Create(CharacterInfo characterInfo, Vector2 position, bool isRemotePlayer = false, bool hasAi=true) { - return Create(characterInfo.File, position, characterInfo, isNetworkPlayer, hasAi); + return Create(characterInfo.File, position, characterInfo, isRemotePlayer, hasAi); } - public static Character Create(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false, bool hasAi=true) + public static Character Create(string file, Vector2 position, CharacterInfo characterInfo = null, bool isRemotePlayer = false, bool hasAi=true) { #if LINUX if (!System.IO.File.Exists(file)) @@ -470,7 +517,7 @@ namespace Barotrauma if (file != humanConfigFile) { - var enemyCharacter = new AICharacter(file, position, characterInfo, isNetworkPlayer); + var enemyCharacter = new AICharacter(file, position, characterInfo, isRemotePlayer); var ai = new EnemyAIController(enemyCharacter, file); enemyCharacter.SetAI(ai); @@ -480,7 +527,7 @@ namespace Barotrauma } else if (hasAi) { - var aiCharacter = new AICharacter(file, position, characterInfo, isNetworkPlayer); + var aiCharacter = new AICharacter(file, position, characterInfo, isRemotePlayer); var ai = new HumanAIController(aiCharacter); aiCharacter.SetAI(ai); @@ -489,13 +536,13 @@ namespace Barotrauma return aiCharacter; } - var character = new Character(file, position, characterInfo, isNetworkPlayer); + var character = new Character(file, position, characterInfo, isRemotePlayer); character.minHealth = -100.0f; return character; } - protected Character(string file, Vector2 position, CharacterInfo characterInfo = null, bool isNetworkPlayer = false) + protected Character(string file, Vector2 position, CharacterInfo characterInfo = null, bool isRemotePlayer = false) : base(null) { @@ -512,7 +559,7 @@ namespace Barotrauma hudProgressBars = new Dictionary(); - IsNetworkPlayer = isNetworkPlayer; + IsRemotePlayer = isRemotePlayer; oxygen = 100.0f; oxygenAvailable = 100.0f; @@ -545,15 +592,10 @@ namespace Barotrauma { AnimController = new FishAnimController(this, doc.Root.Element("ragdoll")); PressureProtection = 100.0f; - //FishAnimController fishAnim = (FishAnimController)animController; - } - - foreach (Limb limb in AnimController.Limbs) - { - limb.body.SetTransform(ConvertUnits.ToSimUnits(position)+limb.SimPosition, 0.0f); - //limb.prevPosition = ConvertUnits.ToDisplayUnits(position); } + AnimController.SetPosition(ConvertUnits.ToSimUnits(position)); + maxHealth = ToolBox.GetAttributeFloat(doc.Root, "health", 100.0f); health = maxHealth; @@ -705,8 +747,13 @@ namespace Barotrauma if (length > 0.0f) targetMovement = targetMovement / length; } - if (Math.Sign(targetMovement.X) == Math.Sign(AnimController.Dir) && IsKeyDown(InputType.Run)) + if (AnimController is HumanoidAnimController && + !((HumanoidAnimController)AnimController).Crouching && + Math.Sign(targetMovement.X) != -Math.Sign(AnimController.Dir) && + IsKeyDown(InputType.Run)) + { targetMovement *= 3.0f; + } targetMovement *= SpeedMultiplier; SpeedMultiplier = 1.0f; @@ -745,6 +792,25 @@ namespace Barotrauma } } + //if (GameMain.Server != null && Character.Controlled != this) + //{ + // if ((dequeuedInput & 0x10) > 0) + // { + // AnimController.TargetDir = Direction.Left; + // } + // else + // { + // AnimController.TargetDir = Direction.Right; + // } + //} + //else if (GameMain.Client != null && Character.controlled != this) + //{ + // if (memPos.Count > 0) + // { + // AnimController.TargetDir = memPos[0].Direction; + // } + //} + if (attackCoolDown >0.0f) { attackCoolDown -= deltaTime; @@ -832,7 +898,7 @@ namespace Barotrauma } - if (IsNetworkPlayer) + if (IsRemotePlayer) { foreach (Key key in keys) { @@ -1032,6 +1098,18 @@ namespace Barotrauma } cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (Submarine == null ? 400.0f : 250.0f)+pressureEffect, 0.05f); } + + if (GameMain.NetworkMember != null && GameMain.NetworkMember.Character == this) + { + if (memLocalPos.Count == 0 || NetTime.Now > memLocalPos.Last().Timestamp + 0.1f) + { + memLocalPos.Add( + new PosInfo( + SimPosition, + AnimController.Dir > 0.0f ? Direction.Right : Direction.Left, + (float)NetTime.Now)); + } + } cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition); if (AnimController.CurrentHull != null && AnimController.CurrentHull.Submarine != null) @@ -1133,7 +1211,8 @@ namespace Barotrauma { foreach (Character c in CharacterList) { - if (c.isDead || c.health <= 0.0f || !c.Enabled) continue; + if (!c.Enabled) continue; + c.AnimController.UpdateAnim(deltaTime); } } @@ -1309,7 +1388,7 @@ namespace Barotrauma aiTarget.SightRange = 0.0f; - aiTarget.SightRange = Mass*10.0f + AnimController.RefLimb.LinearVelocity.Length()*500.0f; + aiTarget.SightRange = Mass*10.0f + AnimController.Collider.LinearVelocity.Length()*500.0f; } public void ShowSpeechBubble(float duration, Color color) @@ -1519,7 +1598,7 @@ namespace Barotrauma // limb.Damage = 100.0f; } - SoundPlayer.PlayDamageSound(DamageSoundType.Implode, 50.0f, AnimController.RefLimb.body); + SoundPlayer.PlayDamageSound(DamageSoundType.Implode, 50.0f, AnimController.Collider); for (int i = 0; i < 10; i++) { @@ -1988,7 +2067,6 @@ namespace Barotrauma keys[(int)InputType.Crouch].Held = crouchState; - float dir = 1.0f; Vector2 pos = Vector2.Zero; @@ -2023,38 +2101,41 @@ namespace Barotrauma pos.X = message.ReadFloat(); pos.Y = message.ReadFloat(); - if (inSub != (Submarine != null)) - { - AnimController.Teleport(pos - SimPosition, Vector2.Zero); - } + if (inSub != (Submarine != null)) + { + AnimController.Teleport(pos - SimPosition, Vector2.Zero); + memPos.Clear(); + } - if ((pos-SimPosition).Length()>600.0f) - { - AnimController.Teleport(pos - SimPosition, -AnimController.RefLimb.LinearVelocity); - } + if ((pos-SimPosition).Length()>600.0f) + { + AnimController.Teleport(pos - SimPosition, -AnimController.MainLimb.LinearVelocity); + memPos.Clear(); + } - if (inSub) - { - //AnimController.FindHull(ConvertUnits.ToDisplayUnits(pos) - Submarine.Loaded.WorldPosition); - Submarine prevSub = Submarine; + if (inSub) + { + //AnimController.FindHull(ConvertUnits.ToDisplayUnits(pos) - Submarine.Loaded.WorldPosition); + Submarine prevSub = Submarine; - Hull newHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(pos), AnimController.CurrentHull, false); - if (newHull != null) - { - AnimController.CurrentHull = newHull; - Submarine = newHull.Submarine; - } + Hull newHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(pos), AnimController.CurrentHull, false); + if (newHull != null) + { + AnimController.CurrentHull = newHull; + Submarine = newHull.Submarine; + } - if (prevSub != null && Submarine != null && prevSub!=Submarine) - { - AnimController.Teleport(pos - SimPosition, Vector2.Zero); - } - } - else - { - AnimController.CurrentHull = null; - Submarine = null; - } + if (prevSub != null && Submarine != null && prevSub!=Submarine) + { + AnimController.Teleport(pos - SimPosition, Vector2.Zero); + memPos.Clear(); + } + } + else + { + AnimController.CurrentHull = null; + Submarine = null; + } if (secondaryKeyState) { @@ -2068,11 +2149,13 @@ namespace Barotrauma { cursorPosition = Position + new Vector2(1000.0f, 0.0f) * dir; - AnimController.TargetDir = dir < 0 ? Direction.Left : Direction.Right; + //AnimController.TargetDir = dir < 0 ? Direction.Left : Direction.Right; } - AnimController.RefLimb.body.TargetPosition = - AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime); + //AnimController.RefLimb.body.TargetPosition = + // AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime); + + memPos.Add(new PosInfo(pos, dir < 0 ? Direction.Left : Direction.Right, sendingTime)); LastNetworkUpdate = sendingTime; diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index dc5e5ada9..05e254bb6 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -28,7 +28,6 @@ namespace Barotrauma //the physics body of the limb public PhysicsBody body; - private Texture2D bodyShapeTexture; private readonly int refJointIndex; @@ -73,11 +72,6 @@ namespace Barotrauma private List wearingItems; private Vector2 animTargetPos; - - public Texture2D BodyShapeTexture - { - get { return bodyShapeTexture; } - } public bool DoesFlip { @@ -334,7 +328,7 @@ namespace Barotrauma } } - public void Move(Vector2 pos, float amount, bool pullFromCenter=false) + public void MoveToPos(Vector2 pos, float force, bool pullFromCenter=false) { Vector2 pullPos = body.SimPosition; if (pullJoint!=null && !pullFromCenter) @@ -344,10 +338,7 @@ namespace Barotrauma animTargetPos = pos; - Vector2 vel = body.LinearVelocity; - Vector2 deltaPos = pos - pullPos; - deltaPos *= amount; - body.ApplyLinearImpulse((deltaPos - vel * 0.5f) * body.Mass, pullPos); + body.MoveToPos(pos, force, pullPos); } public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound) @@ -445,36 +436,12 @@ namespace Barotrauma { //DebugConsole.ThrowError("CHARACTER EXPLODED"); body.ResetDynamics(); - body.SetTransform(character.AnimController.RefLimb.SimPosition, 0.0f); + body.SetTransform(character.SimPosition, 0.0f); } 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; @@ -585,34 +552,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true); } - if (bodyShapeTexture == null) - { - switch (body.BodyShape) - { - case PhysicsBody.Shape.Rectangle: - bodyShapeTexture = GUI.CreateRectangle( - (int)ConvertUnits.ToDisplayUnits(body.width), - (int)ConvertUnits.ToDisplayUnits(body.height)); - break; - - case PhysicsBody.Shape.Capsule: - bodyShapeTexture = GUI.CreateCapsule( - (int)ConvertUnits.ToDisplayUnits(body.radius), - (int)ConvertUnits.ToDisplayUnits(body.height)); - break; - case PhysicsBody.Shape.Circle: - bodyShapeTexture = GUI.CreateCircle((int)ConvertUnits.ToDisplayUnits(body.radius)); - break; - } - } - - spriteBatch.Draw( - bodyShapeTexture, - new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), - null, - character.Submarine!=null ? Color.White : Color.Cyan, - -body.DrawRotation, - new Vector2(bodyShapeTexture.Width / 2, bodyShapeTexture.Height / 2), 1.0f, SpriteEffects.None, 0.0f); + } @@ -624,11 +564,6 @@ namespace Barotrauma body.Remove(); - if (bodyShapeTexture != null) - { - bodyShapeTexture.Dispose(); - } - if (hitSound != null) hitSound.Remove(); } } diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index d0ed6f87d..e981bde10 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -428,7 +428,7 @@ namespace Barotrauma characterIndex = -1; } - var matchingCharacters = Character.CharacterList.FindAll(c => !c.IsNetworkPlayer && c.Name.ToLowerInvariant() == characterName); + var matchingCharacters = Character.CharacterList.FindAll(c => !c.IsRemotePlayer && c.Name.ToLowerInvariant() == characterName); if (!matchingCharacters.Any()) { diff --git a/Subsurface/Source/Items/Components/Holdable/Pickable.cs b/Subsurface/Source/Items/Components/Holdable/Pickable.cs index b4a4df6ca..a4733defc 100644 --- a/Subsurface/Source/Items/Components/Holdable/Pickable.cs +++ b/Subsurface/Source/Items/Components/Holdable/Pickable.cs @@ -151,7 +151,7 @@ namespace Barotrauma.Items.Components StopPicking(picker); - if (!picker.IsNetworkPlayer) OnPicked(picker); + if (!picker.IsRemotePlayer) OnPicked(picker); yield return CoroutineStatus.Success; } 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/Items/Components/Machines/Controller.cs b/Subsurface/Source/Items/Components/Machines/Controller.cs index 1aa1313b4..ae10f6b79 100644 --- a/Subsurface/Source/Items/Components/Machines/Controller.cs +++ b/Subsurface/Source/Items/Components/Machines/Controller.cs @@ -92,7 +92,7 @@ namespace Barotrauma.Items.Components if (userPos != 0.0f) { - float torsoX = ConvertUnits.ToDisplayUnits(character.AnimController.RefLimb.SimPosition.X); + float torsoX = character.Position.X; Vector2 diff = new Vector2(item.Rect.X + UserPos - torsoX, 0.0f); @@ -191,7 +191,7 @@ namespace Barotrauma.Items.Components cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (focusTarget as Item).Prefab.OffsetOnSelected, deltaTime*10.0f); } - if (!character.IsNetworkPlayer || character.ViewTarget == focusTarget) + if (!character.IsRemotePlayer || character.ViewTarget == focusTarget) { item.SendSignal(0, ToolBox.Vector2ToString(character.CursorWorldPosition), "position_out"); } diff --git a/Subsurface/Source/Items/Components/Projectile.cs b/Subsurface/Source/Items/Components/Projectile.cs index 06571e940..c525bb5a1 100644 --- a/Subsurface/Source/Items/Components/Projectile.cs +++ b/Subsurface/Source/Items/Components/Projectile.cs @@ -49,19 +49,11 @@ namespace Barotrauma.Items.Components { IgnoredBodies = new List(); - //launchImpulse = ToolBox.GetAttributeFloat(element, "launchimpulse", 10.0f); - //characterUsable = ToolBox.GetAttributeBool(element, "characterusable", false); - foreach (XElement subElement in element.Elements()) { if (subElement.Name.ToString().ToLowerInvariant() != "attack") continue; attack = new Attack(subElement); } - - //bleedingDamage = ToolBox.GetAttributeFloat(element, "bleedingdamage", 0.0f); - //bluntDamage = ToolBox.GetAttributeFloat(element, "bluntdamage", 0.0f); - - //doesStick = ToolBox.GetAttributeBool(element, "doesstick", false); } public override bool Use(float deltaTime, Character character = null) @@ -150,6 +142,11 @@ namespace Barotrauma.Items.Components { if (IgnoredBodies.Contains(f2.Body)) return false; + if (f2.CollisionCategories == Physics.CollisionCharacter && !(f2.Body.UserData is Limb)) + { + return false; + } + AttackResult attackResult = new AttackResult(0.0f, 0.0f); if (attack != null) { diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index 3a51cc0e6..d6bda4e63 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -420,7 +420,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 b6d4f7cfa..1a0d1296a 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -434,7 +434,7 @@ namespace Barotrauma { Vector2 normal = Vector2.Normalize(Body.Position - limb.SimPosition); - float impact = Math.Min(Vector2.Dot(Velocity - limb.LinearVelocity, -normal), 5.0f); + float impact = Math.Min(Vector2.Dot(Velocity - limb.LinearVelocity, -normal), 50.0f) / 5.0f; ApplyImpact(impact * Math.Min(limb.Mass / 200.0f, 1), -normal, contact); } @@ -497,8 +497,8 @@ namespace Barotrauma FixedArray2 points; contact.GetWorldManifold(out normal2, out points); - Vector2 normalizedVel = limb.character.AnimController.RefLimb.LinearVelocity == Vector2.Zero ? - Vector2.Zero : Vector2.Normalize(limb.character.AnimController.RefLimb.LinearVelocity); + Vector2 normalizedVel = limb.character.AnimController.Collider.LinearVelocity == Vector2.Zero ? + Vector2.Zero : Vector2.Normalize(limb.character.AnimController.Collider.LinearVelocity); Vector2 targetPos = ConvertUnits.ToDisplayUnits(points[0] - normal2); @@ -558,9 +558,10 @@ namespace Barotrauma foreach (Limb limb in c.AnimController.Limbs) { - if (c.AnimController.LowestLimb == limb) continue; 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/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 1f53804fc..00d5ba276 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -664,7 +664,7 @@ namespace Barotrauma.Networking List crew = new List(); foreach (Character c in Character.CharacterList) { - if (!c.IsNetworkPlayer || !c.IsHumanoid || c.Info==null) continue; + if (!c.IsRemotePlayer || !c.IsHumanoid || c.Info==null) continue; crew.Add(c); } diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 670a25371..32218b8b8 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -394,7 +394,7 @@ namespace Barotrauma.Networking if (!(c is AICharacter) || c.IsDead) continue; if (Character.CharacterList.Any( - c2 => c2.IsNetworkPlayer && + c2 => c2.IsRemotePlayer && Vector2.Distance(c2.WorldPosition, c.WorldPosition) < ignoreDistance)) { new NetworkEvent(NetworkEventType.EntityUpdate, c.ID, false); diff --git a/Subsurface/Source/Physics/Physics.cs b/Subsurface/Source/Physics/Physics.cs index 69fa6f870..e63b97173 100644 --- a/Subsurface/Source/Physics/Physics.cs +++ b/Subsurface/Source/Physics/Physics.cs @@ -6,8 +6,6 @@ namespace Barotrauma { static class Physics { - private static double alpha; - public const Category CollisionNone = Category.None; public const Category CollisionAll = Category.All; public const Category CollisionWall = Category.Cat1; diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index 0029c26e6..50b217a3c 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -53,6 +53,8 @@ namespace Barotrauma Vector2 offsetFromTargetPos; + private float netInterpolationState; + public Shape BodyShape { get { return bodyShape; } @@ -118,10 +120,17 @@ namespace Barotrauma set { dir = value; } } + private bool isEnabled = true; + private bool isPhysEnabled = true; public bool Enabled + { + get { return isEnabled; } + set { isEnabled = value; if (isEnabled) body.Enabled = isPhysEnabled; else body.Enabled = false; } + } + public bool PhysEnabled { get { return body.Enabled; } - set { body.Enabled = value; } + set { isPhysEnabled = value; if (Enabled) body.Enabled = value; } } public Vector2 SimPosition @@ -192,6 +201,12 @@ namespace Barotrauma set { body.CollidesWith = value; } } + private Texture2D bodyShapeTexture; + public Texture2D BodyShapeTexture + { + get { return bodyShapeTexture; } + } + public PhysicsBody(XElement element, float scale = 1.0f) : this(element, Vector2.Zero, scale) { @@ -227,7 +242,6 @@ namespace Barotrauma body.Restitution = 0.05f; body.BodyType = BodyType.Dynamic; - //body.AngularDamping = Limb.LimbAngularDamping; body.UserData = this; @@ -245,6 +259,11 @@ namespace Barotrauma body = BodyFactory.CreateRectangle(GameMain.World, width, height, density); bodyShape = Shape.Rectangle; } + else if (radius != 0.0f && width != 0.0f) + { + body = BodyFactory.CreateCapsuleHorizontal(GameMain.World, width, radius, density); + bodyShape = Shape.Capsule; + } else if (radius != 0.0f && height != 0.0f) { body = BodyFactory.CreateCapsule(GameMain.World, height, radius, density); @@ -322,11 +341,51 @@ namespace Barotrauma } body.SetTransform(targetPosition, targetRotation == 0.0f ? body.Rotation : targetRotation); - //body.LinearVelocity = targetVelocity; - //body.AngularVelocity = targetAngularVelocity; targetPosition = Vector2.Zero; } + public void MoveToPos(Vector2 pos, float force, Vector2? pullPos = null) + { + if (pullPos==null) pullPos = body.Position; + + Vector2 vel = body.LinearVelocity; + Vector2 deltaPos = pos - (Vector2)pullPos; + deltaPos *= force; + 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() { @@ -361,10 +420,88 @@ namespace Barotrauma color = Color.Blue; } - sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color, -drawRotation, scale, spriteEffect, depth); - + sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color, -drawRotation, scale, spriteEffect, depth); } + public void DebugDraw(SpriteBatch spriteBatch, Color color) + { + if (bodyShapeTexture == null) + { + switch (BodyShape) + { + case PhysicsBody.Shape.Rectangle: + bodyShapeTexture = GUI.CreateRectangle( + (int)ConvertUnits.ToDisplayUnits(width), + (int)ConvertUnits.ToDisplayUnits(height)); + break; + + case PhysicsBody.Shape.Capsule: + bodyShapeTexture = GUI.CreateCapsule( + (int)ConvertUnits.ToDisplayUnits(radius), + (int)ConvertUnits.ToDisplayUnits(Math.Max(height,width))); + break; + case PhysicsBody.Shape.Circle: + bodyShapeTexture = GUI.CreateCircle((int)ConvertUnits.ToDisplayUnits(radius)); + break; + } + } + + float rot = -DrawRotation; + if (bodyShape == PhysicsBody.Shape.Capsule && width > height) + { + rot -= MathHelper.PiOver2; + } + + spriteBatch.Draw( + bodyShapeTexture, + new Vector2(DrawPosition.X, -DrawPosition.Y), + null, + color, + rot, + new Vector2(bodyShapeTexture.Width / 2, bodyShapeTexture.Height / 2), + 1.0f, SpriteEffects.None, 0.0f); + } + + public void CorrectPosition(List positionBuffer, float deltaTime, out Vector2 newVelocity) + { + newVelocity = Vector2.Zero; + if (positionBuffer.Count < 2) return; + + PosInfo prev = positionBuffer[0]; + PosInfo next = positionBuffer[1]; + + Vector2 currPos = SimPosition; + + //interpolate the position of the collider from the first position in the buffer towards the second + if (prev.Timestamp < next.Timestamp) + { + //if there are more than 2 positions in the buffer, + //increase the interpolation speed to catch up with the server + float speedMultiplier = 1.0f + (float)Math.Pow((positionBuffer.Count - 2) / 2.0f, 2.0f); + + netInterpolationState += (deltaTime * speedMultiplier) / (next.Timestamp - prev.Timestamp); + currPos = Vector2.Lerp(prev.Position, next.Position, netInterpolationState); + + //override the targetMovement to make the character play the walking/running animation + newVelocity = (next.Position - prev.Position) / (next.Timestamp - prev.Timestamp); + } + else + { + currPos = next.Position; + netInterpolationState = 1.0f; + } + + SetTransform(currPos, Rotation); + + if (netInterpolationState >= 1.0f) + { + netInterpolationState = 0.0f; + positionBuffer.RemoveAt(0); + } + } + + + /// /// rotate the body towards the target rotation in the "shortest direction" /// @@ -374,9 +511,16 @@ namespace Barotrauma float angle = MathUtils.GetShortestAngle(nextAngle, targetRotation); - float torque = body.Mass * angle * 60.0f * (force/100.0f); + float torque = angle * 60.0f * (force/100.0f); - body.ApplyTorque(torque); + if (body.IsKinematic) + { + body.AngularVelocity = torque; + } + else + { + body.ApplyTorque(body.Mass * torque); + } } @@ -440,6 +584,12 @@ namespace Barotrauma { list.Remove(this); GameMain.World.RemoveBody(body); + + if (bodyShapeTexture != null) + { + bodyShapeTexture.Dispose(); + bodyShapeTexture = null; + } } } diff --git a/Subsurface/Source/Screens/EditCharacterScreen.cs b/Subsurface/Source/Screens/EditCharacterScreen.cs index 706faa041..b9920f840 100644 --- a/Subsurface/Source/Screens/EditCharacterScreen.cs +++ b/Subsurface/Source/Screens/EditCharacterScreen.cs @@ -173,12 +173,12 @@ namespace Barotrauma DrawJoints(spriteBatch, limb, limbBodyPos); - if (limb.BodyShapeTexture == null) continue; + //if (limb.BodyShapeTexture == null) continue; - spriteBatch.Draw(limb.BodyShapeTexture, limbBodyPos, - null, Color.White, 0.0f, - new Vector2(limb.BodyShapeTexture.Width, limb.BodyShapeTexture.Height) / 2, - 1.0f, SpriteEffects.None, 0.0f); + //spriteBatch.Draw(limb.BodyShapeTexture, limbBodyPos, + // null, Color.White, 0.0f, + // new Vector2(limb.BodyShapeTexture.Width, limb.BodyShapeTexture.Height) / 2, + // 1.0f, SpriteEffects.None, 0.0f); GUI.DrawLine(spriteBatch, limbBodyPos + Vector2.UnitY * 5.0f, limbBodyPos - Vector2.UnitY * 5.0f, Color.White); GUI.DrawLine(spriteBatch, limbBodyPos + Vector2.UnitX * 5.0f, limbBodyPos - Vector2.UnitX * 5.0f, Color.White); diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index f17e12431..d7401f0b3 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -400,6 +400,7 @@ namespace Barotrauma spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend); + float r = Math.Min(CharacterHUD.damageOverlayTimer * 0.5f, 0.5f); spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Lerp(new Color(0.1f, 0.1f, 0.1f), Color.Red, r)); From a8484e10ff9c1661971d0080b99ca646c5947f33 Mon Sep 17 00:00:00 2001 From: Regalis Date: Sun, 23 Oct 2016 19:01:46 +0300 Subject: [PATCH 2/5] Unlit LOS effect, IJKL doesn't move the sub when the debug console is open --- Subsurface/Source/Screens/GameScreen.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index d7401f0b3..f2b951eaa 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -95,7 +95,8 @@ namespace Barotrauma { #if DEBUG - if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null) + if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null && + !DebugConsole.IsOpen) { var closestSub = Submarine.GetClosest(cam.WorldViewCenter); if (closestSub == null) closestSub = GameMain.GameSession.Submarine; @@ -336,7 +337,7 @@ namespace Barotrauma Submarine.DrawDamageable(spriteBatch, null); spriteBatch.End(); - GameMain.LightManager.DrawLightMap(spriteBatch, lightBlur.Effect); + //GameMain.LightManager.DrawLightMap(spriteBatch, lightBlur.Effect); GameMain.LightManager.DrawLOS(spriteBatch, lightBlur.Effect, true); } From c33a4ba5e5e69f72d9d18881f9fd159ee584ad79 Mon Sep 17 00:00:00 2001 From: Regalis Date: Tue, 25 Oct 2016 15:40:19 +0300 Subject: [PATCH 3/5] AmbientLightHulls optimization (only spread to adjacent hulls once, not once per every gap between the hulls) --- Subsurface/Source/Map/Lights/LightManager.cs | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Subsurface/Source/Map/Lights/LightManager.cs b/Subsurface/Source/Map/Lights/LightManager.cs index 3fd45ac65..b3d4c8382 100644 --- a/Subsurface/Source/Map/Lights/LightManager.cs +++ b/Subsurface/Source/Map/Lights/LightManager.cs @@ -328,22 +328,22 @@ namespace Barotrauma.Lights hullAmbientLight.Add(hull, currColor); } + Color nextHullLight = currColor * AmbientLightFalloff; + //light getting too dark to notice -> no need to spread further + if (nextHullLight.A < 20) return hullAmbientLight; + + //use hashset to make sure that each hull is only included once + HashSet hulls = new HashSet(); foreach (Gap g in hull.ConnectedGaps) { - for (int i = 0; i < g.linkedTo.Count;i++ ) - { - if (g.linkedTo[i] is Hull) - { - if (g.linkedTo[i] == hull) continue; + if (!g.IsRoomToRoom || !g.PassAmbientLight || g.Open < 0.5f) continue; + + hulls.Add((g.linkedTo[0] == hull ? g.linkedTo[1] : g.linkedTo[0]) as Hull); + } - Color nextHullLight = currColor * AmbientLightFalloff; - if (!g.PassAmbientLight) nextHullLight *= g.Open; - - if (nextHullLight.A < 10) continue; - - hullAmbientLight = AmbientLightHulls((Hull)g.linkedTo[i], hullAmbientLight, nextHullLight); - } - } + foreach (Hull h in hulls) + { + hullAmbientLight = AmbientLightHulls(h, hullAmbientLight, nextHullLight); } return hullAmbientLight; From ac8edb5b2a80f5115a74a2d65b3d277198da0386 Mon Sep 17 00:00:00 2001 From: Regalis Date: Tue, 25 Oct 2016 18:58:56 +0300 Subject: [PATCH 4/5] Fixed monster/artifact events being out of sync between the server and the clients --- .../BackgroundSprite/BackgroundCreatureManager.cs | 10 +++++----- Subsurface/Source/Events/Missions/CargoMission.cs | 2 +- Subsurface/Source/Map/Hull.cs | 2 +- Subsurface/Source/Map/WayPoint.cs | 4 ++-- Subsurface/Source/Networking/GameServer.cs | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Subsurface/Source/Characters/BackgroundSprite/BackgroundCreatureManager.cs b/Subsurface/Source/Characters/BackgroundSprite/BackgroundCreatureManager.cs index 4a3de9511..ed2974c81 100644 --- a/Subsurface/Source/Characters/BackgroundSprite/BackgroundCreatureManager.cs +++ b/Subsurface/Source/Characters/BackgroundSprite/BackgroundCreatureManager.cs @@ -64,14 +64,14 @@ namespace Barotrauma var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine==null); if (wayPoints.Any()) { - WayPoint wp = wayPoints[Rand.Int(wayPoints.Count)]; + WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, false)]; pos = new Vector2(wp.Rect.X, wp.Rect.Y); - pos += Rand.Vector(200.0f); + pos += Rand.Vector(200.0f, false); } else { - pos = Rand.Vector(2000.0f); + pos = Rand.Vector(2000.0f, false); } } else @@ -80,9 +80,9 @@ namespace Barotrauma } - var prefab = prefabs[Rand.Int(prefabs.Count)]; + var prefab = prefabs[Rand.Int(prefabs.Count, false)]; - int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax); + int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax, false); List swarmMembers = new List(); for (int n = 0; n < amount; n++) diff --git a/Subsurface/Source/Events/Missions/CargoMission.cs b/Subsurface/Source/Events/Missions/CargoMission.cs index b52797ad2..c1d6a0e1d 100644 --- a/Subsurface/Source/Events/Missions/CargoMission.cs +++ b/Subsurface/Source/Events/Missions/CargoMission.cs @@ -53,7 +53,7 @@ namespace Barotrauma return; } - WayPoint cargoSpawnPos = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub); + WayPoint cargoSpawnPos = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub, true); if (cargoSpawnPos==null) { DebugConsole.ThrowError("Couldn't spawn items for cargo mission, cargo spawnpoint not found"); diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index 9667555b4..bd63390df 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -201,7 +201,7 @@ namespace Barotrauma { rect = rectangle; - OxygenPercentage = Rand.Range(90.0f, 100.0f, false); + OxygenPercentage = 100.0f; fireSources = new List(); diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index 35dae5e41..7b6809526 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -636,7 +636,7 @@ namespace Barotrauma if (!wayPoint2.linkedTo.Contains(this)) wayPoint2.linkedTo.Add(this); } - public static WayPoint GetRandom(SpawnType spawnType = SpawnType.Human, Job assignedJob = null, Submarine sub = null) + public static WayPoint GetRandom(SpawnType spawnType = SpawnType.Human, Job assignedJob = null, Submarine sub = null, bool useSyncedRand = false) { List wayPoints = new List(); @@ -651,7 +651,7 @@ namespace Barotrauma if (!wayPoints.Any()) return null; - return wayPoints[Rand.Int(wayPoints.Count(), false)]; + return wayPoints[Rand.Int(wayPoints.Count, !useSyncedRand)]; } public static WayPoint[] SelectCrewSpawnPoints(List crew, Submarine submarine) diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 32218b8b8..f4714b826 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -976,7 +976,7 @@ namespace Barotrauma.Networking var cargoRoom = cargoSpawnPos.CurrentHull; Vector2 position = new Vector2( - cargoSpawnPos.Position.X + Rand.Range(-20.0f, 20.0f, false), + cargoSpawnPos.Position.X + Rand.Range(-20.0f, 20.0f), cargoRoom.Rect.Y - cargoRoom.Rect.Height); foreach (string s in extraCargo.Keys) From 07f8c966ab639a6930411322daea4582209b9e9a Mon Sep 17 00:00:00 2001 From: Regalis Date: Tue, 25 Oct 2016 19:01:19 +0300 Subject: [PATCH 5/5] Submarine position is synced using the same logic as the characters, AICharacter position syncing --- .../Content/Characters/Crawler/crawler.xml | 2 +- .../Content/Characters/Endworm/endworm.xml | 2 +- .../Content/Characters/Moloch/moloch.xml | 2 +- Subsurface/Source/Characters/AICharacter.cs | 15 +- .../Animation/FishAnimController.cs | 2 + Subsurface/Source/Characters/Character.cs | 42 +-- .../Source/Items/Components/DockingPort.cs | 4 +- Subsurface/Source/Map/Submarine.cs | 77 ++++-- Subsurface/Source/Map/SubmarineBody.cs | 245 +++++++----------- Subsurface/Source/Networking/GameClient.cs | 1 + .../Source/Networking/RespawnManager.cs | 10 +- Subsurface/Source/Physics/PhysicsBody.cs | 88 ++++--- 12 files changed, 234 insertions(+), 256 deletions(-) diff --git a/Subsurface/Content/Characters/Crawler/crawler.xml b/Subsurface/Content/Characters/Crawler/crawler.xml index 313a7867d..d2a2dbab5 100644 --- a/Subsurface/Content/Characters/Crawler/crawler.xml +++ b/Subsurface/Content/Characters/Crawler/crawler.xml @@ -8,7 +8,7 @@ diff --git a/Subsurface/Content/Characters/Endworm/endworm.xml b/Subsurface/Content/Characters/Endworm/endworm.xml index 157c81d7a..8090dd20d 100644 --- a/Subsurface/Content/Characters/Endworm/endworm.xml +++ b/Subsurface/Content/Characters/Endworm/endworm.xml @@ -5,7 +5,7 @@ - + diff --git a/Subsurface/Content/Characters/Moloch/moloch.xml b/Subsurface/Content/Characters/Moloch/moloch.xml index aba30598b..9a9b66030 100644 --- a/Subsurface/Content/Characters/Moloch/moloch.xml +++ b/Subsurface/Content/Characters/Moloch/moloch.xml @@ -6,7 +6,7 @@ - + diff --git a/Subsurface/Source/Characters/AICharacter.cs b/Subsurface/Source/Characters/AICharacter.cs index cf48cf5a9..3fe736a58 100644 --- a/Subsurface/Source/Characters/AICharacter.cs +++ b/Subsurface/Source/Characters/AICharacter.cs @@ -254,10 +254,7 @@ namespace Barotrauma AnimController.TargetDir = (targetDir) ? Direction.Right : Direction.Left; AnimController.TargetMovement = targetMovement; - - AnimController.MainLimb.body.TargetPosition = pos; - //AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime); - + if (inSub) { Hull newHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(pos), AnimController.CurrentHull, false); @@ -267,7 +264,15 @@ namespace Barotrauma Submarine = newHull.Submarine; } } - + + int index = 0; + while (index < memPos.Count && sendingTime > memPos[index].Timestamp) + { + index++; + } + + memPos.Insert(index, new PosInfo(pos, (targetDir) ? Direction.Right : Direction.Left, sendingTime)); + LastNetworkUpdate = sendingTime; break; } diff --git a/Subsurface/Source/Characters/Animation/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs index 9afc2afb2..b28c589bf 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -195,6 +195,8 @@ namespace Barotrauma for (int i = 0; i < Limbs.Count(); i++) { + if (Limbs[i].SteerForce <= 0.0f) continue; + Vector2 pullPos = Limbs[i].pullJoint == null ? Limbs[i].SimPosition : Limbs[i].pullJoint.WorldAnchorA; Limbs[i].body.ApplyForce(movement * Limbs[i].SteerForce * Limbs[i].Mass, pullPos); diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 1e6543c59..88124bb67 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -14,33 +14,6 @@ using System.Xml.Linq; namespace Barotrauma { - struct PosInfo - { - public readonly Vector2 Position; - public readonly Direction Direction; - - public readonly float Timestamp; - public readonly UInt32 ID; - - public PosInfo(Vector2 pos, Direction dir, float time) - { - Position = pos; - Direction = dir; - Timestamp = time; - - ID = 0; - } - - public PosInfo(Vector2 pos, Direction dir, UInt32 ID) - { - Position = pos; - Direction = dir; - this.ID = ID; - - Timestamp = 0.0f; - } - } - class Character : Entity, IDamageable, IPropertyObject { public static List CharacterList = new List(); @@ -53,7 +26,7 @@ namespace Barotrauma get { return netStateID; } } - List memPos = new List(); + protected List memPos = new List(); private bool networkUpdateSent; List memLocalPos = new List(); @@ -2148,14 +2121,15 @@ namespace Barotrauma else { cursorPosition = Position + new Vector2(1000.0f, 0.0f) * dir; - - //AnimController.TargetDir = dir < 0 ? Direction.Left : Direction.Right; + } + + int index = 0; + while (index < memPos.Count && sendingTime > memPos[index].Timestamp) + { + index++; } - //AnimController.RefLimb.body.TargetPosition = - // AnimController.EstimateCurrPosition(pos, (float)(NetTime.Now) - sendingTime); - - memPos.Add(new PosInfo(pos, dir < 0 ? Direction.Left : Direction.Right, sendingTime)); + memPos.Insert(index, new PosInfo(pos, dir < 0 ? Direction.Left : Direction.Right, sendingTime)); LastNetworkUpdate = sendingTime; diff --git a/Subsurface/Source/Items/Components/DockingPort.cs b/Subsurface/Source/Items/Components/DockingPort.cs index f89987ced..57757c14f 100644 --- a/Subsurface/Source/Items/Components/DockingPort.cs +++ b/Subsurface/Source/Items/Components/DockingPort.cs @@ -214,7 +214,7 @@ namespace Barotrauma.Items.Components if (useWeldJoint) { joint = JointFactory.CreateWeldJoint(GameMain.World, - item.Submarine.SubBody.Body, dockingTarget.item.Submarine.SubBody.Body, + item.Submarine.PhysicsBody.FarseerBody, dockingTarget.item.Submarine.PhysicsBody.FarseerBody, ConvertUnits.ToSimUnits(pos1), FarseerPhysics.ConvertUnits.ToSimUnits(pos2), true); ((WeldJoint)joint).FrequencyHz = 1.0f; @@ -222,7 +222,7 @@ namespace Barotrauma.Items.Components else { var distanceJoint = JointFactory.CreateDistanceJoint(GameMain.World, - item.Submarine.SubBody.Body, dockingTarget.item.Submarine.SubBody.Body, + item.Submarine.PhysicsBody.FarseerBody, dockingTarget.item.Submarine.PhysicsBody.FarseerBody, ConvertUnits.ToSimUnits(pos1), FarseerPhysics.ConvertUnits.ToSimUnits(pos2), true); distanceJoint.Length = 0.01f; diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index d6bda4e63..2eb0cd2c4 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -75,7 +75,7 @@ namespace Barotrauma private Vector2 prevPosition; - private float lastNetworkUpdate, networkUpdateTimer; + private float networkUpdateTimer; private EntityGrid entityGrid = null; @@ -140,6 +140,11 @@ namespace Barotrauma get { return subBody; } } + public PhysicsBody PhysicsBody + { + get { return subBody.Body; } + } + public Rectangle Borders { get @@ -289,6 +294,7 @@ namespace Barotrauma { MapEntity.mapEntityList[i].Draw(spriteBatch, editing); } + } public static void DrawFront(SpriteBatch spriteBatch, bool editing = false) @@ -298,6 +304,32 @@ namespace Barotrauma if (MapEntity.mapEntityList[i].DrawOverWater) MapEntity.mapEntityList[i].Draw(spriteBatch, editing, false); } + + + if (GameMain.DebugDraw) + { + foreach (Submarine sub in Submarine.Loaded) + { + if (sub.subBody.MemPos.Count < 2) continue; + + Vector2 prevPos = ConvertUnits.ToDisplayUnits(sub.subBody.MemPos[0].Position); + prevPos.Y = -prevPos.Y; + + for (int i = 1; i < sub.subBody.MemPos.Count; i++) + { + Vector2 currPos = ConvertUnits.ToDisplayUnits(sub.subBody.MemPos[i].Position); + currPos.Y = -currPos.Y; + + GUI.DrawRectangle(spriteBatch, new Rectangle((int)currPos.X - 10, (int)currPos.Y - 10, 20, 20), Color.Blue * 0.6f, true, 0.01f); + GUI.DrawLine(spriteBatch, prevPos, currPos, Color.Cyan * 0.5f, 0, 5); + + prevPos = currPos; + } + + } + + + } } public static void DrawDamageable(SpriteBatch spriteBatch, Effect damageEffect, bool editing = false) @@ -530,9 +562,8 @@ namespace Barotrauma } Vector2 pos = new Vector2(subBody.Position.X, subBody.Position.Y); - SubmarineBody newSubBody = new SubmarineBody(this); - GameMain.World.RemoveBody(subBody.Body); - subBody = newSubBody; + subBody.Body.Remove(); + subBody = new SubmarineBody(this); SetPosition(pos); if (entityGrid != null) @@ -580,7 +611,7 @@ namespace Barotrauma if (this != MainSub && MainSub.DockedTo.Contains(this)) return; //send updates more frequently if moving fast - networkUpdateTimer -= MathHelper.Clamp(Velocity.Length(), 0.1f, 5.0f) * deltaTime; + networkUpdateTimer -= MathHelper.Clamp(Velocity.Length()*10.0f, 0.1f, 5.0f) * deltaTime; if (networkUpdateTimer < 0.0f) { @@ -651,12 +682,9 @@ namespace Barotrauma { if (subBody == null) return false; - message.Write(subBody.Position.X); - message.Write(subBody.Position.Y); - - message.Write(Velocity.X); - message.Write(Velocity.Y); - + message.Write(PhysicsBody.SimPosition.X); + message.Write(PhysicsBody.SimPosition.Y); + return true; } @@ -666,13 +694,13 @@ namespace Barotrauma if (GameMain.Server != null) return false; - Vector2 newTargetPosition, newSpeed; + + Vector2 newTargetPosition; try { - if (sendingTime <= lastNetworkUpdate) return false; - - newTargetPosition = new Vector2(message.ReadFloat(), message.ReadFloat()); - newSpeed = new Vector2(message.ReadFloat(), message.ReadFloat()); + newTargetPosition = new Vector2( + message.ReadFloat(), + message.ReadFloat()); } catch (Exception e) @@ -683,14 +711,21 @@ namespace Barotrauma return false; } - if (!newSpeed.IsValid() || !newTargetPosition.IsValid()) return false; + if (!newTargetPosition.IsValid()) return false; - //newTargetPosition = newTargetPosition + newSpeed * (float)(NetTime.Now - sendingTime); + //already interpolating with more up-to-date data -> ignore + if (subBody.MemPos.Count > 1 && subBody.MemPos[0].Timestamp > sendingTime) + { + return true; + } - subBody.TargetPosition = newTargetPosition; - subBody.Velocity = newSpeed; + int index = 0; + while (index < subBody.MemPos.Count && sendingTime > subBody.MemPos[index].Timestamp) + { + index++; + } - lastNetworkUpdate = sendingTime; + subBody.MemPos.Insert(index, new PosInfo(newTargetPosition, Direction.Right, sendingTime)); return true; } diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 1a0d1296a..61b531a1d 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -32,12 +32,10 @@ namespace Barotrauma private float depthDamageTimer; private readonly Submarine submarine; - - public readonly Body Body; - private Vector2? targetPosition; + public readonly PhysicsBody Body; - //private float mass = 10000.0f; + List memPos = new List(); public Rectangle Borders { @@ -55,19 +53,14 @@ namespace Barotrauma } } - public Vector2 TargetPosition - { - //get { return targetPosition.Value; } - set - { - if (!MathUtils.IsValid(value)) return; - targetPosition = value; - } - } - public Vector2 Position { - get { return ConvertUnits.ToDisplayUnits(Body.Position); } + get { return ConvertUnits.ToDisplayUnits(Body.SimPosition); } + } + + public List MemPos + { + get { return memPos; } } public bool AtDamageDepth @@ -79,10 +72,12 @@ namespace Barotrauma { this.submarine = sub; + Body farseerBody = null; + if (!Hull.hullList.Any()) { - - Body = BodyFactory.CreateRectangle(GameMain.World, 1.0f, 1.0f, 1.0f); + Body = new PhysicsBody(1,1,1,1); + farseerBody = Body.FarseerBody; DebugConsole.ThrowError("WARNING: no hulls found, generating a physics body for the submarine failed."); } else @@ -108,21 +103,20 @@ namespace Barotrauma (int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.X * 2.0f), (int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.Y * 2.0f)); - //var triangulatedVertices = Triangulate.ConvexPartition(shapevertices, TriangulationAlgorithm.Bayazit); - - Body = BodyFactory.CreateBody(GameMain.World, this); + farseerBody = BodyFactory.CreateBody(GameMain.World, this); foreach (Structure wall in Structure.WallList) { if (wall.Submarine != submarine) continue; Rectangle rect = wall.Rect; + FixtureFactory.AttachRectangle( ConvertUnits.ToSimUnits(rect.Width), ConvertUnits.ToSimUnits(rect.Height), 50.0f, ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)), - Body, this); + farseerBody, this); } foreach (Hull hull in Hull.hullList) @@ -135,30 +129,32 @@ namespace Barotrauma ConvertUnits.ToSimUnits(rect.Height), 5.0f, ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)), - Body, this); + farseerBody, this); } } - Body.BodyType = BodyType.Dynamic; - Body.CollisionCategories = Physics.CollisionWall; - Body.CollidesWith = + farseerBody.BodyType = BodyType.Dynamic; + farseerBody.CollisionCategories = Physics.CollisionWall; + farseerBody.CollidesWith = Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionCharacter | Physics.CollisionProjectile | Physics.CollisionWall; - Body.Restitution = Restitution; - Body.Friction = Friction; - Body.FixedRotation = true; + farseerBody.Restitution = Restitution; + farseerBody.Friction = Friction; + farseerBody.FixedRotation = true; //mass = Body.Mass; - Body.Awake = true; - Body.SleepingAllowed = false; - Body.IgnoreGravity = true; - Body.OnCollision += OnCollision; - Body.UserData = submarine; + farseerBody.Awake = true; + farseerBody.SleepingAllowed = false; + farseerBody.IgnoreGravity = true; + farseerBody.OnCollision += OnCollision; + farseerBody.UserData = submarine; + + Body = new PhysicsBody(farseerBody); } @@ -187,59 +183,66 @@ namespace Barotrauma } public void Update(float deltaTime) - { - if (targetPosition != null && targetPosition != Position) + { + if (GameMain.Client != null) { - float dist = Vector2.Distance((Vector2)targetPosition, Position); + //if (memPos.Count > 1 && Vector2.Distance(memPos[1].Position, Body.SimPosition) > 5.0f) + //{ + // Vector2 moveAmount = ConvertUnits.ToDisplayUnits(memPos[1].Position - Body.SimPosition); + + // ForceTranslate(moveAmount); + // DisplaceCharacters(moveAmount); + + // foreach (Submarine sub in submarine.DockedTo) + // { + // sub.SubBody.ForceTranslate(moveAmount); + // sub.SubBody.DisplaceCharacters(moveAmount); + // } + + // memPos.RemoveRange(0, 2); + //} + //else - if (dist > 500.0f) //immediately snap the sub to the target position if more than 500.0f units away + Vector2 newVelocity = Body.LinearVelocity; + Vector2 newPosition = Body.SimPosition; + + Body.CorrectPosition(memPos, deltaTime, out newVelocity, out newPosition); + Vector2 moveAmount = ConvertUnits.ToDisplayUnits(newPosition - Body.SimPosition); + + List subsToMove = new List() { this.submarine }; + subsToMove.AddRange(submarine.DockedTo); + + Submarine closestSub = null; + if (Character.Controlled == null) { - Vector2 moveAmount = (Vector2)targetPosition - ConvertUnits.ToDisplayUnits(Body.Position); - - List dockedBodies = new List() { this }; - submarine.DockedTo.ForEach(d => dockedBodies.Add(d.SubBody)); - - foreach (SubmarineBody dockedBody in dockedBodies) - { - dockedBody.ForceTranslate(moveAmount); - - if ((Character.Controlled != null && Character.Controlled.Submarine == dockedBody.submarine) || - (Character.Controlled == null && Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter) == dockedBody.submarine)) - { - GameMain.GameScreen.Cam.UpdateTransform(false); - } - - dockedBody.submarine.SetPrevTransform(dockedBody.submarine.Position); - dockedBody.submarine.UpdateTransform(); - targetPosition = null; - - dockedBody.DisplaceCharacters(moveAmount); - } - - - } - else if (dist > 50.0f) //lerp the position if (50 < dist < 500) - { - Vector2 moveAmount = Vector2.Normalize((Vector2)targetPosition - Position); - moveAmount *= Math.Min(dist, 100.0f); - - ForceTranslate(moveAmount * deltaTime); - - foreach (Submarine sub in submarine.DockedTo) - { - sub.SubBody.ForceTranslate(moveAmount * deltaTime); - } + closestSub= Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter); } else { - targetPosition = null; + closestSub = Character.Controlled.Submarine; } - } - else - { - targetPosition = null; - } + bool displace = moveAmount.Length() > 100.0f; + + foreach (Submarine sub in subsToMove) + { + sub.PhysicsBody.SetTransform(sub.PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(moveAmount), 0.0f); + sub.PhysicsBody.LinearVelocity = newVelocity; + + if (displace) sub.SubBody.DisplaceCharacters(moveAmount); + } + + if (closestSub != null && subsToMove.Contains(closestSub)) + { + GameMain.GameScreen.Cam.Position += moveAmount; + if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += moveAmount; + + if (Character.Controlled!=null) Character.Controlled.CursorPosition += moveAmount; + } + + return; + } + //------------------------- Vector2 totalForce = CalculateBuoyancy(); @@ -258,51 +261,22 @@ namespace Barotrauma UpdateDepthDamage(deltaTime); } - - + /// - /// Immediately translates the position of the physics body, gamescreen camera and Character.Controlled.CursorPosition - /// - /// Amount to move in display units - private void ForceTranslate(Vector2 amount) - { - Body.SetTransform(Body.Position + ConvertUnits.ToSimUnits(amount), 0.0f); - - bool isClosestSub = false; - if (Character.Controlled == null) - { - isClosestSub = Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter) == submarine; - } - else - { - isClosestSub = Character.Controlled.Submarine == submarine; - - Character.Controlled.CursorPosition += amount; - } - - if (isClosestSub) - { - GameMain.GameScreen.Cam.Position += amount; - if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += amount; - } - } - - - /// - /// Moves away any character that is inside the bounding box of the sub (but not inside it) + /// Moves away any character that is inside the bounding box of the sub (but not inside the sub) /// /// The translation that was applied to the sub before doing the displacement /// (used for determining where to push the characters) private void DisplaceCharacters(Vector2 subTranslation) { Rectangle worldBorders = Borders; - worldBorders.Location += ConvertUnits.ToDisplayUnits(Body.Position).ToPoint(); + worldBorders.Location += ConvertUnits.ToDisplayUnits(Body.SimPosition).ToPoint(); Vector2 translateDir = Vector2.Normalize(subTranslation); foreach (Character c in Character.CharacterList) { - if (c.AnimController.CurrentHull != null) continue; + if (c.AnimController.CurrentHull != null && c.AnimController.CanEnterSubmarine) continue; foreach (Limb limb in c.AnimController.Limbs) { @@ -317,7 +291,7 @@ namespace Barotrauma //should never be null when casting a line out from inside the bounding box Debug.Assert(intersection != null); - //\"+ translatedir\" in order to move the character slightly away from the wall + //"+ translatedir" in order to move the character slightly away from the wall c.AnimController.SetPosition(ConvertUnits.ToSimUnits(c.WorldPosition + ((Vector2)intersection - limb.WorldPosition)) + translateDir); return; @@ -342,8 +316,6 @@ namespace Barotrauma float neutralPercentage = 0.07f; - Body.IgnoreGravity = true; - float buoyancy = neutralPercentage - waterPercentage; if (buoyancy > 0.0f) buoyancy *= 2.0f; @@ -367,58 +339,25 @@ namespace Barotrauma float depth = DamageDepth - Position.Y; - // float prevTimer = depthDamageTimer; - depthDamageTimer -= deltaTime; - //if (prevTimer>5.0f && depthDamageTimer<=5.0f) - //{ - // SoundPlayer.PlayDamageSound(DamageSoundType.Pressure, 50.0f,); - //} - if (depthDamageTimer > 0.0f) return; foreach (Structure wall in Structure.WallList) { if (wall.Submarine != submarine) continue; - //if (Rand.Int(5) < 4) continue; - if (wall.Health < depth*0.01f) + if (wall.Health < depth * 0.01f) { - Explosion.RangedStructureDamage(wall.WorldPosition, 100.0f, depth*0.01f); + Explosion.RangedStructureDamage(wall.WorldPosition, 100.0f, depth * 0.01f); if (Character.Controlled != null && Character.Controlled.Submarine == submarine) { - GameMain.GameScreen.Cam.Shake = Math.Max(GameMain.GameScreen.Cam.Shake, Math.Min(depth *0.001f, 50.0f)); + GameMain.GameScreen.Cam.Shake = Math.Max(GameMain.GameScreen.Cam.Shake, Math.Min(depth * 0.001f, 50.0f)); } } } - //Vector2 damagePos = Vector2.Zero; - //if (Rand.Int(2)==0) - //{ - // damagePos = new Vector2( - // (Rand.Int(2) == 0) ? Borders.X : Borders.X+Borders.Width, - // Rand.Range(Borders.Y - Borders.Height, Borders.Y)); - //} - //else - //{ - // damagePos = new Vector2( - // Rand.Range(Borders.X, Borders.X + Borders.Width), - // (Rand.Int(2) == 0) ? Borders.Y : Borders.Y - Borders.Height); - //} - - //damagePos += submarine.Position + submarine.HiddenSubPosition; - //SoundPlayer.PlayDamageSound(DamageSoundType.Pressure, 50.0f, damagePos, 10000.0f); - - //if (Character.Controlled != null && Character.Controlled.Submarine == submarine) - //{ - // GameMain.GameScreen.Cam.Shake = depth * PressureDamageMultiplier * 0.1f; - //} - - //Explosion.RangedStructureDamage(damagePos, depth * PressureDamageMultiplier * 50.0f, depth * PressureDamageMultiplier); - //SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, Rand.Range(0.0f, 100.0f), damagePos, 5000.0f); - depthDamageTimer = 10.0f; } @@ -432,7 +371,7 @@ namespace Barotrauma if (collision && limb.Mass > 100.0f) { - Vector2 normal = Vector2.Normalize(Body.Position - limb.SimPosition); + Vector2 normal = Vector2.Normalize(Body.SimPosition - limb.SimPosition); float impact = Math.Min(Vector2.Dot(Velocity - limb.LinearVelocity, -normal), 50.0f) / 5.0f; @@ -445,7 +384,7 @@ namespace Barotrauma VoronoiCell cell = f2.Body.UserData as VoronoiCell; if (cell != null) { - var collisionNormal = Vector2.Normalize(ConvertUnits.ToDisplayUnits(Body.Position) - cell.Center); + var collisionNormal = Vector2.Normalize(ConvertUnits.ToDisplayUnits(Body.SimPosition) - cell.Center); float wallImpact = Vector2.Dot(Velocity, -collisionNormal); @@ -474,7 +413,7 @@ namespace Barotrauma Vector2 normal; FixedArray2 points; contact.GetWorldManifold(out normal, out points); - if (contact.FixtureA.Body == sub.SubBody.Body) + if (contact.FixtureA.Body == sub.SubBody.Body.FarseerBody) { normal = -normal; } diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 00d5ba276..e4e0b2b0f 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -271,6 +271,7 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.Select(); new GUIMessageBox("Connection timed out", "You were disconnected for too long and your character was deleted. Please wait for another round to start."); + myCharacter = null; } GameMain.NetLobbyScreen.ClearPlayers(); diff --git a/Subsurface/Source/Networking/RespawnManager.cs b/Subsurface/Source/Networking/RespawnManager.cs index 0a1be059b..987cd1068 100644 --- a/Subsurface/Source/Networking/RespawnManager.cs +++ b/Subsurface/Source/Networking/RespawnManager.cs @@ -231,8 +231,8 @@ namespace Barotrauma.Networking if (updateReturnTimer > 10.0f) { updateReturnTimer = 0.0f; - - respawnShuttle.SubBody.Body.IgnoreCollisionWith(Level.Loaded.ShaftBody); + + respawnShuttle.PhysicsBody.FarseerBody.IgnoreCollisionWith(Level.Loaded.ShaftBody); shuttleSteering.AutoPilot = true; shuttleSteering.MaintainPos = false; @@ -302,7 +302,7 @@ namespace Barotrauma.Networking private IEnumerable ForceShuttleToPos(Vector2 position, float speed) { - respawnShuttle.SubBody.Body.IgnoreCollisionWith(Level.Loaded.ShaftBody); + respawnShuttle.PhysicsBody.FarseerBody.IgnoreCollisionWith(Level.Loaded.ShaftBody); while (Math.Abs(position.Y - respawnShuttle.WorldPosition.Y) > 100.0f) { @@ -313,7 +313,7 @@ namespace Barotrauma.Networking if (respawnShuttle.SubBody == null) yield return CoroutineStatus.Success; } - respawnShuttle.SubBody.Body.RestoreCollisionWith(Level.Loaded.ShaftBody); + respawnShuttle.PhysicsBody.FarseerBody.RestoreCollisionWith(Level.Loaded.ShaftBody); yield return CoroutineStatus.Success; } @@ -378,7 +378,7 @@ namespace Barotrauma.Networking respawnShuttle.Velocity = Vector2.Zero; - respawnShuttle.SubBody.Body.RestoreCollisionWith(Level.Loaded.ShaftBody); + respawnShuttle.PhysicsBody.FarseerBody.RestoreCollisionWith(Level.Loaded.ShaftBody); } diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index 50b217a3c..e3e4b2e25 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -11,9 +11,35 @@ using System; namespace Barotrauma { + struct PosInfo + { + public readonly Vector2 Position; + public readonly Direction Direction; + + public readonly float Timestamp; + public readonly UInt32 ID; + + public PosInfo(Vector2 pos, Direction dir, float time) + { + Position = pos; + Direction = dir; + Timestamp = time; + + ID = 0; + } + + public PosInfo(Vector2 pos, Direction dir, UInt32 ID) + { + Position = pos; + Direction = dir; + this.ID = ID; + + Timestamp = 0.0f; + } + } + class PhysicsBody { - public enum Shape { Circle, Rectangle, Capsule @@ -70,18 +96,7 @@ namespace Barotrauma targetPosition.Y = MathHelper.Clamp(value.Y, -10000.0f, 10000.0f); } } - - //public Vector2 TargetVelocity - //{ - // get { return targetVelocity; } - // set - // { - // if (!MathUtils.IsValid(value)) return; - // targetVelocity.X = MathHelper.Clamp(value.X, -100.0f, 100.0f); - // targetVelocity.Y = MathHelper.Clamp(value.Y, -100.0f, 100.0f); - // } - //} - + public float TargetRotation { get { return targetRotation; } @@ -92,16 +107,6 @@ namespace Barotrauma } } - //public float TargetAngularVelocity - //{ - // get { return targetAngularVelocity; } - // set - // { - // if (!MathUtils.IsValid(value)) return; - // targetAngularVelocity = value; - // } - //} - public Vector2 DrawPosition { get { return Submarine == null ? drawPosition : drawPosition + Submarine.DrawPosition; } @@ -223,6 +228,16 @@ namespace Barotrauma list.Add(this); } + public PhysicsBody(Body farseerBody) + { + body = farseerBody; + body.UserData = this; + + LastSentPosition = body.Position; + + list.Add(this); + } + public PhysicsBody(XElement element, Vector2 position, float scale=1.0f) { float radius = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "radius", 0.0f)) * scale; @@ -464,35 +479,42 @@ namespace Barotrauma public void CorrectPosition(List positionBuffer, float deltaTime, out Vector2 newVelocity) { - newVelocity = Vector2.Zero; - if (positionBuffer.Count < 2) return; + Vector2 newPosition = SimPosition; + CorrectPosition(positionBuffer, deltaTime, out newVelocity, out newPosition); + + SetTransform(newPosition, Rotation); + } + + public void CorrectPosition(List positionBuffer, float deltaTime, out Vector2 newVelocity, out Vector2 newPosition) + { + newVelocity = Vector2.Zero; + newPosition = SimPosition; + + if (positionBuffer.Count < 2) return; + PosInfo prev = positionBuffer[0]; PosInfo next = positionBuffer[1]; - - Vector2 currPos = SimPosition; - + //interpolate the position of the collider from the first position in the buffer towards the second if (prev.Timestamp < next.Timestamp) { //if there are more than 2 positions in the buffer, //increase the interpolation speed to catch up with the server - float speedMultiplier = 1.0f + (float)Math.Pow((positionBuffer.Count - 2) / 2.0f, 2.0f); + float speedMultiplier = 0.9f + (float)Math.Pow((positionBuffer.Count - 2) / 5.0f, 2.0f); netInterpolationState += (deltaTime * speedMultiplier) / (next.Timestamp - prev.Timestamp); - currPos = Vector2.Lerp(prev.Position, next.Position, netInterpolationState); + newPosition = Vector2.Lerp(prev.Position, next.Position, netInterpolationState); //override the targetMovement to make the character play the walking/running animation newVelocity = (next.Position - prev.Position) / (next.Timestamp - prev.Timestamp); } else { - currPos = next.Position; + newPosition = next.Position; netInterpolationState = 1.0f; } - SetTransform(currPos, Rotation); - if (netInterpolationState >= 1.0f) { netInterpolationState = 0.0f;