Backported animcontroller-overhaul

This commit is contained in:
Regalis
2016-10-22 15:18:16 +03:00
parent bb9b2c6eb7
commit 641e579e92
39 changed files with 1169 additions and 995 deletions
@@ -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) { }
}
}
@@ -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);
}
}
@@ -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);
}
}
}
}
+374 -236
View File
@@ -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<LimbType, Limb> 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<LimbType, Limb>();
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<Vector2> 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;
}
/// <summary>
///
/// </summary>
/// <param name="pullFromCenter">if false, force is applied to the position of pullJoint</param>
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<Vector2> 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()