From 62c88be214176371723a7aa46381b1e5adb07b4f Mon Sep 17 00:00:00 2001 From: Regalis Date: Thu, 13 Oct 2016 23:19:48 +0300 Subject: [PATCH] Controlling humanoid movement with one capsule-shaped physics body that other limbs (attempt to) follow Broken and WIP --- Subsurface/Content/Characters/Human/human.xml | 4 + .../Characters/AI/IndoorsSteeringManager.cs | 4 +- .../Characters/Animation/AnimController.cs | 9 +- .../Animation/FishAnimController.cs | 20 +- .../Animation/HumanoidAnimController.cs | 316 +++++++++++------- .../Source/Characters/Animation/Ragdoll.cs | 133 +++++--- Subsurface/Source/Characters/Limb.cs | 3 +- Subsurface/Source/Map/SubmarineBody.cs | 1 - Subsurface/Source/Physics/PhysicsBody.cs | 11 +- 9 files changed, 306 insertions(+), 195 deletions(-) diff --git a/Subsurface/Content/Characters/Human/human.xml b/Subsurface/Content/Characters/Human/human.xml index 1fdb2ec3a..5af2274a9 100644 --- a/Subsurface/Content/Characters/Human/human.xml +++ b/Subsurface/Content/Characters/Human/human.xml @@ -76,6 +76,10 @@ + + + + diff --git a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs index 83c22d31b..1d68fbc30 100644 --- a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs @@ -154,9 +154,9 @@ namespace Barotrauma { x = 0.0f; } - else if (character.AnimController.LowestLimb != null && hull != null) + else if (hull != null) { - if (character.AnimController.LowestLimb.Position.Y < hull.Rect.Y - hull.Rect.Height + 10.0f) x = 0.0f; + if (character.AnimController.GetColliderBottom().Y < hull.Rect.Y - hull.Rect.Height + 10.0f) x = 0.0f; } character.AnimController.IgnorePlatforms = false; 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..9849bf52b 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -293,19 +293,21 @@ namespace Barotrauma Structure structure = fixture.Body.UserData as Structure; if (stairs == null && structure != null) { - if (LowestLimb.SimPosition.Y < structure.SimPosition.Y) - { - return -1; - } - else - { - stairs = structure; - } + //TODO: fix + //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; + //TODO: fix + //if (IgnorePlatforms || LowestLimb.Position.Y < platform.Rect.Y) return -1; break; case Physics.CollisionWall: break; diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index 116766d36..738cf18d8 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) { @@ -64,80 +64,135 @@ namespace Barotrauma if (character.IsDead) return; if (Frozen) return; - Vector2 colliderPos = GetLimb(LimbType.Torso).SimPosition; + if (collider == null) return; + + Vector2 colliderPos = GetColliderBottom(); //if (inWater) stairs = null; - if (onFloorTimer <= 0.0f && !SimplePhysicsEnabled) + //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; + // } + //} + bool onStairs = stairs != null; + stairs = null; + + var contacts = collider.body.FarseerBody.ContactList; + while (contacts != null && contacts.Contact != null) { - 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) => + if (contacts.Contact.Enabled && contacts.Contact.IsTouching) { - switch (fixture.CollisionCategories) + Vector2 normal; + FarseerPhysics.Common.FixedArray2 points; + + contacts.Contact.GetWorldManifold(out normal, out points); + + switch (contacts.Contact.FixtureA.CollisionCategories) { case Physics.CollisionStairs: - if (inWater && TargetMovement.Y < 0.5f) return -1; - Structure structure = fixture.Body.UserData as Structure; - if (stairs == null && structure != null) + Structure structure = contacts.Contact.FixtureA.Body.UserData as Structure; + if (structure != null && onStairs) { - if (LowestLimb.SimPosition.Y < structure.SimPosition.Y) - { - return -1; - } - else - { - stairs = structure; - } + 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; } + // 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; + //} - onGround = true; - if (fraction < closestFraction) + + if (points[0].Y < collider.SimPosition.Y) { - closestFraction = fraction; - Structure structure = fixture.Body.UserData as Structure; - if (structure != null) closestStructure = structure; + floorY = Math.Max(floorY, points[0].Y); + + onGround = true; + onFloorTimer = 0.1f; } - 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; - } - } + contacts = contacts.Next; + } //the ragdoll "stays on ground" for 50 millisecs after separation if (onFloorTimer <= 0.0f) @@ -152,7 +207,7 @@ namespace Barotrauma { onFloorTimer -= deltaTime; } - + //stun (= disable the animations) if the ragdoll receives a large enough impact if (strongestImpact > 0.0f) { @@ -160,9 +215,10 @@ namespace Barotrauma } strongestImpact = 0.0f; - + if (stunTimer > 0) { + collider.Disabled = true; stunTimer -= deltaTime; return; } @@ -179,11 +235,11 @@ 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; @@ -199,16 +255,17 @@ namespace Barotrauma else { - if (Anim != Animation.UsingConstruction) ResetPullJoints(); + if (Anim != Animation.UsingConstruction) ResetPullJoints(); } - + if (SimplePhysicsEnabled) { UpdateStandingSimple(); return; } + inWater = false; switch (Anim) { @@ -224,12 +281,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 @@ -268,19 +325,19 @@ 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; if (stairs != null) @@ -297,10 +354,10 @@ namespace Barotrauma { TargetMovement /= 1.0f; walkCycleSpeed *= 1.5f; - } + } } - Vector2 colliderPos = new Vector2(torso.SimPosition.X, floorY); + Vector2 colliderPos = GetColliderBottom(); if (Math.Abs(TargetMovement.X) > 1.0f) { @@ -313,24 +370,24 @@ 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 = MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, movementLerp); movement.Y = 0.0f; for (int i = 0; i < 2; i++) @@ -355,9 +412,9 @@ namespace Barotrauma } } - if (LowestLimb == null) return; + //if (LowestLimb == null) return; - if (!onGround || (LowestLimb.SimPosition.Y - floorY > 0.5f && stairs == null)) return; + if (onGround) collider.body.LinearVelocity = new Vector2(movement.X * 1.5f, collider.LinearVelocity.Y); //float? ceilingY = null; //if (Submarine.PickBody(head.SimPosition, head.SimPosition + Vector2.UnitY, null, Physics.CollisionWall)!=null) @@ -366,7 +423,7 @@ namespace Barotrauma // if (ceilingY - floorY < HeadPosition) Crouching = true; //} - + getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f); torso.pullJoint.Enabled = true; @@ -375,8 +432,6 @@ 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.Y, colliderPos.Y + TorsoPosition - Math.Abs(walkPosX * 0.05f), getUpSpeed * 2.0f)); @@ -390,17 +445,31 @@ namespace Barotrauma } else { + if (!onGround) movement = Vector2.Zero; + torso.pullJoint.WorldAnchorB = MathUtils.SmoothStep(torso.SimPosition, new Vector2(footMid + movement.X * 0.3f, 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) ? 1.0f : 0.3f), colliderPos.Y + HeadPosition), getUpSpeed * 1.2f); waist.pullJoint.WorldAnchorB = waist.SimPosition + movement * 0.1f; } + if (!onGround) + { + Vector2 move = torso.pullJoint.WorldAnchorB - torso.SimPosition; + + foreach (Limb limb in Limbs) + { + if (limb == collider) continue; + MoveLimb(limb, limb.SimPosition+move, 15.0f, true); + } + + return; + } //moving horizontally if (TargetMovement.X != 0.0f) @@ -462,7 +531,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) @@ -507,7 +576,7 @@ namespace Barotrauma var leftArm = GetLimb(LimbType.LeftArm); leftArm.body.SmoothRotate(0.0f, 20.0f); } - } + } } @@ -521,17 +590,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); } @@ -596,7 +666,7 @@ namespace Barotrauma if (TargetMovement == Vector2.Zero) return; - movement = MathUtils.SmoothStep(movement, TargetMovement*swimSpeed, 0.3f); + movement = MathUtils.SmoothStep(movement, TargetMovement * swimSpeed, 0.3f); //dont try to move upwards if head is already out of water if (surfaceLimiter > 1.0f && TargetMovement.Y > 0.0f) @@ -747,7 +817,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; } @@ -759,7 +829,7 @@ namespace Barotrauma 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); - + Vector2 handPos = new Vector2( ladderSimPos.X, @@ -807,12 +877,12 @@ namespace Barotrauma 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); + torso.body.ApplyForce((climbForce * 40.0f + subSpeed * 50.0f) * torso.Mass); head.body.SmoothRotate(0.0f); if (!character.SelectedConstruction.Prefab.Triggers.Any()) @@ -862,15 +932,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); @@ -880,7 +950,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); } @@ -942,15 +1012,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; } @@ -977,7 +1047,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); } } @@ -990,7 +1060,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; } @@ -1085,7 +1155,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); @@ -1136,7 +1206,7 @@ namespace Barotrauma Vector2 targetMovement = character.GetTargetMovement(); - Vector2 currPosition = prevPosition + targetMovement * timePassed/500.0f; + Vector2 currPosition = prevPosition + targetMovement * timePassed / 500.0f; return currPosition; } @@ -1200,7 +1270,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); @@ -1219,6 +1289,6 @@ namespace Barotrauma limb.body.SetTransform(limb.body.SimPosition, angle); } } - + } } diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index c11270df7..874163913 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -57,18 +57,15 @@ namespace Barotrauma public bool onGround; private bool ignorePlatforms; - private Limb refLimb; + protected Limb refLimb; protected Structure stairs; protected Direction dir; - //private byte ID; - - public Limb LowestLimb - { - get { return lowestLimb; } - } + public Direction TargetDir; + + protected Limb collider; public Limb RefLimb { @@ -278,7 +275,13 @@ namespace Barotrauma limb.sprite.Depth = startDepth + limb.sprite.Depth * 0.0001f; } - FindLowestLimb(); + + collider = GetLimb(LimbType.Controller); + if (collider == null) return; + + collider.body.FarseerBody.FixedRotation = true; + collider.pullJoint = null; + refLimb = collider; } public void AddJoint(XElement subElement, float scale = 1.0f) @@ -345,57 +348,72 @@ 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; } - 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); - - if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY - 10.0f) return false; - - - - if (targetMovement.Y < 0.5f) + float stairBottomPos = ConvertUnits.ToSimUnits(structure.Rect.Y - structure.Rect.Height + 10); + if (colliderBottom.Y < stairBottomPos && targetMovement.Y < 0.5f) { - if (inWater || lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + 50.0f) - { - stairs = null; - return false; - } + stairs = null; + return false; } + + if (targetMovement.Y >= 0.0f && colliderBottom.Y > ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y * 8.0f)) + { + stairs = null; + return false; + } + + stairs = structure; + + //float stairPosY = structure.StairDirection == Direction.Right ? + // lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X); + - //if (targetMovement.Y >= 0.0f && lowestLimb.SimPosition.Y > ConvertUnits.ToSimUnits(structure.Rect.Y - Submarine.GridSize.Y * 8.0f)) + //if (lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + stairPosY - 10.0f) return false; + + + + //if (targetMovement.Y < 0.5f) //{ - // //stairs = null; - // //return false; + // if (inWater || lowestLimb.Position.Y < structure.Rect.Y - structure.Rect.Height + 50.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; - } - } - else - { - 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; + // } + + // } + // else + // { + // stairs = null; + // return false; + // } + //} } @@ -717,7 +735,7 @@ namespace Barotrauma Vector2 flowForce = Vector2.Zero; - FindLowestLimb(); + //FindLowestLimb(); FindHull(); @@ -1010,19 +1028,24 @@ namespace Barotrauma limbDictionary.TryGetValue(limbType, out limb); return limb; } - - public void FindLowestLimb() + + + public Vector2 GetColliderBottom() { - //find the lowest limb - lowestLimb = null; - foreach (Limb limb in Limbs) - { - if (lowestLimb == null) - lowestLimb = limb; - else if (limb.SimPosition.Y < lowestLimb.SimPosition.Y) - lowestLimb = limb; - } + return collider == null ? Vector2.Zero : collider.SimPosition - Vector2.UnitY * (collider.body.height / 2 + collider.body.radius); } + + //public void FindLowestLimb() + //{ //find the lowest limb + // lowestLimb = null; + // foreach (Limb limb in Limbs) + // { + // if (lowestLimb == null) + // lowestLimb = limb; + // else if (limb.SimPosition.Y < lowestLimb.SimPosition.Y) + // lowestLimb = limb; + // } + //} public void Remove() { diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index dc5e5ada9..39cf82e8a 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -16,7 +16,8 @@ namespace Barotrauma public enum LimbType { None, LeftHand, RightHand, LeftArm, RightArm, - LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist + LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist, + Controller }; class Limb diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 8451a12ec..c09393184 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -556,7 +556,6 @@ namespace Barotrauma foreach (Limb limb in c.AnimController.Limbs) { - if (c.AnimController.LowestLimb == limb) continue; limb.body.ApplyLinearImpulse(limb.Mass * impulse); } } diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index 31fefd980..5b4e3b2ad 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -383,9 +383,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); + } } public void Remove()