Instead of sending over mouse position as two floats (8 bytes total), the game will send the aim angle represented as a short (0 to 65535, so it's fairly precise) and the selected item ID (up to 4 bytes total, 2 bytes if it's only one of the inputs). The problem with IsKeyHit is that it checked when the player started a key press, when it should've been checking for the key being released.
1176 lines
44 KiB
C#
1176 lines
44 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Xml.Linq;
|
|
using FarseerPhysics;
|
|
using Microsoft.Xna.Framework;
|
|
using Barotrauma.Items.Components;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
class HumanoidAnimController : AnimController
|
|
{
|
|
public bool Crouching;
|
|
|
|
private bool aiming;
|
|
|
|
private float walkAnimSpeed;
|
|
|
|
private float movementLerp;
|
|
|
|
private float thighTorque;
|
|
|
|
private float cprAnimState;
|
|
|
|
private float inWaterTimer;
|
|
private bool swimming;
|
|
|
|
protected override float TorsoPosition
|
|
{
|
|
get
|
|
{
|
|
return Crouching ? base.TorsoPosition - base.HeadPosition * 0.3f : base.TorsoPosition;
|
|
}
|
|
}
|
|
|
|
protected override float TorsoAngle
|
|
{
|
|
get
|
|
{
|
|
return Crouching ? base.TorsoAngle + 0.5f : base.TorsoAngle;
|
|
}
|
|
}
|
|
|
|
public HumanoidAnimController(Character character, XElement element)
|
|
: base(character, element)
|
|
{
|
|
walkAnimSpeed = ToolBox.GetAttributeFloat(element, "walkanimspeed", 4.0f);
|
|
walkAnimSpeed = MathHelper.ToRadians(walkAnimSpeed);
|
|
|
|
movementLerp = ToolBox.GetAttributeFloat(element, "movementlerp", 0.4f);
|
|
|
|
thighTorque = ToolBox.GetAttributeFloat(element, "thightorque", -5.0f);
|
|
}
|
|
|
|
public override void UpdateAnim(float deltaTime)
|
|
{
|
|
if (Frozen) return;
|
|
|
|
levitatingCollider = true;
|
|
ColliderIndex = Crouching ? 1 : 0;
|
|
if (!Crouching && ColliderIndex == 1) Crouching = true;
|
|
|
|
if (!character.AllowInput)
|
|
{
|
|
levitatingCollider = false;
|
|
Collider.FarseerBody.FixedRotation = false;
|
|
|
|
/*if (character.IsRemotePlayer)
|
|
{
|
|
MainLimb.pullJoint.WorldAnchorB = Collider.SimPosition;
|
|
MainLimb.pullJoint.Enabled = true;
|
|
}
|
|
else
|
|
{*/
|
|
Collider.LinearVelocity = (GetLimb(LimbType.Waist).SimPosition - Collider.SimPosition) * 20.0f;
|
|
Collider.SmoothRotate(GetLimb(LimbType.Torso).Rotation);
|
|
//}
|
|
|
|
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;
|
|
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)),
|
|
Collider.Rotation);
|
|
|
|
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) * 10.0f;
|
|
Collider.FarseerBody.FixedRotation = false;
|
|
}
|
|
else
|
|
{
|
|
Collider.FarseerBody.FixedRotation = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Collider.FarseerBody.Enabled = false;
|
|
}
|
|
|
|
if (character.LockHands)
|
|
{
|
|
var leftHand = GetLimb(LimbType.LeftHand);
|
|
var rightHand = GetLimb(LimbType.RightHand);
|
|
|
|
var waist = GetLimb(LimbType.Waist);
|
|
|
|
rightHand.Disabled = true;
|
|
leftHand.Disabled = true;
|
|
|
|
|
|
Vector2 midPos = waist.SimPosition;
|
|
|
|
Matrix torsoTransform = Matrix.CreateRotationZ(waist.Rotation);
|
|
|
|
|
|
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);
|
|
}
|
|
else
|
|
{
|
|
|
|
if (Anim != Animation.UsingConstruction) ResetPullJoints();
|
|
|
|
}
|
|
|
|
if (SimplePhysicsEnabled)
|
|
{
|
|
UpdateStandingSimple();
|
|
return;
|
|
}
|
|
|
|
|
|
switch (Anim)
|
|
{
|
|
case Animation.Climbing:
|
|
levitatingCollider = false;
|
|
UpdateClimbing();
|
|
break;
|
|
case Animation.CPR:
|
|
UpdateCPR(deltaTime);
|
|
break;
|
|
case Animation.UsingConstruction:
|
|
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);
|
|
if (inWaterTimer >= 1.0f) swimming = true;
|
|
}
|
|
else
|
|
{
|
|
inWaterTimer = Math.Min(inWaterTimer - deltaTime, 0.5f);
|
|
if (inWaterTimer <= 0.0f) swimming = false;
|
|
}
|
|
|
|
if (swimming)
|
|
{
|
|
UpdateSwimming();
|
|
}
|
|
else
|
|
{
|
|
UpdateStanding();
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (TargetDir != dir) Flip();
|
|
|
|
foreach (Limb limb in Limbs)
|
|
{
|
|
limb.Disabled = false;
|
|
}
|
|
|
|
aiming = false;
|
|
if (character.IsRemotePlayer && GameMain.Server == null) Collider.LinearVelocity = Vector2.Zero;
|
|
}
|
|
|
|
|
|
|
|
void UpdateStanding()
|
|
{
|
|
Vector2 handPos;
|
|
|
|
//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 waist = GetLimb(LimbType.Waist);
|
|
|
|
Limb leftHand = GetLimb(LimbType.LeftHand);
|
|
Limb rightHand = GetLimb(LimbType.RightHand);
|
|
|
|
Limb leftLeg = GetLimb(LimbType.LeftLeg);
|
|
Limb rightLeg = GetLimb(LimbType.RightLeg);
|
|
|
|
float getUpSpeed = 0.3f;
|
|
float walkCycleSpeed = movement.X * walkAnimSpeed;
|
|
if (stairs != null)
|
|
{
|
|
TargetMovement = new Vector2(MathHelper.Clamp(TargetMovement.X, -1.5f, 1.5f), TargetMovement.Y);
|
|
|
|
/*if ((TargetMovement.X > 0.0f && stairs.StairDirection == Direction.Right) ||
|
|
TargetMovement.X < 0.0f && stairs.StairDirection == Direction.Left)
|
|
{
|
|
TargetMovement *= 1.7f;
|
|
//walkCycleSpeed *= 1.0f;
|
|
}*/
|
|
}
|
|
|
|
Vector2 colliderPos = GetColliderBottom();
|
|
if (Math.Abs(TargetMovement.X) > 1.0f)
|
|
{
|
|
float slowdownAmount = 0.0f;
|
|
if (currentHull != null)
|
|
{
|
|
//full slowdown (1.5f) when water is up to the torso
|
|
surfaceY = ConvertUnits.ToSimUnits(currentHull.Surface);
|
|
slowdownAmount = MathHelper.Clamp((surfaceY - colliderPos.Y) / torsoPosition, 0.0f, 1.0f) * 1.5f;
|
|
}
|
|
|
|
float maxSpeed = Math.Max(TargetMovement.Length() - slowdownAmount, 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);
|
|
|
|
Vector2 stepSize = new Vector2(
|
|
this.stepSize.X * walkPosX * runningModifier,
|
|
this.stepSize.Y * walkPosY * runningModifier * runningModifier);
|
|
|
|
if (Crouching) stepSize *= 0.5f;
|
|
|
|
float footMid = colliderPos.X;// (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f;
|
|
|
|
movement = overrideTargetMovement == Vector2.Zero ?
|
|
MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, movementLerp) :
|
|
overrideTargetMovement;
|
|
|
|
if (Math.Abs(movement.X) < 0.005f)
|
|
{
|
|
movement.X = 0.0f;
|
|
}
|
|
|
|
movement.Y = 0.0f;
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
Limb leg = GetLimb((i == 0) ? LimbType.LeftThigh : LimbType.RightThigh);// : leftLeg;
|
|
|
|
float shortestAngle = leg.Rotation - torso.Rotation;
|
|
|
|
if (Math.Abs(shortestAngle) < 2.5f) continue;
|
|
|
|
if (Math.Abs(shortestAngle) > 5.0f)
|
|
{
|
|
TargetDir = TargetDir == Direction.Right ? Direction.Left : Direction.Right;
|
|
}
|
|
else
|
|
{
|
|
|
|
leg.body.ApplyTorque(shortestAngle * 10.0f);
|
|
|
|
leg = GetLimb((i == 0) ? LimbType.LeftLeg : LimbType.RightLeg);
|
|
leg.body.ApplyTorque(-shortestAngle * 10.0f);
|
|
}
|
|
}
|
|
|
|
if (onGround && (!character.IsRemotePlayer || GameMain.Server != null))
|
|
{
|
|
//move slower if collider isn't upright
|
|
float rotationFactor = (float)Math.Abs(Math.Cos(Collider.Rotation));
|
|
|
|
Collider.LinearVelocity = new Vector2(
|
|
movement.X * rotationFactor,
|
|
Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y);
|
|
}
|
|
|
|
getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f);
|
|
|
|
torso.pullJoint.Enabled = true;
|
|
head.pullJoint.Enabled = true;
|
|
waist.pullJoint.Enabled = true;
|
|
|
|
if (stairs != null)
|
|
{
|
|
torso.pullJoint.WorldAnchorB = new Vector2(
|
|
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 ? 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.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) ? 0.6f : 0.2f), colliderPos.Y + HeadPosition), getUpSpeed * 1.2f);
|
|
|
|
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)
|
|
{
|
|
//progress the walking animation
|
|
walkPos -= (walkCycleSpeed / runningModifier) * 0.8f;
|
|
|
|
MoveLimb(leftFoot,
|
|
colliderPos + new Vector2(
|
|
stepSize.X,
|
|
(stepSize.Y > 0.0f) ? stepSize.Y : -0.15f),
|
|
15.0f, true);
|
|
|
|
MoveLimb(rightFoot,
|
|
colliderPos + new Vector2(
|
|
-stepSize.X,
|
|
(-stepSize.Y > 0.0f) ? -stepSize.Y : -0.15f),
|
|
15.0f, true);
|
|
|
|
leftFoot.body.SmoothRotate(leftLeg.body.Rotation + MathHelper.PiOver2 * Dir * 1.6f, 20.0f * runningModifier);
|
|
rightFoot.body.SmoothRotate(rightLeg.body.Rotation + MathHelper.PiOver2 * Dir * 1.6f, 20.0f * runningModifier);
|
|
|
|
if (runningModifier > 1.0f)
|
|
{
|
|
if (walkPosY > 0.0f)
|
|
{
|
|
GetLimb(LimbType.LeftThigh).body.ApplyTorque(-walkPosY * Dir * Math.Abs(movement.X) * thighTorque);
|
|
}
|
|
else
|
|
{
|
|
GetLimb(LimbType.RightThigh).body.ApplyTorque(walkPosY * Dir * Math.Abs(movement.X) * thighTorque);
|
|
}
|
|
}
|
|
|
|
if (legTorque > 0.0f)
|
|
{
|
|
if (Math.Sign(walkPosX) != Math.Sign(movement.X))
|
|
{
|
|
GetLimb(LimbType.LeftLeg).body.ApplyTorque(-walkPosY * Dir * Math.Abs(movement.X) * legTorque / runningModifier);
|
|
}
|
|
else
|
|
{
|
|
GetLimb(LimbType.RightLeg).body.ApplyTorque(walkPosY * Dir * Math.Abs(movement.X) * legTorque / runningModifier);
|
|
}
|
|
}
|
|
|
|
//calculate the positions of hands
|
|
handPos = torso.SimPosition;
|
|
handPos.X = -walkPosX * 0.4f;
|
|
|
|
float lowerY = -1.0f + (runningModifier - 1.0f) * 0.8f;
|
|
|
|
handPos.Y = lowerY + (float)(Math.Abs(Math.Sin(walkPos - Math.PI * 1.5f) * 0.15 * runningModifier));
|
|
|
|
Vector2 posAddition = new Vector2(-movement.X * 0.015f * runningModifier, 0.0f);
|
|
|
|
if (!rightHand.Disabled)
|
|
{
|
|
HandIK(rightHand, torso.SimPosition + posAddition +
|
|
new Vector2(
|
|
-handPos.X,
|
|
(Math.Sign(walkPosX) == Math.Sign(Dir)) ? handPos.Y : lowerY), 0.7f * runningModifier);
|
|
}
|
|
|
|
if (!leftHand.Disabled)
|
|
{
|
|
HandIK(leftHand, torso.SimPosition + posAddition +
|
|
new Vector2(
|
|
handPos.X,
|
|
(Math.Sign(walkPosX) == Math.Sign(-Dir)) ? handPos.Y : lowerY), 0.7f * runningModifier);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//float movementFactor = (movement.X / 4.0f) * movement.X * Math.Sign(movement.X);
|
|
|
|
for (int i = -1; i < 2; i += 2)
|
|
{
|
|
Vector2 footPos = colliderPos;
|
|
|
|
if (Crouching)
|
|
{
|
|
footPos = new Vector2(
|
|
waist.SimPosition.X + Math.Sign(stepSize.X * i) * Dir * 0.3f,
|
|
colliderPos.Y - 0.1f);
|
|
}
|
|
else
|
|
{
|
|
footPos = new Vector2(GetCenterOfMass().X + stepSize.X * i * 0.2f, colliderPos.Y - 0.1f);
|
|
}
|
|
|
|
|
|
var foot = i == -1 ? rightFoot : leftFoot;
|
|
|
|
MoveLimb(foot, footPos, Math.Abs(foot.SimPosition.X - footPos.X) * 100.0f, true);
|
|
}
|
|
|
|
leftFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 50.0f);
|
|
rightFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 50.0f);
|
|
|
|
if (!rightHand.Disabled)
|
|
{
|
|
rightHand.body.SmoothRotate(0.0f, 5.0f);
|
|
|
|
var rightArm = GetLimb(LimbType.RightArm);
|
|
rightArm.body.SmoothRotate(0.0f, 20.0f);
|
|
}
|
|
|
|
if (!leftHand.Disabled)
|
|
{
|
|
leftHand.body.SmoothRotate(0.0f, 5.0f);
|
|
|
|
var leftArm = GetLimb(LimbType.LeftArm);
|
|
leftArm.body.SmoothRotate(0.0f, 20.0f);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateStandingSimple()
|
|
{
|
|
movement = MathUtils.SmoothStep(movement, TargetMovement, movementLerp);
|
|
|
|
if (inWater && movement.LengthSquared() > 0.00001f)
|
|
{
|
|
movement = Vector2.Normalize(movement);
|
|
}
|
|
|
|
if (Math.Abs(movement.X)<0.005f)
|
|
{
|
|
movement.X = 0.0f;
|
|
}
|
|
}
|
|
|
|
private void ClimbOverObstacles()
|
|
{
|
|
if (Collider.FarseerBody.ContactList == null || Math.Abs(movement.X) < 0.01f) return;
|
|
|
|
//check if the collider is touching a suitable obstacle to climb over
|
|
Vector2? handle = null;
|
|
FarseerPhysics.Dynamics.Contacts.ContactEdge ce = Collider.FarseerBody.ContactList;
|
|
while (ce != null && ce.Contact != null)
|
|
{
|
|
if (ce.Contact.Enabled && ce.Contact.IsTouching && ce.Contact.FixtureA.CollisionCategories.HasFlag(Physics.CollisionWall))
|
|
{
|
|
Vector2 contactNormal;
|
|
FarseerPhysics.Common.FixedArray2<Vector2> contactPos;
|
|
ce.Contact.GetWorldManifold(out contactNormal, out contactPos);
|
|
|
|
//only climb if moving towards the obstacle
|
|
if (Math.Sign(contactPos[0].X - Collider.SimPosition.X) == Math.Sign(movement.X) &&
|
|
(handle == null || contactPos[0].Y > ((Vector2)handle).Y))
|
|
{
|
|
handle = contactPos[0];
|
|
}
|
|
}
|
|
|
|
ce = ce.Next;
|
|
}
|
|
|
|
if (handle == null) return;
|
|
|
|
float colliderBottomY = GetColliderBottom().Y;
|
|
|
|
//the contact point should be higher than the bottom of the collider
|
|
if (((Vector2)handle).Y < colliderBottomY + 0.01f ||
|
|
((Vector2)handle).Y > Collider.SimPosition.Y) return;
|
|
|
|
//find the height of the floor below the torso
|
|
//(if moving towards towards an obstacle that's low enough to climb over, the torso should be above it)
|
|
float obstacleY = GetFloorY(GetLimb(LimbType.Torso));
|
|
|
|
if (obstacleY > colliderBottomY)
|
|
{
|
|
//higher vertical velocity for taller obstacles
|
|
Collider.LinearVelocity += Vector2.UnitY * (((Vector2)handle).Y - colliderBottomY + 0.01f) * 50;
|
|
onGround = true;
|
|
}
|
|
}
|
|
|
|
void UpdateSwimming()
|
|
{
|
|
IgnorePlatforms = true;
|
|
|
|
Vector2 footPos, handPos;
|
|
|
|
float surfaceLimiter = 1.0f;
|
|
|
|
Limb head = GetLimb(LimbType.Head);
|
|
Limb torso = GetLimb(LimbType.Torso);
|
|
|
|
if (currentHull != null && (currentHull.Rect.Y - currentHull.Surface > 50.0f))
|
|
{
|
|
surfaceLimiter = (ConvertUnits.ToDisplayUnits(Collider.SimPosition.Y + 0.4f) - surfaceY);
|
|
surfaceLimiter = Math.Max(1.0f, surfaceLimiter);
|
|
if (surfaceLimiter > 50.0f) return;
|
|
}
|
|
|
|
Limb leftHand = GetLimb(LimbType.LeftHand);
|
|
Limb rightHand = GetLimb(LimbType.RightHand);
|
|
|
|
Limb leftFoot = GetLimb(LimbType.LeftFoot);
|
|
Limb rightFoot = GetLimb(LimbType.RightFoot);
|
|
|
|
float rotation = MathHelper.WrapAngle(Collider.Rotation);
|
|
rotation = MathHelper.ToDegrees(rotation);
|
|
if (rotation < 0.0f) rotation += 360;
|
|
|
|
if (!character.IsRemotePlayer && !aiming && Anim != Animation.UsingConstruction)
|
|
{
|
|
if (rotation > 20 && rotation < 170)
|
|
TargetDir = Direction.Left;
|
|
else if (rotation > 190 && rotation < 340)
|
|
TargetDir = Direction.Right;
|
|
}
|
|
|
|
float targetSpeed = TargetMovement.Length();
|
|
if (targetSpeed > 0.0f) TargetMovement /= targetSpeed;
|
|
|
|
if (targetSpeed > 0.1f)
|
|
{
|
|
if (!aiming)
|
|
{
|
|
float newRotation = MathUtils.VectorToAngle(TargetMovement) - MathHelper.PiOver2;
|
|
Collider.SmoothRotate(newRotation, 5.0f);
|
|
//torso.body.SmoothRotate(newRotation);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (aiming)
|
|
{
|
|
Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
|
|
Vector2 diff = (mousePos - torso.SimPosition) * Dir;
|
|
|
|
TargetMovement = new Vector2(0.0f, -0.1f);
|
|
|
|
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, 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)
|
|
{
|
|
//pull head above water
|
|
head.body.SmoothRotate(0.0f, 5.0f);
|
|
|
|
walkPos += 0.05f;
|
|
}
|
|
else
|
|
{
|
|
TargetMovement = new Vector2(
|
|
(float)Math.Sqrt(targetSpeed * targetSpeed - TargetMovement.Y * TargetMovement.Y)
|
|
* Math.Sign(TargetMovement.X),
|
|
Math.Max(TargetMovement.Y, TargetMovement.Y * 0.2f));
|
|
|
|
//turn head above the water
|
|
head.body.ApplyTorque(Dir);
|
|
}
|
|
|
|
movement.Y = movement.Y - (surfaceLimiter - 1.0f) * 0.01f;
|
|
}
|
|
|
|
if (!character.IsRemotePlayer || GameMain.Server != null)
|
|
{
|
|
Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement * swimSpeed, movementLerp);
|
|
}
|
|
|
|
walkPos += movement.Length() * 0.15f;
|
|
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);
|
|
|
|
rightThigh.body.SmoothRotate(torso.Rotation + (float)Math.Sin(walkPos) * 0.3f, 2.0f);
|
|
leftThigh.body.SmoothRotate(torso.Rotation - (float)Math.Sin(walkPos) * 0.3f, 2.0f);
|
|
|
|
Vector2 transformedFootPos = new Vector2((float)Math.Sin(walkPos) * 0.5f, 0.0f);
|
|
transformedFootPos = Vector2.Transform(
|
|
transformedFootPos,
|
|
Matrix.CreateRotationZ(Collider.Rotation));
|
|
|
|
MoveLimb(rightFoot, footPos - transformedFootPos, 1.0f);
|
|
MoveLimb(leftFoot, footPos + transformedFootPos, 1.0f);
|
|
|
|
handPos = (torso.SimPosition + head.SimPosition) / 2.0f;
|
|
|
|
//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.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.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.25f), 1.5f);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
handPos += head.LinearVelocity * 0.1f;
|
|
|
|
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);
|
|
|
|
Matrix rotationMatrix = Matrix.CreateRotationZ(torso.Rotation);
|
|
|
|
if (!rightHand.Disabled)
|
|
{
|
|
Vector2 rightHandPos = new Vector2(-handPosX, -handPosY);
|
|
rightHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, rightHandPos.X) : Math.Min(-0.3f, rightHandPos.X);
|
|
rightHandPos = Vector2.Transform(rightHandPos, rotationMatrix);
|
|
|
|
HandIK(rightHand, handPos + rightHandPos, 0.5f);
|
|
}
|
|
|
|
if (!leftHand.Disabled)
|
|
{
|
|
Vector2 leftHandPos = new Vector2(handPosX, handPosY);
|
|
leftHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, leftHandPos.X) : Math.Min(-0.3f, leftHandPos.X);
|
|
leftHandPos = Vector2.Transform(leftHandPos, rotationMatrix);
|
|
|
|
HandIK(leftHand, handPos + leftHandPos, 0.5f);
|
|
}
|
|
}
|
|
|
|
void UpdateClimbing()
|
|
{
|
|
if (character.SelectedConstruction == null || character.SelectedConstruction.GetComponent<Ladder>() == null)
|
|
{
|
|
Anim = Animation.None;
|
|
return;
|
|
}
|
|
|
|
onGround = false;
|
|
IgnorePlatforms = true;
|
|
|
|
Vector2 tempTargetMovement = TargetMovement;
|
|
|
|
tempTargetMovement.Y = Math.Min(tempTargetMovement.Y, 1.0f);
|
|
|
|
movement = MathUtils.SmoothStep(movement, tempTargetMovement, 0.3f);
|
|
|
|
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 leftHand = GetLimb(LimbType.LeftHand);
|
|
Limb rightHand = GetLimb(LimbType.RightHand);
|
|
|
|
Vector2 ladderSimPos = ConvertUnits.ToSimUnits(
|
|
character.SelectedConstruction.Rect.X + character.SelectedConstruction.Rect.Width / 2.0f,
|
|
character.SelectedConstruction.Rect.Y);
|
|
|
|
float stepHeight = ConvertUnits.ToSimUnits(30.0f);
|
|
|
|
if (currentHull == null && character.SelectedConstruction.Submarine != null)
|
|
{
|
|
ladderSimPos += character.SelectedConstruction.Submarine.SimPosition;
|
|
}
|
|
else if (currentHull.Submarine != null && currentHull.Submarine != character.SelectedConstruction.Submarine)
|
|
{
|
|
ladderSimPos += character.SelectedConstruction.Submarine.SimPosition - currentHull.Submarine.SimPosition;
|
|
}
|
|
|
|
MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, Collider.SimPosition.Y + 0.9f - colliderHeightFromFloor), 10.5f);
|
|
MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, Collider.SimPosition.Y + 0.7f - colliderHeightFromFloor), 10.5f);
|
|
MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, Collider.SimPosition.Y + 0.6f - colliderHeightFromFloor), 10.5f);
|
|
|
|
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,
|
|
Collider.SimPosition.Y + 0.8f + movement.Y * 0.1f - ladderSimPos.Y);
|
|
|
|
handPos.Y = Math.Min(-0.2f, handPos.Y) - colliderHeightFromFloor;
|
|
|
|
MoveLimb(leftHand,
|
|
new Vector2(handPos.X,
|
|
(slide ? handPos.Y : MathUtils.Round(handPos.Y - stepHeight, stepHeight * 2.0f) + stepHeight) + ladderSimPos.Y),
|
|
5.2f);
|
|
|
|
MoveLimb(rightHand,
|
|
new Vector2(handPos.X,
|
|
(slide ? handPos.Y : MathUtils.Round(handPos.Y, stepHeight * 2.0f)) + ladderSimPos.Y),
|
|
5.2f);
|
|
|
|
leftHand.body.ApplyTorque(Dir * 2.0f);
|
|
rightHand.body.ApplyTorque(Dir * 2.0f);
|
|
|
|
Vector2 footPos = new Vector2(
|
|
handPos.X - Dir * 0.05f,
|
|
Collider.SimPosition.Y + 0.9f - colliderHeightFromFloor - stepHeight * 2.7f - ladderSimPos.Y - 0.7f);
|
|
|
|
//if (movement.Y < 0) footPos.Y += 0.05f;
|
|
|
|
MoveLimb(leftFoot,
|
|
new Vector2(footPos.X,
|
|
(slide ? footPos.Y : MathUtils.Round(footPos.Y + stepHeight, stepHeight * 2.0f) - stepHeight) + ladderSimPos.Y),
|
|
15.5f, true);
|
|
|
|
MoveLimb(rightFoot,
|
|
new Vector2(footPos.X,
|
|
(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
|
|
Limb leftLeg = GetLimb(LimbType.LeftLeg);
|
|
Limb rightLeg = GetLimb(LimbType.RightLeg);
|
|
|
|
leftLeg.body.ApplyTorque(Dir * -8.0f);
|
|
rightLeg.body.ApplyTorque(Dir * -8.0f);
|
|
|
|
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.Zero : character.SelectedConstruction.Submarine.Velocity;
|
|
|
|
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;
|
|
return;
|
|
}
|
|
|
|
Rectangle trigger = character.SelectedConstruction.Prefab.Triggers.FirstOrDefault();
|
|
trigger = character.SelectedConstruction.TransformTrigger(trigger);
|
|
|
|
bool notClimbing = false;
|
|
if (character.IsRemotePlayer && GameMain.Server == null)
|
|
{
|
|
notClimbing = character.IsKeyDown(InputType.Left) || character.IsKeyDown(InputType.Right);
|
|
}
|
|
else
|
|
{
|
|
notClimbing = Math.Abs(targetMovement.X) > 0.05f ||
|
|
(TargetMovement.Y < 0.0f && ConvertUnits.ToSimUnits(trigger.Height) + handPos.Y < HeadPosition) ||
|
|
(TargetMovement.Y > 0.0f && handPos.Y > 0.1f);
|
|
}
|
|
|
|
if (notClimbing)
|
|
{
|
|
Anim = Animation.None;
|
|
character.SelectedConstruction = null;
|
|
IgnorePlatforms = false;
|
|
}
|
|
|
|
}
|
|
|
|
private void UpdateCPR(float deltaTime)
|
|
{
|
|
if (character.SelectedCharacter == null)
|
|
{
|
|
Anim = Animation.None;
|
|
return;
|
|
}
|
|
|
|
Crouching = true;
|
|
|
|
Vector2 diff = character.SelectedCharacter.SimPosition - character.SimPosition;
|
|
var targetHead = character.SelectedCharacter.AnimController.GetLimb(LimbType.Head);
|
|
|
|
Vector2 headDiff = targetHead == null ? diff : targetHead.SimPosition - character.SimPosition;
|
|
|
|
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;
|
|
|
|
Grab(handPos, handPos);
|
|
|
|
float yPos = (float)Math.Sin(cprAnimState) * 0.1f;
|
|
cprAnimState += deltaTime * 8.0f;
|
|
|
|
var head = GetLimb(LimbType.Head);
|
|
head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos);
|
|
head.pullJoint.Enabled = true;
|
|
}
|
|
public override void DragCharacter(Character target, LimbType rightHandTarget = LimbType.RightHand, LimbType leftHandTarget = LimbType.LeftHand)
|
|
{
|
|
if (target == null) return;
|
|
|
|
Limb leftHand = GetLimb(LimbType.LeftHand);
|
|
Limb rightHand = GetLimb(LimbType.RightHand);
|
|
|
|
//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)
|
|
{
|
|
targetLimb.pullJoint.Enabled = false;
|
|
}
|
|
else
|
|
{
|
|
Vector2 diff = ConvertUnits.ToSimUnits(targetLimb.WorldPosition - pullLimb.WorldPosition);
|
|
|
|
pullLimb.pullJoint.Enabled = true;
|
|
pullLimb.pullJoint.WorldAnchorB = pullLimb.SimPosition + diff;
|
|
pullLimb.pullJoint.MaxForce = 10000.0f;
|
|
|
|
targetLimb.pullJoint.Enabled = true;
|
|
targetLimb.pullJoint.WorldAnchorB = targetLimb.SimPosition - diff;
|
|
targetLimb.pullJoint.MaxForce = 10000.0f;
|
|
|
|
target.AnimController.movement -= diff;
|
|
}
|
|
}
|
|
|
|
float dist = Vector2.Distance(target.SimPosition, Collider.SimPosition);
|
|
|
|
//limit movement if moving away from the target
|
|
if (Vector2.Dot(target.SimPosition - Collider.SimPosition, targetMovement)<0)
|
|
{
|
|
targetMovement *= MathHelper.Clamp(2.0f - dist, 0.0f, 1.0f);
|
|
}
|
|
|
|
target.AnimController.IgnorePlatforms = IgnorePlatforms;
|
|
|
|
if (!target.AllowInput)
|
|
{
|
|
target.AnimController.TargetMovement = TargetMovement;
|
|
}
|
|
else if (target is AICharacter)
|
|
{
|
|
target.AnimController.TargetMovement = Vector2.Lerp(
|
|
target.AnimController.TargetMovement,
|
|
(character.SimPosition + Vector2.UnitX * Dir) - target.SimPosition, 0.5f);
|
|
}
|
|
}
|
|
|
|
public void Grab(Vector2 rightHandPos, Vector2 leftHandPos)
|
|
{
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
Limb pullLimb = (i == 0) ? GetLimb(LimbType.LeftHand) : GetLimb(LimbType.RightHand);
|
|
|
|
pullLimb.Disabled = true;
|
|
|
|
pullLimb.pullJoint.Enabled = true;
|
|
pullLimb.pullJoint.WorldAnchorB = (i == 0) ? rightHandPos : leftHandPos;
|
|
pullLimb.pullJoint.MaxForce = 500.0f;
|
|
}
|
|
|
|
}
|
|
|
|
public override void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle)
|
|
{
|
|
Holdable holdable = item.GetComponent<Holdable>();
|
|
|
|
if (character.IsUnconscious || character.Stun > 0.0f) aim = false;
|
|
|
|
//calculate the handle positions
|
|
Matrix itemTransfrom = Matrix.CreateRotationZ(item.body.Rotation);
|
|
Vector2[] transformedHandlePos = new Vector2[2];
|
|
transformedHandlePos[0] = Vector2.Transform(handlePos[0], itemTransfrom);
|
|
transformedHandlePos[1] = Vector2.Transform(handlePos[1], itemTransfrom);
|
|
|
|
Limb head = GetLimb(LimbType.Head);
|
|
Limb torso = GetLimb(LimbType.Torso);
|
|
Limb leftHand = GetLimb(LimbType.LeftHand);
|
|
Limb rightHand = GetLimb(LimbType.RightHand);
|
|
|
|
Vector2 itemPos = aim ? aimPos : holdPos;
|
|
|
|
bool usingController = character.SelectedConstruction != null && character.SelectedConstruction.GetComponent<Controller>() != null;
|
|
|
|
|
|
float itemAngle;
|
|
if (Anim != Animation.Climbing && !usingController && stunTimer <= 0.0f && aim && itemPos != Vector2.Zero)
|
|
{
|
|
Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
|
|
|
|
Vector2 diff = (mousePos - torso.SimPosition) * Dir;
|
|
|
|
holdAngle = MathUtils.VectorToAngle(new Vector2(diff.X, diff.Y * Dir)) - torso.body.Rotation * Dir;
|
|
|
|
itemAngle = (torso.body.Rotation + holdAngle * Dir);
|
|
|
|
if (holdable.ControlPose)
|
|
{
|
|
head.body.SmoothRotate(itemAngle);
|
|
|
|
if (TargetMovement == Vector2.Zero && inWater)
|
|
{
|
|
torso.body.AngularVelocity -= torso.body.AngularVelocity * 0.1f;
|
|
torso.body.ApplyForce(torso.body.LinearVelocity * -0.5f);
|
|
}
|
|
|
|
aiming = true;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
itemAngle = (torso.body.Rotation + holdAngle * Dir);
|
|
}
|
|
|
|
Vector2 shoulderPos = limbJoints[2].WorldAnchorA;
|
|
Vector2 transformedHoldPos = shoulderPos;
|
|
|
|
if (itemPos == Vector2.Zero || Anim == Animation.Climbing || usingController)
|
|
{
|
|
if (character.SelectedItems[1] == item)
|
|
{
|
|
transformedHoldPos = leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1];
|
|
itemAngle = (leftHand.Rotation + (holdAngle - MathHelper.PiOver2) * Dir);
|
|
}
|
|
if (character.SelectedItems[0] == item)
|
|
{
|
|
transformedHoldPos = rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0];
|
|
itemAngle = (rightHand.Rotation + (holdAngle - MathHelper.PiOver2) * Dir);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (character.SelectedItems[0] == item)
|
|
{
|
|
rightHand.Disabled = true;
|
|
}
|
|
if (character.SelectedItems[1] == item)
|
|
{
|
|
leftHand.Disabled = true;
|
|
}
|
|
|
|
|
|
itemPos.X = itemPos.X * Dir;
|
|
|
|
Matrix torsoTransform = Matrix.CreateRotationZ(itemAngle);
|
|
|
|
transformedHoldPos += Vector2.Transform(itemPos, torsoTransform);
|
|
}
|
|
|
|
item.body.ResetDynamics();
|
|
|
|
Vector2 currItemPos = (character.SelectedItems[0] == item) ?
|
|
rightHand.pullJoint.WorldAnchorA - transformedHandlePos[0] :
|
|
leftHand.pullJoint.WorldAnchorA - transformedHandlePos[1];
|
|
item.SetTransform(currItemPos, itemAngle);
|
|
|
|
//item.SetTransform(MathUtils.SmoothStep(item.body.SimPosition, transformedHoldPos + bodyVelocity, 0.5f), itemAngle);
|
|
|
|
if (Anim == Animation.Climbing) return;
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
if (character.SelectedItems[i] != item) continue;
|
|
if (itemPos == Vector2.Zero) continue;
|
|
|
|
Limb hand = (i == 0) ? rightHand : leftHand;
|
|
|
|
HandIK(hand, transformedHoldPos + transformedHandlePos[i]);
|
|
}
|
|
}
|
|
|
|
private void HandIK(Limb hand, Vector2 pos, float force = 1.0f)
|
|
{
|
|
Vector2 shoulderPos = limbJoints[2].WorldAnchorA;
|
|
|
|
Limb arm = (hand.type == LimbType.LeftHand) ? GetLimb(LimbType.LeftArm) : GetLimb(LimbType.RightArm);
|
|
|
|
//hand length
|
|
float a = 37.0f;
|
|
|
|
//arm length
|
|
float b = 28.0f;
|
|
|
|
//distance from shoulder to holdpos
|
|
float c = ConvertUnits.ToDisplayUnits(Vector2.Distance(pos, shoulderPos));
|
|
c = MathHelper.Clamp(a + b - 1, b - a, c);
|
|
|
|
float ang2 = MathUtils.VectorToAngle(pos - shoulderPos) + MathHelper.PiOver2;
|
|
|
|
float armAngle = MathUtils.SolveTriangleSSS(a, b, c);
|
|
float handAngle = MathUtils.SolveTriangleSSS(b, a, c);
|
|
|
|
arm.body.SmoothRotate((ang2 - armAngle * Dir), 20.0f * force);
|
|
hand.body.SmoothRotate((ang2 + handAngle * Dir), 100.0f * force);
|
|
}
|
|
|
|
public override void Flip()
|
|
{
|
|
base.Flip();
|
|
|
|
walkPos = -walkPos;
|
|
|
|
Limb torso = GetLimb(LimbType.Torso);
|
|
|
|
Vector2 difference;
|
|
|
|
Matrix torsoTransform = Matrix.CreateRotationZ(torso.Rotation);
|
|
|
|
for (int i = 0; i < character.SelectedItems.Length; i++)
|
|
{
|
|
if (character.SelectedItems[i] != null)
|
|
{
|
|
difference = character.SelectedItems[i].body.SimPosition - torso.SimPosition;
|
|
difference = Vector2.Transform(difference, torsoTransform);
|
|
difference.Y = -difference.Y;
|
|
|
|
character.SelectedItems[i].body.SetTransform(
|
|
torso.SimPosition + Vector2.Transform(difference, -torsoTransform),
|
|
MathUtils.WrapAngleTwoPi(-character.SelectedItems[i].body.Rotation));
|
|
}
|
|
}
|
|
|
|
foreach (Limb limb in Limbs)
|
|
{
|
|
bool mirror = false;
|
|
bool flipAngle = false;
|
|
bool wrapAngle = false;
|
|
|
|
switch (limb.type)
|
|
{
|
|
case LimbType.LeftHand:
|
|
case LimbType.LeftArm:
|
|
case LimbType.RightHand:
|
|
case LimbType.RightArm:
|
|
mirror = true;
|
|
flipAngle = true;
|
|
break;
|
|
case LimbType.LeftThigh:
|
|
case LimbType.LeftLeg:
|
|
case LimbType.LeftFoot:
|
|
case LimbType.RightThigh:
|
|
case LimbType.RightLeg:
|
|
case LimbType.RightFoot:
|
|
mirror = Crouching && !inWater;
|
|
flipAngle = (limb.DoesFlip || Crouching) && !inWater;
|
|
wrapAngle = !inWater;
|
|
break;
|
|
default:
|
|
flipAngle = limb.DoesFlip && !inWater;
|
|
wrapAngle = !inWater;
|
|
break;
|
|
}
|
|
|
|
Vector2 position = limb.SimPosition;
|
|
|
|
if ((limb.pullJoint == null || !limb.pullJoint.Enabled) && mirror)
|
|
{
|
|
difference = limb.body.SimPosition - torso.SimPosition;
|
|
difference = Vector2.Transform(difference, torsoTransform);
|
|
difference.Y = -difference.Y;
|
|
|
|
position = torso.SimPosition + Vector2.Transform(difference, -torsoTransform);
|
|
|
|
//TrySetLimbPosition(limb, limb.SimPosition, );
|
|
}
|
|
|
|
float angle = flipAngle ? -limb.body.Rotation : limb.body.Rotation;
|
|
if (wrapAngle) angle = MathUtils.WrapAnglePi(angle);
|
|
|
|
TrySetLimbPosition(limb, Collider.SimPosition, position);
|
|
|
|
limb.body.SetTransform(limb.body.SimPosition, angle);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|