Unstable 0.1500.5.0 (almost forgor edition 💀)
This commit is contained in:
@@ -1,12 +1,31 @@
|
||||
using FarseerPhysics;
|
||||
using Barotrauma.Items.Components;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
abstract class AnimController : Ragdoll
|
||||
{
|
||||
public Vector2 RightHandIKPos { get; protected set; }
|
||||
public Vector2 LeftHandIKPos { get; protected set; }
|
||||
|
||||
protected LimbJoint rightShoulder, leftShoulder;
|
||||
protected float upperArmLength, forearmLength;
|
||||
protected float useItemTimer;
|
||||
protected bool aiming;
|
||||
protected bool wasAiming;
|
||||
protected bool aimingMelee;
|
||||
protected bool wasAimingMelee;
|
||||
|
||||
public bool IsAiming => wasAiming;
|
||||
public bool IsAimingMelee => wasAimingMelee;
|
||||
|
||||
public float ArmLength => upperArmLength + forearmLength;
|
||||
|
||||
public abstract GroundedMovementParams WalkParams { get; set; }
|
||||
public abstract GroundedMovementParams RunParams { get; set; }
|
||||
public abstract SwimParams SwimSlowParams { get; set; }
|
||||
@@ -60,14 +79,14 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
return IsMovingFast? SwimFastParams : SwimSlowParams;
|
||||
return IsMovingFast ? SwimFastParams : SwimSlowParams;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanWalk => RagdollParams.CanWalk;
|
||||
public bool IsMovingBackwards => !InWater && Math.Sign(targetMovement.X) == -Math.Sign(Dir);
|
||||
|
||||
|
||||
// TODO: define death anim duration in XML
|
||||
protected float deathAnimTimer, deathAnimDuration = 5.0f;
|
||||
|
||||
@@ -155,13 +174,9 @@ namespace Barotrauma
|
||||
|
||||
public AnimController(Character character, string seed, RagdollParams ragdollParams = null) : base(character, seed, ragdollParams) { }
|
||||
|
||||
public virtual void UpdateAnim(float deltaTime) { }
|
||||
public abstract void UpdateAnim(float deltaTime);
|
||||
|
||||
public virtual void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle, float itemAngleRelativeToHoldAngle = 0.0f, bool aimingMelee = false) { }
|
||||
|
||||
public virtual void DragCharacter(Character target, float deltaTime) { }
|
||||
|
||||
public virtual void UpdateUseItem(bool allowMovement, Vector2 handWorldPos) { }
|
||||
public abstract void DragCharacter(Character target, float deltaTime);
|
||||
|
||||
public virtual float GetSpeed(AnimationType type)
|
||||
{
|
||||
@@ -253,5 +268,437 @@ namespace Barotrauma
|
||||
throw new NotImplementedException(type.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateUseItem(bool allowMovement, Vector2 handWorldPos)
|
||||
{
|
||||
useItemTimer = 0.5f;
|
||||
Anim = Animation.UsingConstruction;
|
||||
|
||||
if (!allowMovement)
|
||||
{
|
||||
TargetMovement = Vector2.Zero;
|
||||
TargetDir = handWorldPos.X > character.WorldPosition.X ? Direction.Right : Direction.Left;
|
||||
float sqrDist = Vector2.DistanceSquared(character.WorldPosition, handWorldPos);
|
||||
if (sqrDist > MathUtils.Pow(ConvertUnits.ToDisplayUnits(upperArmLength + forearmLength), 2))
|
||||
{
|
||||
TargetMovement = Vector2.Normalize(handWorldPos - character.WorldPosition) * GetCurrentSpeed(false) * Math.Max(character.SpeedMultiplier, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!character.Enabled) { return; }
|
||||
|
||||
Vector2 handSimPos = ConvertUnits.ToSimUnits(handWorldPos);
|
||||
if (character.Submarine != null)
|
||||
{
|
||||
handSimPos -= character.Submarine.SimPosition;
|
||||
}
|
||||
|
||||
var leftHand = GetLimb(LimbType.LeftHand);
|
||||
if (leftHand != null)
|
||||
{
|
||||
leftHand.Disabled = true;
|
||||
leftHand.PullJointEnabled = true;
|
||||
leftHand.PullJointWorldAnchorB = handSimPos;
|
||||
}
|
||||
|
||||
var rightHand = GetLimb(LimbType.RightHand);
|
||||
if (rightHand != null)
|
||||
{
|
||||
rightHand.Disabled = true;
|
||||
rightHand.PullJointEnabled = true;
|
||||
rightHand.PullJointWorldAnchorB = handSimPos;
|
||||
}
|
||||
}
|
||||
|
||||
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.PullJointEnabled = true;
|
||||
pullLimb.PullJointWorldAnchorB = (i == 0) ? rightHandPos : leftHandPos;
|
||||
pullLimb.PullJointMaxForce = 500.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private Direction previousDirection;
|
||||
private readonly Vector2[] transformedHandlePos = new Vector2[2];
|
||||
//TODO: refactor this method, it's way too convoluted
|
||||
public void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle, float itemAngleRelativeToHoldAngle = 0.0f, bool aimMelee = false)
|
||||
{
|
||||
aimingMelee = aimMelee;
|
||||
if (character.Stun > 0.0f || character.IsIncapacitated)
|
||||
{
|
||||
aim = false;
|
||||
}
|
||||
|
||||
//calculate the handle positions
|
||||
Matrix itemTransfrom = Matrix.CreateRotationZ(item.body.Rotation);
|
||||
float horizontalOffset = ConvertUnits.ToSimUnits((item.Sprite.size.X / 2 - item.Sprite.Origin.X) * item.Scale);
|
||||
|
||||
//handlePos[0] = ConvertUnits.ToSimUnits(new Vector2(-45,25) * 0.5f);
|
||||
//handlePos[1] = ConvertUnits.ToSimUnits(new Vector2(-65,30) * 0.5f);
|
||||
|
||||
transformedHandlePos[0] = Vector2.Transform(new Vector2(handlePos[0].X + horizontalOffset, handlePos[0].Y), itemTransfrom);
|
||||
transformedHandlePos[1] = Vector2.Transform(new Vector2(handlePos[1].X + horizontalOffset, handlePos[1].Y), itemTransfrom);
|
||||
|
||||
Limb torso = GetLimb(LimbType.Torso) ?? MainLimb;
|
||||
Limb leftHand = GetLimb(LimbType.LeftHand);
|
||||
Limb rightHand = GetLimb(LimbType.RightHand);
|
||||
|
||||
Vector2 itemPos = aim ? aimPos : holdPos;
|
||||
|
||||
var controller = character.SelectedConstruction?.GetComponent<Controller>();
|
||||
bool usingController = controller != null && !controller.AllowAiming;
|
||||
bool isClimbing = character.IsClimbing && Math.Abs(character.AnimController.TargetMovement.Y) > 0.01f;
|
||||
float itemAngle;
|
||||
Holdable holdable = item.GetComponent<Holdable>();
|
||||
float torsoRotation = torso.Rotation;
|
||||
bool equippedInRightHand = character.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == item && rightHand != null && !rightHand.IsSevered;
|
||||
bool equippedInLefthand = character.Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand) == item && leftHand != null && !leftHand.IsSevered;
|
||||
if (aim && !isClimbing && !usingController && character.Stun <= 0.0f && itemPos != Vector2.Zero && !character.IsIncapacitated)
|
||||
{
|
||||
Vector2 mousePos = ConvertUnits.ToSimUnits(character.SmoothedCursorPosition);
|
||||
Vector2 diff = holdable.Aimable ? (mousePos - AimSourceSimPos) * Dir : Vector2.UnitX;
|
||||
holdAngle = MathUtils.VectorToAngle(new Vector2(diff.X, diff.Y * Dir)) - torsoRotation * Dir;
|
||||
holdAngle += GetAimWobble(rightHand, leftHand, item);
|
||||
itemAngle = torsoRotation + holdAngle * Dir;
|
||||
if (holdable.ControlPose)
|
||||
{
|
||||
var head = GetLimb(LimbType.Head);
|
||||
if (head != null)
|
||||
{
|
||||
head.body.SmoothRotate(itemAngle, force: 30 * head.Mass);
|
||||
}
|
||||
if (TargetMovement == Vector2.Zero && inWater)
|
||||
{
|
||||
torso.body.AngularVelocity -= torso.body.AngularVelocity * 0.1f;
|
||||
torso.body.ApplyForce(torso.body.LinearVelocity * -0.5f);
|
||||
}
|
||||
aiming = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (holdable.UseHandRotationForHoldAngle)
|
||||
{
|
||||
if (equippedInRightHand)
|
||||
{
|
||||
itemAngle = rightHand.Rotation + holdAngle * Dir;
|
||||
}
|
||||
else if (equippedInLefthand)
|
||||
{
|
||||
itemAngle = leftHand.Rotation + holdAngle * Dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemAngle = torsoRotation + holdAngle * Dir;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
itemAngle = torsoRotation + holdAngle * Dir;
|
||||
}
|
||||
}
|
||||
|
||||
if (rightShoulder == null) { return; }
|
||||
Vector2 transformedHoldPos = rightShoulder.WorldAnchorA;
|
||||
if (itemPos == Vector2.Zero || isClimbing || usingController)
|
||||
{
|
||||
if (equippedInRightHand)
|
||||
{
|
||||
transformedHoldPos = rightHand.PullJointWorldAnchorA - transformedHandlePos[0];
|
||||
itemAngle = rightHand.Rotation + (holdAngle - rightHand.Params.GetSpriteOrientation() + MathHelper.PiOver2) * Dir;
|
||||
}
|
||||
else if (equippedInLefthand)
|
||||
{
|
||||
transformedHoldPos = leftHand.PullJointWorldAnchorA - transformedHandlePos[1];
|
||||
itemAngle = leftHand.Rotation + (holdAngle - leftHand.Params.GetSpriteOrientation() + MathHelper.PiOver2) * Dir;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (equippedInRightHand)
|
||||
{
|
||||
transformedHoldPos = rightShoulder.WorldAnchorA;
|
||||
rightHand.Disabled = true;
|
||||
}
|
||||
if (equippedInLefthand)
|
||||
{
|
||||
if (leftShoulder == null) { return; }
|
||||
transformedHoldPos = leftShoulder.WorldAnchorA;
|
||||
leftHand.Disabled = true;
|
||||
}
|
||||
itemPos.X *= Dir;
|
||||
transformedHoldPos += Vector2.Transform(itemPos, Matrix.CreateRotationZ(itemAngle));
|
||||
}
|
||||
|
||||
item.body.ResetDynamics();
|
||||
|
||||
Vector2 currItemPos = equippedInRightHand ?
|
||||
rightHand.PullJointWorldAnchorA - transformedHandlePos[0] :
|
||||
leftHand.PullJointWorldAnchorA - transformedHandlePos[1];
|
||||
|
||||
if (!MathUtils.IsValid(currItemPos))
|
||||
{
|
||||
string errorMsg = "Attempted to move the item \"" + item + "\" to an invalid position in HumanidAnimController.HoldItem: " +
|
||||
currItemPos + ", rightHandPos: " + rightHand.PullJointWorldAnchorA + ", leftHandPos: " + leftHand.PullJointWorldAnchorA +
|
||||
", handlePos[0]: " + handlePos[0] + ", handlePos[1]: " + handlePos[1] +
|
||||
", transformedHandlePos[0]: " + transformedHandlePos[0] + ", transformedHandlePos[1]:" + transformedHandlePos[1] +
|
||||
", item pos: " + item.SimPosition + ", itemAngle: " + itemAngle +
|
||||
", collider pos: " + character.SimPosition;
|
||||
DebugConsole.Log(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"HumanoidAnimController.HoldItem:InvalidPos:" + character.Name + item.Name,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
errorMsg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (holdable.Pusher != null)
|
||||
{
|
||||
if (character.Stun > 0.0f || character.IsIncapacitated)
|
||||
{
|
||||
holdable.Pusher.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!holdable.Pusher.Enabled)
|
||||
{
|
||||
holdable.Pusher.Enabled = true;
|
||||
holdable.Pusher.ResetDynamics();
|
||||
holdable.Pusher.SetTransform(currItemPos, itemAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
holdable.Pusher.TargetPosition = currItemPos;
|
||||
holdable.Pusher.TargetRotation = holdAngle * Dir;
|
||||
|
||||
holdable.Pusher.MoveToTargetPosition(true);
|
||||
|
||||
currItemPos = holdable.Pusher.SimPosition;
|
||||
itemAngle = holdable.Pusher.Rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
float targetAngle = MathUtils.WrapAngleTwoPi(itemAngle + itemAngleRelativeToHoldAngle * Dir);
|
||||
float currentRotation = MathUtils.WrapAngleTwoPi(item.body.Rotation);
|
||||
float itemRotation = MathHelper.SmoothStep(currentRotation, targetAngle, deltaTime * 25);
|
||||
if (previousDirection != dir || Math.Abs(targetAngle - currentRotation) > MathHelper.Pi)
|
||||
{
|
||||
itemRotation = targetAngle;
|
||||
}
|
||||
item.SetTransform(currItemPos, itemRotation, setPrevTransform: false);
|
||||
previousDirection = dir;
|
||||
|
||||
if (!isClimbing && !character.IsIncapacitated && itemPos != Vector2.Zero && (aim || !holdable.UseHandRotationForHoldAngle))
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (!character.Inventory.IsInLimbSlot(item, i == 0 ? InvSlotType.RightHand : InvSlotType.LeftHand)) { continue; }
|
||||
#if DEBUG
|
||||
if (handlePos[i].LengthSquared() > ArmLength)
|
||||
{
|
||||
DebugConsole.AddWarning($"Aim position for the item {item.Name} may be incorrect (further than the length of the character's arm)");
|
||||
}
|
||||
#endif
|
||||
HandIK(i == 0 ? rightHand : leftHand, transformedHoldPos + transformedHandlePos[i], CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float GetAimWobble(Limb rightHand, Limb leftHand, Item heldItem)
|
||||
{
|
||||
float wobbleStrength = 0.0f;
|
||||
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == heldItem)
|
||||
{
|
||||
wobbleStrength += Character.CharacterHealth.GetLimbDamage(rightHand, afflictionType: "damage");
|
||||
}
|
||||
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand) == heldItem)
|
||||
{
|
||||
wobbleStrength += Character.CharacterHealth.GetLimbDamage(leftHand, afflictionType: "damage");
|
||||
}
|
||||
if (wobbleStrength <= 0.1f) { return 0.0f; }
|
||||
wobbleStrength = (float)Math.Min(wobbleStrength, 1.0f);
|
||||
|
||||
float lowFreqNoise = PerlinNoise.GetPerlin((float)Timing.TotalTime / 320.0f, (float)Timing.TotalTime / 240.0f) - 0.5f;
|
||||
float highFreqNoise = PerlinNoise.GetPerlin((float)Timing.TotalTime / 40.0f, (float)Timing.TotalTime / 50.0f) - 0.5f;
|
||||
|
||||
return (lowFreqNoise * 1.0f + highFreqNoise * 0.1f) * wobbleStrength;
|
||||
}
|
||||
|
||||
public void HandIK(Limb hand, Vector2 pos, float armTorque = 1.0f, float handTorque = 1.0f)
|
||||
{
|
||||
Vector2 shoulderPos;
|
||||
|
||||
Limb arm, forearm;
|
||||
if (hand.type == LimbType.LeftHand)
|
||||
{
|
||||
if (leftShoulder == null) { return; }
|
||||
shoulderPos = leftShoulder.WorldAnchorA;
|
||||
arm = GetLimb(LimbType.LeftArm);
|
||||
forearm = GetLimb(LimbType.LeftForearm);
|
||||
LeftHandIKPos = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rightShoulder == null) { return; }
|
||||
shoulderPos = rightShoulder.WorldAnchorA;
|
||||
arm = GetLimb(LimbType.RightArm);
|
||||
forearm = GetLimb(LimbType.RightForearm);
|
||||
RightHandIKPos = pos;
|
||||
}
|
||||
if (arm == null) { return; }
|
||||
|
||||
//distance from shoulder to holdpos
|
||||
float c = Vector2.Distance(pos, shoulderPos);
|
||||
c = MathHelper.Clamp(c, Math.Abs(upperArmLength - forearmLength), forearmLength + upperArmLength - 0.01f);
|
||||
|
||||
float armAngle = MathUtils.VectorToAngle(pos - shoulderPos) + arm.Params.GetSpriteOrientation() - MathHelper.PiOver2;
|
||||
float upperArmAngle = MathUtils.SolveTriangleSSS(forearmLength, upperArmLength, c) * Dir;
|
||||
float lowerArmAngle = MathUtils.SolveTriangleSSS(upperArmLength, forearmLength, c) * Dir;
|
||||
|
||||
//make sure the arm angle "has the same number of revolutions" as the arm
|
||||
while (arm.Rotation - armAngle > MathHelper.Pi)
|
||||
{
|
||||
armAngle += MathHelper.TwoPi;
|
||||
}
|
||||
while (arm.Rotation - armAngle < -MathHelper.Pi)
|
||||
{
|
||||
armAngle -= MathHelper.TwoPi;
|
||||
}
|
||||
|
||||
arm?.body.SmoothRotate(armAngle - upperArmAngle, 100.0f * armTorque * arm.Mass, wrapAngle: false);
|
||||
float forearmAngle = armAngle + lowerArmAngle;
|
||||
forearm?.body.SmoothRotate(forearmAngle, 100.0f * handTorque * forearm.Mass, wrapAngle: false);
|
||||
float handAngle = forearm != null ? forearmAngle : armAngle;
|
||||
hand?.body.SmoothRotate(handAngle, 10.0f * handTorque * hand.Mass, wrapAngle: false);
|
||||
}
|
||||
|
||||
public void ApplyPose(Vector2 leftHandPos, Vector2 rightHandPos, Vector2 leftFootPos, Vector2 rightFootPos, float footMoveForce = 10)
|
||||
{
|
||||
var leftHand = GetLimb(LimbType.LeftHand);
|
||||
var rightHand = GetLimb(LimbType.RightHand);
|
||||
var waist = GetLimb(LimbType.Waist) ?? GetLimb(LimbType.Torso);
|
||||
if (waist == null) { return; }
|
||||
Vector2 midPos = waist.SimPosition;
|
||||
if (leftHand != null)
|
||||
{
|
||||
leftHand.Disabled = true;
|
||||
leftHandPos.X *= Dir;
|
||||
leftHandPos += midPos;
|
||||
HandIK(leftHand, leftHandPos);
|
||||
}
|
||||
if (rightHand != null)
|
||||
{
|
||||
rightHand.Disabled = true;
|
||||
rightHandPos.X *= Dir;
|
||||
rightHandPos += midPos;
|
||||
HandIK(rightHand, rightHandPos);
|
||||
}
|
||||
var leftFoot = GetLimb(LimbType.LeftFoot);
|
||||
if (leftFoot != null)
|
||||
{
|
||||
leftFoot.Disabled = true;
|
||||
leftFootPos = new Vector2(waist.SimPosition.X + leftFootPos.X * Dir, GetColliderBottom().Y + leftFootPos.Y);
|
||||
MoveLimb(leftFoot, leftFootPos, Math.Abs(leftFoot.SimPosition.X - leftFootPos.X) * footMoveForce * leftFoot.Mass, true);
|
||||
}
|
||||
var rightFoot = GetLimb(LimbType.RightFoot);
|
||||
if (rightFoot != null)
|
||||
{
|
||||
rightFoot.Disabled = true;
|
||||
rightFootPos = new Vector2(waist.SimPosition.X + rightFootPos.X * Dir, GetColliderBottom().Y + rightFootPos.Y);
|
||||
MoveLimb(rightFoot, rightFootPos, Math.Abs(rightFoot.SimPosition.X - rightFootPos.X) * footMoveForce * rightFoot.Mass, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyTestPose()
|
||||
{
|
||||
var waist = GetLimb(LimbType.Waist) ?? GetLimb(LimbType.Torso);
|
||||
if (waist != null)
|
||||
{
|
||||
ApplyPose(
|
||||
new Vector2(-0.75f, -0.2f),
|
||||
new Vector2(0.75f, -0.2f),
|
||||
new Vector2(-WalkParams.StepSize.X * 0.5f, -0.1f * RagdollParams.JointScale),
|
||||
new Vector2(WalkParams.StepSize.X * 0.5f, -0.1f * RagdollParams.JointScale));
|
||||
}
|
||||
}
|
||||
|
||||
protected void CalculateArmLengths()
|
||||
{
|
||||
//calculate arm and forearm length (atm this assumes that both arms are the same size)
|
||||
Limb rightForearm = GetLimb(LimbType.RightForearm);
|
||||
Limb rightHand = GetLimb(LimbType.RightHand);
|
||||
if (rightHand == null) { return; }
|
||||
|
||||
rightShoulder = GetJointBetweenLimbs(LimbType.Torso, LimbType.RightArm) ?? GetJointBetweenLimbs(LimbType.Head, LimbType.RightArm) ?? GetJoint(LimbType.RightArm, new LimbType[] { LimbType.RightHand, LimbType.RightForearm });
|
||||
leftShoulder = GetJointBetweenLimbs(LimbType.Torso, LimbType.LeftArm) ?? GetJointBetweenLimbs(LimbType.Head, LimbType.LeftArm) ?? GetJoint(LimbType.LeftArm, new LimbType[] { LimbType.LeftHand, LimbType.LeftForearm });
|
||||
|
||||
Vector2 localAnchorShoulder = Vector2.Zero;
|
||||
Vector2 localAnchorElbow = Vector2.Zero;
|
||||
if (rightShoulder != null)
|
||||
{
|
||||
localAnchorShoulder = rightShoulder.LimbA.type == LimbType.RightArm ? rightShoulder.LocalAnchorA : rightShoulder.LocalAnchorB;
|
||||
}
|
||||
LimbJoint rightElbow = rightForearm == null ?
|
||||
GetJointBetweenLimbs(LimbType.RightArm, LimbType.RightHand) :
|
||||
GetJointBetweenLimbs(LimbType.RightArm, LimbType.RightForearm);
|
||||
if (rightElbow != null)
|
||||
{
|
||||
localAnchorElbow = rightElbow.LimbA.type == LimbType.RightArm ? rightElbow.LocalAnchorA : rightElbow.LocalAnchorB;
|
||||
}
|
||||
upperArmLength = Vector2.Distance(localAnchorShoulder, localAnchorElbow);
|
||||
if (rightElbow != null)
|
||||
{
|
||||
if (rightForearm == null)
|
||||
{
|
||||
forearmLength = Vector2.Distance(
|
||||
rightHand.PullJointLocalAnchorA,
|
||||
rightElbow.LimbA.type == LimbType.RightHand ? rightElbow.LocalAnchorA : rightElbow.LocalAnchorB);
|
||||
}
|
||||
else
|
||||
{
|
||||
LimbJoint rightWrist = GetJointBetweenLimbs(LimbType.RightForearm, LimbType.RightHand);
|
||||
if (rightWrist != null)
|
||||
{
|
||||
forearmLength = Vector2.Distance(
|
||||
rightElbow.LimbA.type == LimbType.RightForearm ? rightElbow.LocalAnchorA : rightElbow.LocalAnchorB,
|
||||
rightWrist.LimbA.type == LimbType.RightForearm ? rightWrist.LocalAnchorA : rightWrist.LocalAnchorB);
|
||||
|
||||
forearmLength += Vector2.Distance(
|
||||
rightHand.PullJointLocalAnchorA,
|
||||
rightElbow.LimbA.type == LimbType.RightHand ? rightElbow.LocalAnchorA : rightElbow.LocalAnchorB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected LimbJoint GetJointBetweenLimbs(LimbType limbTypeA, LimbType limbTypeB)
|
||||
{
|
||||
return LimbJoints.FirstOrDefault(lj =>
|
||||
(lj.LimbA.type == limbTypeA && lj.LimbB.type == limbTypeB) ||
|
||||
(lj.LimbB.type == limbTypeA && lj.LimbA.type == limbTypeB));
|
||||
}
|
||||
|
||||
protected LimbJoint GetJoint(LimbType matchingType, IEnumerable<LimbType> ignoredTypes)
|
||||
{
|
||||
return LimbJoints.FirstOrDefault(lj =>
|
||||
lj.LimbA.type == matchingType && ignoredTypes.None(t => lj.LimbB.type == t) ||
|
||||
lj.LimbB.type == matchingType && ignoredTypes.None(t => lj.LimbB.type == t));
|
||||
}
|
||||
|
||||
public override void Recreate(RagdollParams ragdollParams = null)
|
||||
{
|
||||
base.Recreate(ragdollParams);
|
||||
if (Character.Params.CanInteract)
|
||||
{
|
||||
CalculateArmLengths();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-5
@@ -139,7 +139,7 @@ namespace Barotrauma
|
||||
if (MainLimb == null) { return; }
|
||||
var mainLimb = MainLimb;
|
||||
|
||||
levitatingCollider = true;
|
||||
levitatingCollider = !IsHanging;
|
||||
|
||||
if (!character.CanMove)
|
||||
{
|
||||
@@ -192,6 +192,11 @@ namespace Barotrauma
|
||||
strongestImpact = 0.0f;
|
||||
}
|
||||
|
||||
if (aiming)
|
||||
{
|
||||
TargetMovement = TargetMovement.ClampLength(2);
|
||||
}
|
||||
|
||||
if (inWater && !forceStanding)
|
||||
{
|
||||
Collider.FarseerBody.FixedRotation = false;
|
||||
@@ -202,7 +207,7 @@ namespace Barotrauma
|
||||
if (CurrentGroundedParams != null)
|
||||
{
|
||||
//rotate collider back upright
|
||||
float standAngle = dir == Direction.Right ? CurrentGroundedParams.ColliderStandAngleInRadians : -CurrentGroundedParams.ColliderStandAngleInRadians;
|
||||
float standAngle = CurrentGroundedParams.ColliderStandAngleInRadians * Dir;
|
||||
if (Math.Abs(MathUtils.GetShortestAngle(Collider.Rotation, standAngle)) > 0.001f)
|
||||
{
|
||||
Collider.AngularVelocity = MathUtils.GetShortestAngle(Collider.Rotation, standAngle) * 60.0f;
|
||||
@@ -215,17 +220,19 @@ namespace Barotrauma
|
||||
}
|
||||
UpdateWalkAnim(deltaTime);
|
||||
}
|
||||
|
||||
if (character.SelectedCharacter != null)
|
||||
{
|
||||
DragCharacter(character.SelectedCharacter, deltaTime);
|
||||
return;
|
||||
}
|
||||
|
||||
if (character.AnimController.AnimationTestPose)
|
||||
{
|
||||
ApplyTestPose();
|
||||
}
|
||||
//don't flip when simply physics is enabled
|
||||
if (SimplePhysicsEnabled) { return; }
|
||||
|
||||
if (!character.IsRemotelyControlled && (character.AIController == null || character.AIController.CanFlip))
|
||||
if (!character.IsRemotelyControlled && (character.AIController == null || character.AIController.CanFlip) && !aiming)
|
||||
{
|
||||
if (!inWater || (CurrentSwimParams != null && CurrentSwimParams.Mirror))
|
||||
{
|
||||
@@ -290,6 +297,10 @@ namespace Barotrauma
|
||||
{
|
||||
flipTimer = 0.0f;
|
||||
}
|
||||
wasAiming = aiming;
|
||||
aiming = false;
|
||||
wasAimingMelee = aimingMelee;
|
||||
aimingMelee = false;
|
||||
}
|
||||
|
||||
private bool CanDrag(Character target)
|
||||
@@ -449,6 +460,16 @@ namespace Barotrauma
|
||||
//limbs are disabled when simple physics is enabled, no need to move them
|
||||
if (SimplePhysicsEnabled) { return; }
|
||||
mainLimb.PullJointEnabled = true;
|
||||
|
||||
if (aiming && movement.Length() <= 0.1f)
|
||||
{
|
||||
Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
|
||||
Vector2 diff = (mousePos - (GetLimb(LimbType.Torso) ?? MainLimb).SimPosition) * Dir;
|
||||
TargetMovement = new Vector2(0.0f, -0.1f);
|
||||
float newRotation = MathUtils.VectorToAngle(diff);
|
||||
Collider.SmoothRotate(newRotation, CurrentSwimParams.SteerTorque * character.SpeedMultiplier);
|
||||
}
|
||||
|
||||
if (!isMoving)
|
||||
{
|
||||
WalkPos = MathHelper.SmoothStep(WalkPos, MathHelper.PiOver2, deltaTime * 5);
|
||||
|
||||
+37
-404
@@ -146,34 +146,8 @@ namespace Barotrauma
|
||||
|
||||
public bool Crouching;
|
||||
|
||||
private float upperArmLength = 0.0f, forearmLength = 0.0f;
|
||||
|
||||
public float ArmLength => upperArmLength + forearmLength;
|
||||
|
||||
public Vector2 RightHandIKPos
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public Vector2 LeftHandIKPos
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private LimbJoint rightShoulder, leftShoulder;
|
||||
|
||||
private float upperLegLength = 0.0f, lowerLegLength = 0.0f;
|
||||
|
||||
private bool aiming;
|
||||
private bool wasAiming;
|
||||
|
||||
private bool aimingMelee;
|
||||
private bool wasAimingMelee;
|
||||
|
||||
public bool IsAiming => wasAiming;
|
||||
public bool IsAimingMelee => wasAimingMelee;
|
||||
|
||||
private readonly float movementLerp;
|
||||
|
||||
private float cprAnimTimer;
|
||||
@@ -184,7 +158,6 @@ namespace Barotrauma
|
||||
//prevents rapid switches between swimming/walking if the water level is fluctuating around the minimum swimming depth
|
||||
private float swimmingStateLockTimer;
|
||||
|
||||
private float useItemTimer;
|
||||
public float HeadLeanAmount => CurrentGroundedParams.HeadLeanAmount;
|
||||
public float TorsoLeanAmount => CurrentGroundedParams.TorsoLeanAmount;
|
||||
public Vector2 FootMoveOffset => CurrentGroundedParams.FootMoveOffset * RagdollParams.JointScale;
|
||||
@@ -219,61 +192,12 @@ namespace Barotrauma
|
||||
movementLerp = RagdollParams.MainElement.GetAttributeFloat("movementlerp", 0.4f);
|
||||
}
|
||||
|
||||
public override void Recreate(RagdollParams ragdollParams)
|
||||
public override void Recreate(RagdollParams ragdollParams = null)
|
||||
{
|
||||
base.Recreate(ragdollParams);
|
||||
CalculateArmLengths();
|
||||
CalculateLegLengths();
|
||||
}
|
||||
|
||||
private void CalculateArmLengths()
|
||||
{
|
||||
//calculate arm and forearm length (atm this assumes that both arms are the same size)
|
||||
Limb rightForearm = GetLimb(LimbType.RightForearm);
|
||||
Limb rightHand = GetLimb(LimbType.RightHand);
|
||||
if (rightHand == null) { return; }
|
||||
|
||||
rightShoulder = GetJointBetweenLimbs(LimbType.Torso, LimbType.RightArm);
|
||||
leftShoulder = GetJointBetweenLimbs(LimbType.Torso, LimbType.LeftArm);
|
||||
Vector2 localAnchorShoulder = Vector2.Zero;
|
||||
Vector2 localAnchorElbow = Vector2.Zero;
|
||||
if (rightShoulder != null)
|
||||
{
|
||||
localAnchorShoulder = rightShoulder.LimbA.type == LimbType.RightArm ? rightShoulder.LocalAnchorA : rightShoulder.LocalAnchorB;
|
||||
}
|
||||
LimbJoint rightElbow = rightForearm == null ?
|
||||
GetJointBetweenLimbs(LimbType.RightArm, LimbType.RightHand) :
|
||||
GetJointBetweenLimbs(LimbType.RightArm, LimbType.RightForearm);
|
||||
if (rightElbow != null)
|
||||
{
|
||||
localAnchorElbow = rightElbow.LimbA.type == LimbType.RightArm ? rightElbow.LocalAnchorA : rightElbow.LocalAnchorB;
|
||||
}
|
||||
upperArmLength = Vector2.Distance(localAnchorShoulder, localAnchorElbow);
|
||||
if (rightElbow != null)
|
||||
{
|
||||
if (rightForearm == null)
|
||||
{
|
||||
forearmLength = Vector2.Distance(
|
||||
rightHand.PullJointLocalAnchorA,
|
||||
rightElbow.LimbA.type == LimbType.RightHand ? rightElbow.LocalAnchorA : rightElbow.LocalAnchorB);
|
||||
}
|
||||
else
|
||||
{
|
||||
LimbJoint rightWrist = GetJointBetweenLimbs(LimbType.RightForearm, LimbType.RightHand);
|
||||
if (rightWrist != null)
|
||||
{
|
||||
forearmLength = Vector2.Distance(
|
||||
rightElbow.LimbA.type == LimbType.RightForearm ? rightElbow.LocalAnchorA : rightElbow.LocalAnchorB,
|
||||
rightWrist.LimbA.type == LimbType.RightForearm ? rightWrist.LocalAnchorA : rightWrist.LocalAnchorB);
|
||||
|
||||
forearmLength += Vector2.Distance(
|
||||
rightHand.PullJointLocalAnchorA,
|
||||
rightElbow.LimbA.type == LimbType.RightHand ? rightElbow.LocalAnchorA : rightElbow.LocalAnchorB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateLegLengths()
|
||||
{
|
||||
//calculate upper and lower leg length (atm this assumes that both legs are the same size)
|
||||
@@ -304,21 +228,16 @@ namespace Barotrauma
|
||||
ankleJoint.LimbA.type == footType ? ankleJoint.LocalAnchorA : ankleJoint.LocalAnchorB,
|
||||
GetLimb(footType).PullJointLocalAnchorA);
|
||||
}
|
||||
private LimbJoint GetJointBetweenLimbs(LimbType limbTypeA, LimbType limbTypeB)
|
||||
{
|
||||
return LimbJoints.FirstOrDefault(lj =>
|
||||
(lj.LimbA.type == limbTypeA && lj.LimbB.type == limbTypeB) ||
|
||||
(lj.LimbB.type == limbTypeA && lj.LimbA.type == limbTypeB));
|
||||
}
|
||||
|
||||
public override void UpdateAnim(float deltaTime)
|
||||
{
|
||||
if (Frozen) return;
|
||||
if (MainLimb == null) { return; }
|
||||
|
||||
levitatingCollider = true;
|
||||
levitatingCollider = !IsHanging;
|
||||
ColliderIndex = Crouching && !swimming ? 1 : 0;
|
||||
if (character.SelectedConstruction?.GetComponent<Controller>()?.ControlCharacterPose ?? false ||
|
||||
character.SelectedConstruction?.GetComponent<Ladder>() != null ||
|
||||
(ForceSelectAnimationType != AnimationType.Crouch && ForceSelectAnimationType != AnimationType.NotDefined))
|
||||
{
|
||||
Crouching = false;
|
||||
@@ -422,41 +341,25 @@ namespace Barotrauma
|
||||
midPos += Vector2.Transform(new Vector2(-0.3f * Dir, -0.2f), torsoTransform);
|
||||
|
||||
if (rightHand.PullJointEnabled) midPos = (midPos + rightHand.PullJointWorldAnchorB) / 2.0f;
|
||||
HandIK(rightHand, midPos, CurrentHumanAnimParams.ArmIKStrength, CurrentHumanAnimParams.HandIKStrength);
|
||||
HandIK(leftHand, midPos, CurrentHumanAnimParams.ArmIKStrength, CurrentHumanAnimParams.HandIKStrength);
|
||||
HandIK(rightHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength);
|
||||
HandIK(leftHand, midPos, CurrentAnimationParams.ArmIKStrength, CurrentAnimationParams.HandIKStrength);
|
||||
}
|
||||
else if (character.AnimController.AnimationTestPose)
|
||||
{
|
||||
var leftHand = GetLimb(LimbType.LeftHand);
|
||||
var rightHand = GetLimb(LimbType.RightHand);
|
||||
var waist = GetLimb(LimbType.Waist) ?? GetLimb(LimbType.Torso);
|
||||
rightHand.Disabled = true;
|
||||
leftHand.Disabled = true;
|
||||
Vector2 midPos = waist.SimPosition;
|
||||
HandIK(rightHand, midPos + new Vector2(-1, -0.2f) * Dir);
|
||||
HandIK(leftHand, midPos + new Vector2(1, -0.2f) * Dir);
|
||||
|
||||
var leftFoot = GetLimb(LimbType.LeftFoot);
|
||||
var rightFoot = GetLimb(LimbType.RightFoot);
|
||||
rightFoot.Disabled = true;
|
||||
leftFoot.Disabled = true;
|
||||
// The code here is a bit obscure, but it's pretty much copy-pasted from the block that is used for crouching.
|
||||
for (int i = -1; i < 2; i += 2)
|
||||
{
|
||||
Vector2 footPos = GetColliderBottom();
|
||||
footPos = new Vector2(waist.SimPosition.X + Math.Sign(WalkParams.StepSize.X * i) * Dir * 0.3f, footPos.Y - 0.1f * RagdollParams.JointScale);
|
||||
var foot = i == -1 ? rightFoot : leftFoot;
|
||||
MoveLimb(foot, footPos, Math.Abs(foot.SimPosition.X - footPos.X) * 100.0f, true);
|
||||
}
|
||||
ApplyTestPose();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Anim != Animation.UsingConstruction) ResetPullJoints();
|
||||
if (Anim != Animation.UsingConstruction)
|
||||
{
|
||||
ResetPullJoints();
|
||||
}
|
||||
}
|
||||
|
||||
if (SimplePhysicsEnabled)
|
||||
{
|
||||
UpdateStandingSimple();
|
||||
IsHanging = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -520,12 +423,11 @@ namespace Barotrauma
|
||||
{
|
||||
limb.Disabled = false;
|
||||
}
|
||||
|
||||
wasAiming = aiming;
|
||||
aiming = false;
|
||||
wasAimingMelee = aimingMelee;
|
||||
aimingMelee = false;
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) return;
|
||||
IsHanging = false;
|
||||
}
|
||||
|
||||
void UpdateStanding()
|
||||
@@ -844,16 +746,18 @@ namespace Barotrauma
|
||||
var arm = GetLimb(armType);
|
||||
if (arm != null && Math.Abs(arm.body.AngularVelocity) < 10.0f)
|
||||
{
|
||||
arm.body.SmoothRotate(MathHelper.Clamp(-arm.body.AngularVelocity, -0.1f, 0.1f), arm.Mass * 10.0f);
|
||||
arm.body.SmoothRotate(MathHelper.Clamp(-arm.body.AngularVelocity, -0.5f, 0.5f), arm.Mass * 50.0f);
|
||||
}
|
||||
|
||||
//get the elbow to a neutral rotation
|
||||
if (Math.Abs(hand.body.AngularVelocity) < 10.0f)
|
||||
{
|
||||
LimbJoint elbow = GetJointBetweenLimbs(armType, hand.type) ?? GetJointBetweenLimbs(armType, foreArmType);
|
||||
var forearm = GetLimb(foreArmType) ?? hand;
|
||||
LimbJoint elbow = GetJointBetweenLimbs(armType, foreArmType) ?? GetJointBetweenLimbs(armType, hand.type);
|
||||
if (elbow != null)
|
||||
{
|
||||
hand.body.ApplyTorque(MathHelper.Clamp(-elbow.JointAngle, -MathHelper.PiOver2, MathHelper.PiOver2) * hand.Mass * 10.0f);
|
||||
float diff = elbow.JointAngle - (Dir > 0 ? elbow.LowerLimit : elbow.UpperLimit);
|
||||
forearm.body.ApplyTorque(MathHelper.Clamp(-diff, -MathHelper.PiOver2, MathHelper.PiOver2) * forearm.Mass * 100.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1099,6 +1003,7 @@ namespace Barotrauma
|
||||
rightHandPos.X = (Dir == 1.0f) ? Math.Max(0.3f, rightHandPos.X) : Math.Min(-0.3f, rightHandPos.X);
|
||||
rightHandPos = Vector2.Transform(rightHandPos, rotationMatrix);
|
||||
float speedMultiplier = character.SpeedMultiplier * (1 - Character.GetRightHandPenalty());
|
||||
// Limb hand, Vector2 pos, float force = 1.0f
|
||||
HandIK(rightHand, handPos + rightHandPos, CurrentSwimParams.ArmMoveStrength * speedMultiplier, CurrentSwimParams.HandMoveStrength * speedMultiplier);
|
||||
}
|
||||
|
||||
@@ -1390,6 +1295,8 @@ namespace Barotrauma
|
||||
{
|
||||
target.Oxygen += deltaTime * 0.5f; //Stabilize them
|
||||
}
|
||||
|
||||
bool powerfulCPR = character.HasAbilityFlag(AbilityFlags.PowerfulCPR);
|
||||
|
||||
int skill = (int)character.GetSkillLevel("medical");
|
||||
//pump for 15 seconds (cprAnimTimer 0-15), then do mouth-to-mouth for 2 seconds (cprAnimTimer 15-17)
|
||||
@@ -1406,13 +1313,19 @@ namespace Barotrauma
|
||||
{
|
||||
if (target.Oxygen < -10.0f)
|
||||
{
|
||||
//stabilize the oxygen level but don't allow it to go positive and revive the character yet
|
||||
float stabilizationAmount = skill * CPRSettings.StabilizationPerSkill;
|
||||
stabilizationAmount = MathHelper.Clamp(stabilizationAmount, CPRSettings.StabilizationMin, CPRSettings.StabilizationMax);
|
||||
character.Oxygen -= (1.0f / stabilizationAmount) * deltaTime; //Worse skill = more oxygen required
|
||||
if (character.Oxygen > 0.0f) target.Oxygen += stabilizationAmount * deltaTime; //we didn't suffocate yet did we
|
||||
|
||||
//DebugConsole.NewMessage("CPR Us: " + character.Oxygen + " Them: " + target.Oxygen + " How good we are: restore " + cpr + " use " + (30.0f - cpr), Color.Aqua);
|
||||
if (powerfulCPR)
|
||||
{
|
||||
//prevent the patient from suffocating no matter how fast their oxygen level is dropping
|
||||
target.Oxygen = Math.Max(target.Oxygen, -10.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
//stabilize the oxygen level but don't allow it to go positive and revive the character yet
|
||||
float stabilizationAmount = skill * CPRSettings.StabilizationPerSkill;
|
||||
stabilizationAmount = MathHelper.Clamp(stabilizationAmount, CPRSettings.StabilizationMin, CPRSettings.StabilizationMax);
|
||||
character.Oxygen -= 1.0f / stabilizationAmount * deltaTime; //Worse skill = more oxygen required
|
||||
if (character.Oxygen > 0.0f) { target.Oxygen += stabilizationAmount * deltaTime; } //we didn't suffocate yet did we
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1447,6 +1360,8 @@ namespace Barotrauma
|
||||
reviveChance = (float)Math.Pow(reviveChance, CPRSettings.ReviveChanceExponent);
|
||||
reviveChance = MathHelper.Clamp(reviveChance, CPRSettings.ReviveChanceMin, CPRSettings.ReviveChanceMax);
|
||||
|
||||
if (powerfulCPR) { reviveChance *= 2.0f; }
|
||||
|
||||
if (Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) <= reviveChance)
|
||||
{
|
||||
//increase oxygen and clamp it above zero
|
||||
@@ -1706,248 +1621,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
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.PullJointEnabled = true;
|
||||
pullLimb.PullJointWorldAnchorB = (i == 0) ? rightHandPos : leftHandPos;
|
||||
pullLimb.PullJointMaxForce = 500.0f;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: refactor this method, it's way too convoluted
|
||||
public override void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle, float itemAngleRelativeToHoldAngle = 0.0f, bool aimingMelee = false)
|
||||
{
|
||||
if (character.Stun > 0.0f || character.IsIncapacitated)
|
||||
{
|
||||
aim = false;
|
||||
}
|
||||
|
||||
//calculate the handle positions
|
||||
Matrix itemTransfrom = Matrix.CreateRotationZ(item.body.Rotation);
|
||||
// TODO: don't create new arrays, reuse
|
||||
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);
|
||||
|
||||
// TODO: Remove this. Provide the position in params.
|
||||
Vector2 itemPos = aim ? aimPos : holdPos;
|
||||
|
||||
var controller = character.SelectedConstruction?.GetComponent<Controller>();
|
||||
bool usingController = controller != null && !controller.AllowAiming;
|
||||
bool isClimbing = character.IsClimbing && Math.Abs(character.AnimController.TargetMovement.Y) > 0.01f;
|
||||
|
||||
float itemAngle;
|
||||
|
||||
Holdable holdable = item.GetComponent<Holdable>();
|
||||
|
||||
this.aimingMelee = aimingMelee;
|
||||
|
||||
if (!isClimbing && !usingController && character.Stun <= 0.0f && aim && itemPos != Vector2.Zero && !character.IsIncapacitated)
|
||||
{
|
||||
Vector2 mousePos = ConvertUnits.ToSimUnits(character.SmoothedCursorPosition);
|
||||
|
||||
Vector2 diff = holdable.Aimable ? (mousePos - AimSourceSimPos) * Dir : Vector2.UnitX;
|
||||
|
||||
holdAngle = MathUtils.VectorToAngle(new Vector2(diff.X, diff.Y * Dir)) - torso.body.Rotation * Dir;
|
||||
holdAngle += GetAimWobble(rightHand, leftHand, item);
|
||||
|
||||
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 transformedHoldPos = rightShoulder.WorldAnchorA;
|
||||
if (itemPos == Vector2.Zero || isClimbing || usingController)
|
||||
{
|
||||
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == item)
|
||||
{
|
||||
if (rightHand == null || rightHand.IsSevered) { return; }
|
||||
transformedHoldPos = rightHand.PullJointWorldAnchorA - transformedHandlePos[0];
|
||||
itemAngle = (rightHand.Rotation + (holdAngle - MathHelper.PiOver2) * Dir);
|
||||
}
|
||||
else if (character.Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand) == item)
|
||||
{
|
||||
if (leftHand == null || leftHand.IsSevered) { return; }
|
||||
transformedHoldPos = leftHand.PullJointWorldAnchorA - transformedHandlePos[1];
|
||||
itemAngle = (leftHand.Rotation + (holdAngle - MathHelper.PiOver2) * Dir);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == item)
|
||||
{
|
||||
if (rightHand == null || rightHand.IsSevered) { return; }
|
||||
transformedHoldPos = rightShoulder.WorldAnchorA;
|
||||
rightHand.Disabled = true;
|
||||
}
|
||||
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand) == item)
|
||||
{
|
||||
if (leftHand == null || leftHand.IsSevered) { return; }
|
||||
transformedHoldPos = leftShoulder.WorldAnchorA;
|
||||
leftHand.Disabled = true;
|
||||
}
|
||||
|
||||
itemPos.X *= Dir;
|
||||
transformedHoldPos += Vector2.Transform(itemPos, Matrix.CreateRotationZ(itemAngle));
|
||||
}
|
||||
|
||||
item.body.ResetDynamics();
|
||||
|
||||
Vector2 currItemPos = (character.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == item) ?
|
||||
rightHand.PullJointWorldAnchorA - transformedHandlePos[0] :
|
||||
leftHand.PullJointWorldAnchorA - transformedHandlePos[1];
|
||||
|
||||
if (!MathUtils.IsValid(currItemPos))
|
||||
{
|
||||
string errorMsg = "Attempted to move the item \"" + item + "\" to an invalid position in HumanidAnimController.HoldItem: " +
|
||||
currItemPos + ", rightHandPos: " + rightHand.PullJointWorldAnchorA + ", leftHandPos: " + leftHand.PullJointWorldAnchorA +
|
||||
", handlePos[0]: " + handlePos[0] + ", handlePos[1]: " + handlePos[1] +
|
||||
", transformedHandlePos[0]: " + transformedHandlePos[0] + ", transformedHandlePos[1]:" + transformedHandlePos[1] +
|
||||
", item pos: " + item.SimPosition + ", itemAngle: " + itemAngle +
|
||||
", collider pos: " + character.SimPosition;
|
||||
DebugConsole.Log(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"HumanoidAnimController.HoldItem:InvalidPos:" + character.Name + item.Name,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
errorMsg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (holdable.Pusher != null)
|
||||
{
|
||||
if (character.Stun > 0.0f || character.IsIncapacitated)
|
||||
{
|
||||
holdable.Pusher.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!holdable.Pusher.Enabled)
|
||||
{
|
||||
holdable.Pusher.Enabled = true;
|
||||
holdable.Pusher.ResetDynamics();
|
||||
holdable.Pusher.SetTransform(currItemPos, itemAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
holdable.Pusher.TargetPosition = currItemPos;
|
||||
holdable.Pusher.TargetRotation = holdAngle * Dir;
|
||||
|
||||
holdable.Pusher.MoveToTargetPosition(true);
|
||||
|
||||
currItemPos = holdable.Pusher.SimPosition;
|
||||
itemAngle = holdable.Pusher.Rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.SetTransform(currItemPos, itemAngle + itemAngleRelativeToHoldAngle * Dir, setPrevTransform: false);
|
||||
|
||||
if (!isClimbing && !character.IsIncapacitated && itemPos != Vector2.Zero)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (!character.Inventory.IsInLimbSlot(item, i == 0 ? InvSlotType.RightHand : InvSlotType.LeftHand)) { continue; }
|
||||
HandIK(i == 0 ? rightHand : leftHand, transformedHoldPos + transformedHandlePos[i], CurrentHumanAnimParams.ArmIKStrength, CurrentHumanAnimParams.HandIKStrength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float GetAimWobble(Limb rightHand, Limb leftHand, Item heldItem)
|
||||
{
|
||||
float wobbleStrength = 0.0f;
|
||||
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == heldItem)
|
||||
{
|
||||
wobbleStrength += Character.CharacterHealth.GetLimbDamage(rightHand, afflictionType: "damage");
|
||||
}
|
||||
if (character.Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand) == heldItem)
|
||||
{
|
||||
wobbleStrength += Character.CharacterHealth.GetLimbDamage(leftHand, afflictionType: "damage");
|
||||
}
|
||||
if (wobbleStrength <= 0.1f) { return 0.0f; }
|
||||
wobbleStrength = (float)Math.Min(wobbleStrength, 1.0f);
|
||||
|
||||
float lowFreqNoise = PerlinNoise.GetPerlin((float)Timing.TotalTime / 320.0f, (float)Timing.TotalTime / 240.0f) - 0.5f;
|
||||
float highFreqNoise = PerlinNoise.GetPerlin((float)Timing.TotalTime / 40.0f, (float)Timing.TotalTime / 50.0f) - 0.5f;
|
||||
|
||||
return (lowFreqNoise * 1.0f + highFreqNoise * 0.1f) * wobbleStrength;
|
||||
}
|
||||
|
||||
private void HandIK(Limb hand, Vector2 pos, float armTorque = 1.0f, float handTorque = 1.0f)
|
||||
{
|
||||
Vector2 shoulderPos;
|
||||
|
||||
Limb arm, forearm;
|
||||
if (hand.type == LimbType.LeftHand)
|
||||
{
|
||||
if (leftShoulder == null) { return; }
|
||||
shoulderPos = leftShoulder.WorldAnchorA;
|
||||
arm = GetLimb(LimbType.LeftArm);
|
||||
forearm = GetLimb(LimbType.LeftForearm);
|
||||
LeftHandIKPos = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rightShoulder == null) { return; }
|
||||
shoulderPos = rightShoulder.WorldAnchorA;
|
||||
arm = GetLimb(LimbType.RightArm);
|
||||
forearm = GetLimb(LimbType.RightForearm);
|
||||
RightHandIKPos = pos;
|
||||
}
|
||||
if (arm == null) { return; }
|
||||
|
||||
//distance from shoulder to holdpos
|
||||
float c = Vector2.Distance(pos, shoulderPos);
|
||||
c = MathHelper.Clamp(c, Math.Abs(upperArmLength - forearmLength), forearmLength + upperArmLength - 0.01f);
|
||||
|
||||
float armAngle = MathUtils.VectorToAngle(pos - shoulderPos) + MathHelper.PiOver2;
|
||||
|
||||
float upperArmAngle = MathUtils.SolveTriangleSSS(forearmLength, upperArmLength, c) * Dir;
|
||||
float lowerArmAngle = MathUtils.SolveTriangleSSS(upperArmLength, forearmLength, c) * Dir;
|
||||
|
||||
//make sure the arm angle "has the same number of revolutions" as the arm
|
||||
while (arm.Rotation - armAngle > MathHelper.Pi)
|
||||
{
|
||||
armAngle += MathHelper.TwoPi;
|
||||
}
|
||||
while (arm.Rotation - armAngle < -MathHelper.Pi)
|
||||
{
|
||||
armAngle -= MathHelper.TwoPi;
|
||||
}
|
||||
|
||||
arm?.body.SmoothRotate(armAngle - upperArmAngle, 100.0f * armTorque * arm.Mass, wrapAngle: false);
|
||||
float forearmAngle = armAngle + lowerArmAngle;
|
||||
forearm?.body.SmoothRotate(forearmAngle, 100.0f * handTorque * forearm.Mass, wrapAngle: false);
|
||||
float handAngle = forearm != null ? armAngle : forearmAngle;
|
||||
hand?.body.SmoothRotate(handAngle, 100.0f * handTorque * hand.Mass, wrapAngle: false);
|
||||
}
|
||||
|
||||
private void FootIK(Limb foot, Vector2 pos, float legTorque, float footTorque, float footAngle)
|
||||
{
|
||||
if (!MathUtils.IsValid(pos))
|
||||
@@ -2014,47 +1687,6 @@ namespace Barotrauma
|
||||
foot.body.SmoothRotate((legAngle - (lowerLegAngle + footAngle) * Dir), foot.Mass * footTorque, wrapAngle: false);
|
||||
}
|
||||
|
||||
public override void UpdateUseItem(bool allowMovement, Vector2 handWorldPos)
|
||||
{
|
||||
useItemTimer = 0.5f;
|
||||
Anim = Animation.UsingConstruction;
|
||||
|
||||
if (!allowMovement)
|
||||
{
|
||||
TargetMovement = Vector2.Zero;
|
||||
TargetDir = handWorldPos.X > character.WorldPosition.X ? Direction.Right : Direction.Left;
|
||||
float sqrDist = Vector2.DistanceSquared(character.WorldPosition, handWorldPos);
|
||||
if (sqrDist > MathUtils.Pow(ConvertUnits.ToDisplayUnits(upperArmLength + forearmLength), 2))
|
||||
{
|
||||
TargetMovement = Vector2.Normalize(handWorldPos - character.WorldPosition) * GetCurrentSpeed(false) * Math.Max(character.SpeedMultiplier, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!character.Enabled) { return; }
|
||||
|
||||
Vector2 handSimPos = ConvertUnits.ToSimUnits(handWorldPos);
|
||||
if (character.Submarine != null)
|
||||
{
|
||||
handSimPos -= character.Submarine.SimPosition;
|
||||
}
|
||||
|
||||
var leftHand = GetLimb(LimbType.LeftHand);
|
||||
if (leftHand != null)
|
||||
{
|
||||
leftHand.Disabled = true;
|
||||
leftHand.PullJointEnabled = true;
|
||||
leftHand.PullJointWorldAnchorB = handSimPos;
|
||||
}
|
||||
|
||||
var rightHand = GetLimb(LimbType.RightHand);
|
||||
if (rightHand != null)
|
||||
{
|
||||
rightHand.Disabled = true;
|
||||
rightHand.PullJointEnabled = true;
|
||||
rightHand.PullJointWorldAnchorB = handSimPos;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flip()
|
||||
{
|
||||
base.Flip();
|
||||
@@ -2073,7 +1705,8 @@ namespace Barotrauma
|
||||
{
|
||||
heldItem.FlipX(relativeToSub: false);
|
||||
}
|
||||
heldItem.FlipX(relativeToSub: false);
|
||||
// TODO: was this added by a mistake?
|
||||
//heldItem.FlipX(relativeToSub: false);
|
||||
}
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
|
||||
@@ -125,7 +125,8 @@ namespace Barotrauma
|
||||
protected float surfaceY;
|
||||
|
||||
protected bool inWater, headInWater;
|
||||
public bool onGround;
|
||||
protected bool onGround;
|
||||
public bool OnGround => onGround;
|
||||
private Vector2 lastFloorCheckPos;
|
||||
private bool lastFloorCheckIgnoreStairs, lastFloorCheckIgnorePlatforms;
|
||||
|
||||
@@ -887,7 +888,7 @@ namespace Barotrauma
|
||||
|
||||
|
||||
/// <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)
|
||||
public void MoveLimb(Limb limb, Vector2 pos, float amount, bool pullFromCenter = false)
|
||||
{
|
||||
limb.MoveToPos(pos, amount, pullFromCenter);
|
||||
}
|
||||
@@ -974,8 +975,7 @@ namespace Barotrauma
|
||||
Vector2 newSubPos = newHull.Submarine == null ? Vector2.Zero : newHull.Submarine.Position;
|
||||
Vector2 prevSubPos = currentHull.Submarine == null ? Vector2.Zero : currentHull.Submarine.Position;
|
||||
|
||||
Teleport(ConvertUnits.ToSimUnits(prevSubPos - newSubPos),
|
||||
Vector2.Zero);
|
||||
Teleport(ConvertUnits.ToSimUnits(prevSubPos - newSubPos), Vector2.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1099,6 +1099,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public bool forceStanding;
|
||||
public bool forceNotStanding;
|
||||
|
||||
public void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
@@ -1270,6 +1271,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
UpdateProjSpecific(deltaTime, cam);
|
||||
forceNotStanding = false;
|
||||
}
|
||||
|
||||
private void CheckBodyInRest(float deltaTime)
|
||||
@@ -1569,7 +1571,7 @@ namespace Barotrauma
|
||||
return closestFraction;
|
||||
}, rayStart, rayEnd, Physics.CollisionStairs | Physics.CollisionPlatform | Physics.CollisionWall | Physics.CollisionLevel);
|
||||
|
||||
if (standOnFloorFixture != null)
|
||||
if (standOnFloorFixture != null && !IsHanging)
|
||||
{
|
||||
standOnFloorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * standOnFloorFraction;
|
||||
if (rayStart.Y - standOnFloorY < Collider.height * 0.5f + Collider.radius + ColliderHeightFromFloor * 1.2f)
|
||||
@@ -1606,6 +1608,13 @@ namespace Barotrauma
|
||||
}
|
||||
if (MainLimb == null) { return; }
|
||||
|
||||
if (Character.AIController is EnemyAIController enemyAI && enemyAI.LatchOntoAI != null && enemyAI.LatchOntoAI.IsAttached)
|
||||
{
|
||||
enemyAI.LatchOntoAI.DeattachFromBody(reset: true);
|
||||
}
|
||||
Character.Latchers.ForEachMod(l => l.DeattachFromBody(reset: true));
|
||||
Character.Latchers.Clear();
|
||||
|
||||
Vector2 limbMoveAmount = forceMainLimbToCollider ? simPosition - MainLimb.SimPosition : simPosition - Collider.SimPosition;
|
||||
if (lerp)
|
||||
{
|
||||
@@ -1629,6 +1638,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsHanging { get; protected set; }
|
||||
|
||||
public void Hang()
|
||||
{
|
||||
ResetPullJoints();
|
||||
onGround = false;
|
||||
levitatingCollider = false;
|
||||
IsHanging = true;
|
||||
}
|
||||
|
||||
protected void TrySetLimbPosition(Limb limb, Vector2 original, Vector2 simPosition, bool lerp = false, bool ignorePlatforms = true)
|
||||
{
|
||||
Vector2 movePos = simPosition;
|
||||
|
||||
Reference in New Issue
Block a user