2f107db...5202af9
This commit is contained in:
@@ -131,22 +131,22 @@ namespace Barotrauma
|
||||
{
|
||||
if (Frozen) return;
|
||||
if (MainLimb == null) { return; }
|
||||
|
||||
if (character.IsDead || character.IsUnconscious || character.Stun > 0.0f)
|
||||
|
||||
if (!character.AllowInput)
|
||||
{
|
||||
Collider.Enabled = false;
|
||||
levitatingCollider = false;
|
||||
Collider.FarseerBody.FixedRotation = false;
|
||||
//set linear velocity even though the collider is disabled,
|
||||
//because the character won't be able to switch back from ragdoll mode until the velocity of the collider is low enough
|
||||
Collider.LinearVelocity = MainLimb.LinearVelocity;
|
||||
Collider.SetTransformIgnoreContacts(MainLimb.SimPosition, MainLimb.Rotation);
|
||||
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
Collider.LinearVelocity = MainLimb.LinearVelocity;
|
||||
Collider.FarseerBody.FixedRotation = false;
|
||||
Collider.SetTransformIgnoreContacts(MainLimb.SimPosition, MainLimb.Rotation);
|
||||
}
|
||||
if (character.IsDead && deathAnimTimer < deathAnimDuration)
|
||||
{
|
||||
deathAnimTimer += deltaTime;
|
||||
UpdateDying(deltaTime);
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -266,6 +266,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanDrag(Character target)
|
||||
{
|
||||
return Mass / target.Mass > 0.1f;
|
||||
}
|
||||
|
||||
private float eatTimer = 0.0f;
|
||||
|
||||
public override void DragCharacter(Character target, float deltaTime)
|
||||
@@ -294,9 +299,12 @@ namespace Barotrauma
|
||||
{
|
||||
//pull the target character to the position of the mouth
|
||||
//(+ make the force fluctuate to waggle the character a bit)
|
||||
targetCharacter.AnimController.MainLimb.MoveToPos(mouthPos, (float)(Math.Sin(eatTimer) + 10.0f));
|
||||
targetCharacter.AnimController.MainLimb.body.SmoothRotate(mouthLimb.Rotation);
|
||||
targetCharacter.AnimController.Collider.MoveToPos(mouthPos, (float)(Math.Sin(eatTimer) + 10.0f));
|
||||
if (CanDrag(target))
|
||||
{
|
||||
targetCharacter.AnimController.MainLimb.MoveToPos(mouthPos, (float)(Math.Sin(eatTimer) + 10.0f));
|
||||
targetCharacter.AnimController.MainLimb.body.SmoothRotate(mouthLimb.Rotation, 20.0f);
|
||||
targetCharacter.AnimController.Collider.MoveToPos(mouthPos, (float)(Math.Sin(eatTimer) + 10.0f));
|
||||
}
|
||||
|
||||
//pull the character's mouth to the target character (again with a fluctuating force)
|
||||
float pullStrength = (float)(Math.Sin(eatTimer) * Math.Max(Math.Sin(eatTimer * 0.5f), 0.0f));
|
||||
@@ -496,7 +504,7 @@ namespace Barotrauma
|
||||
Vector2 colliderBottom = GetColliderBottom();
|
||||
|
||||
float movementAngle = 0.0f;
|
||||
float mainLimbAngle = (MainLimb.type == LimbType.Torso ? TorsoAngle.Value : HeadAngle.Value) * Dir;
|
||||
float mainLimbAngle = (MainLimb.type == LimbType.Torso ? TorsoAngle ?? 0 : HeadAngle ?? 0) * Dir;
|
||||
while (MainLimb.Rotation - (movementAngle + mainLimbAngle) > MathHelper.Pi)
|
||||
{
|
||||
movementAngle += MathHelper.TwoPi;
|
||||
@@ -669,6 +677,8 @@ namespace Barotrauma
|
||||
|
||||
limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength);
|
||||
}
|
||||
|
||||
limb?.body.SmoothRotate(angle, torque, wrapAngle: false);
|
||||
}
|
||||
|
||||
private void SmoothRotateWithoutWrapping(Limb limb, float angle, Limb referenceLimb, float torque)
|
||||
@@ -707,8 +717,17 @@ namespace Barotrauma
|
||||
centerOfMass,
|
||||
new Vector2(centerOfMass.X - (l.SimPosition.X - centerOfMass.X), l.SimPosition.Y),
|
||||
true);
|
||||
l.body.PositionSmoothingFactor = 0.8f;
|
||||
}
|
||||
}
|
||||
|
||||
if (character.SelectedCharacter != null && CanDrag(character.SelectedCharacter))
|
||||
{
|
||||
float diff = character.SelectedCharacter.SimPosition.X - centerOfMass.X;
|
||||
if (diff < 100.0f)
|
||||
{
|
||||
character.SelectedCharacter.AnimController.SetPosition(
|
||||
new Vector2(centerOfMass.X - diff, character.SelectedCharacter.SimPosition.Y), lerp: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,10 +341,13 @@ namespace Barotrauma
|
||||
if (!character.AllowInput)
|
||||
{
|
||||
levitatingCollider = false;
|
||||
Collider.Enabled = false;
|
||||
Collider.LinearVelocity = MainLimb.LinearVelocity;
|
||||
Collider.FarseerBody.FixedRotation = false;
|
||||
Collider.SetTransformIgnoreContacts(MainLimb.SimPosition, MainLimb.Rotation);
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
Collider.Enabled = false;
|
||||
Collider.LinearVelocity = MainLimb.LinearVelocity;
|
||||
Collider.SetTransformIgnoreContacts(MainLimb.SimPosition, MainLimb.Rotation);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -498,7 +501,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
aiming = false;
|
||||
if (character.IsRemotePlayer && GameMain.Server == null) Collider.LinearVelocity = Vector2.Zero;
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) return;
|
||||
}
|
||||
|
||||
void UpdateStanding()
|
||||
@@ -569,8 +572,11 @@ namespace Barotrauma
|
||||
movement.Y = 0.0f;
|
||||
|
||||
if (torso == null) { return; }
|
||||
|
||||
bool isNotRemote = true;
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) isNotRemote = !character.IsRemotePlayer;
|
||||
|
||||
if (onGround && (!character.IsRemotePlayer || GameMain.Server != null))
|
||||
if (onGround && isNotRemote)
|
||||
{
|
||||
//move slower if collider isn't upright
|
||||
float rotationFactor = (float)Math.Abs(Math.Cos(Collider.Rotation));
|
||||
@@ -783,7 +789,7 @@ namespace Barotrauma
|
||||
{
|
||||
Collider.LinearVelocity = movement;
|
||||
}
|
||||
else if (onGround && (!character.IsRemotePlayer || GameMain.Server != null))
|
||||
else if (onGround && (!character.IsRemotePlayer || (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)))
|
||||
{
|
||||
Collider.LinearVelocity = new Vector2(
|
||||
movement.X,
|
||||
@@ -976,7 +982,10 @@ namespace Barotrauma
|
||||
movement.Y = movement.Y - (surfaceLimiter - 1.0f) * 0.01f;
|
||||
}
|
||||
|
||||
if (!character.IsRemotePlayer || GameMain.Server != null)
|
||||
bool isNotRemote = true;
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) isNotRemote = !character.IsRemotePlayer;
|
||||
|
||||
if (isNotRemote)
|
||||
{
|
||||
Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement, movementLerp);
|
||||
}
|
||||
@@ -1165,7 +1174,11 @@ namespace Barotrauma
|
||||
trigger = character.SelectedConstruction.TransformTrigger(trigger);
|
||||
|
||||
bool notClimbing = false;
|
||||
if (character.IsRemotePlayer && GameMain.Server == null)
|
||||
|
||||
bool isNotRemote = true;
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) isNotRemote = !character.IsRemotePlayer;
|
||||
|
||||
if (isNotRemote)
|
||||
{
|
||||
notClimbing = character.IsKeyDown(InputType.Left) || character.IsKeyDown(InputType.Right);
|
||||
}
|
||||
@@ -1263,9 +1276,9 @@ namespace Barotrauma
|
||||
|
||||
bool wasCritical = target.Vitality < 0.0f;
|
||||
|
||||
if (GameMain.Client == null) //Serverside code
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) //Serverside code
|
||||
{
|
||||
target.Oxygen += deltaTime * 0.5f; //Stabilize them
|
||||
target.Oxygen += deltaTime * 0.5f; //Stabilize them
|
||||
}
|
||||
|
||||
int skill = (int)character.GetSkillLevel("medical");
|
||||
@@ -1279,15 +1292,18 @@ namespace Barotrauma
|
||||
torso.PullJointEnabled = true;
|
||||
|
||||
//Serverside code
|
||||
if (GameMain.Client == null && target.Oxygen < -10.0f)
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
//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
|
||||
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);
|
||||
//DebugConsole.NewMessage("CPR Us: " + character.Oxygen + " Them: " + target.Oxygen + " How good we are: restore " + cpr + " use " + (30.0f - cpr), Color.Aqua);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1319,7 +1335,7 @@ namespace Barotrauma
|
||||
},
|
||||
0.0f, true, 0.0f, character);
|
||||
}
|
||||
if (GameMain.Client == null) //Serverside code
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) //Serverside code
|
||||
{
|
||||
float reviveChance = skill * CPRSettings.ReviveChancePerSkill;
|
||||
reviveChance = (float)Math.Pow(reviveChance, CPRSettings.ReviveChanceExponent);
|
||||
@@ -1330,7 +1346,7 @@ namespace Barotrauma
|
||||
//increase oxygen and clamp it above zero
|
||||
// -> the character should be revived if there are no major afflictions in addition to lack of oxygen
|
||||
target.Oxygen = Math.Max(target.Oxygen + 10.0f, 10.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cprPump += deltaTime;
|
||||
@@ -1380,7 +1396,7 @@ namespace Barotrauma
|
||||
if (Anim == Animation.Climbing)
|
||||
{
|
||||
//cannot drag up ladders if the character is conscious
|
||||
if (target.AllowInput && GameMain.Client == null)
|
||||
if (target.AllowInput && (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient))
|
||||
{
|
||||
character.DeselectCharacter();
|
||||
return;
|
||||
@@ -1459,7 +1475,7 @@ namespace Barotrauma
|
||||
|
||||
Limb pullLimb = i == 0 ? leftHand : rightHand;
|
||||
|
||||
if (GameMain.Client == null)
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
//stop dragging if there's something between the pull limb and the target limb
|
||||
Vector2 sourceSimPos = pullLimb.SimPosition;
|
||||
@@ -1541,7 +1557,7 @@ namespace Barotrauma
|
||||
|
||||
float dist = ConvertUnits.ToSimUnits(Vector2.Distance(target.WorldPosition, WorldPosition));
|
||||
//let the target break free if it's moving away and gets far enough
|
||||
if (GameMain.Client == null && dist > 1.4f && target.AllowInput &&
|
||||
if ((GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) && dist > 1.4f && target.AllowInput &&
|
||||
Vector2.Dot(target.WorldPosition - WorldPosition, target.AnimController.TargetMovement) > 0)
|
||||
{
|
||||
character.DeselectCharacter();
|
||||
@@ -1609,7 +1625,7 @@ namespace Barotrauma
|
||||
|
||||
if (Anim != Animation.Climbing && !usingController && character.Stun <= 0.0f && aim && itemPos != Vector2.Zero)
|
||||
{
|
||||
Vector2 mousePos = ConvertUnits.ToSimUnits(character.CursorPosition);
|
||||
Vector2 mousePos = ConvertUnits.ToSimUnits(character.SmoothedCursorPosition);
|
||||
|
||||
Vector2 diff = holdable.Aimable ? (mousePos - AimSourceSimPos) * Dir : Vector2.UnitX;
|
||||
|
||||
@@ -1872,15 +1888,16 @@ namespace Barotrauma
|
||||
|
||||
for (int i = 0; i < character.SelectedItems.Length; i++)
|
||||
{
|
||||
if (character.SelectedItems[i] != null && character.SelectedItems[i].body != null)
|
||||
if (i == 1 && character.SelectedItems[0] == character.SelectedItems[1])
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (character.SelectedItems[i]?.body != null && !character.SelectedItems[i].Removed)
|
||||
{
|
||||
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));
|
||||
character.SelectedItems[i].body.SimPosition,
|
||||
MathUtils.WrapAngleTwoPi(character.SelectedItems[i].body.Rotation + MathHelper.Pi));
|
||||
character.SelectedItems[i].GetComponent<Holdable>()?.Flip();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1898,7 +1915,6 @@ namespace Barotrauma
|
||||
case LimbType.RightHand:
|
||||
case LimbType.RightArm:
|
||||
case LimbType.RightForearm:
|
||||
mirror = true;
|
||||
flipAngle = true;
|
||||
break;
|
||||
case LimbType.LeftThigh:
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class HumanoidAnimParams : ISerializableEntity
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public HumanoidAnimParams(string file)
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file);
|
||||
if (doc == null || doc.Root == null) return;
|
||||
|
||||
Name = doc.Root.Name.ToString();
|
||||
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, doc.Root);
|
||||
}
|
||||
|
||||
[Serialize(0.3f, true), Editable]
|
||||
public float GetUpSpeed
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(1.54f, true), Editable]
|
||||
public float HeadPosition
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(1.15f, true), Editable]
|
||||
public float TorsoPosition
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize(0.25f, true), Editable]
|
||||
public float HeadLeanAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(0.25f, true), Editable]
|
||||
public float TorsoLeanAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(5.0f, true), Editable]
|
||||
public float CycleSpeed
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(15.0f, true), Editable]
|
||||
public float FootMoveStrength
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
[Serialize(20.0f, true), Editable]
|
||||
public float FootRotateStrength
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize("0.4,0.12", true), Editable]
|
||||
public Vector2 StepSize
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("0.0, 0.0", true), Editable]
|
||||
public Vector2 FootMoveOffset
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(10.0f, true), Editable]
|
||||
public float LegCorrectionTorque
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(15.0f, true), Editable]
|
||||
public float ThighCorrectionTorque
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("0.4, 0.15", true), Editable]
|
||||
public Vector2 HandMoveAmount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("-0.15, 0.0", true), Editable]
|
||||
public Vector2 HandMoveOffset
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(0.7f, true), Editable]
|
||||
public float HandMoveStrength
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(-1.0f, true), Editable]
|
||||
public float HandClampY
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -97,7 +97,7 @@ namespace Barotrauma
|
||||
|
||||
public static string GetDefaultFileName(string speciesName, AnimationType animType) => $"{speciesName.CapitaliseFirstInvariant()}{animType.ToString()}";
|
||||
public static string GetDefaultFolder(string speciesName) => $"Content/Characters/{speciesName.CapitaliseFirstInvariant()}/Animations/";
|
||||
public static string GetDefaultFile(string speciesName, AnimationType animType) => $"{GetDefaultFolder(speciesName)}{GetDefaultFileName(speciesName, animType)}.xml";
|
||||
public static string GetDefaultFile(string speciesName, AnimationType animType) => $"{GetFolder(speciesName)}{GetDefaultFileName(speciesName, animType)}.xml";
|
||||
|
||||
protected static string GetFolder(string speciesName)
|
||||
{
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@ namespace Barotrauma
|
||||
|
||||
public static string GetDefaultFileName(string speciesName) => $"{speciesName.CapitaliseFirstInvariant()}DefaultRagdoll";
|
||||
public static string GetDefaultFolder(string speciesName) => $"Content/Characters/{speciesName.CapitaliseFirstInvariant()}/Ragdolls/";
|
||||
public static string GetDefaultFile(string speciesName) => $"{GetDefaultFolder(speciesName)}{GetDefaultFileName(speciesName)}.xml";
|
||||
public static string GetDefaultFile(string speciesName) => $"{GetFolder(speciesName)}{GetDefaultFileName(speciesName)}.xml";
|
||||
|
||||
private static readonly object[] dummyParams = new object[]
|
||||
{
|
||||
@@ -662,7 +662,7 @@ namespace Barotrauma
|
||||
public SerializableEntityEditor SerializableEntityEditor { get; protected set; }
|
||||
public virtual void AddToEditor(ParamsEditor editor)
|
||||
{
|
||||
SerializableEntityEditor = new SerializableEntityEditor(editor.EditorBox.Content.RectTransform, this, false, true);
|
||||
SerializableEntityEditor = new SerializableEntityEditor(editor.EditorBox.Content.RectTransform, this, inGame: false, showName: true);
|
||||
SubParams.ForEach(sp => sp.AddToEditor(editor));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -314,16 +314,16 @@ namespace Barotrauma
|
||||
{
|
||||
if (!PhysicsBody.IsValidShape(limbParams.Radius, limbParams.Height, limbParams.Width))
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot create the ragdoll: invalid collider dimensions on limb: " + limbParams.Name);
|
||||
return;
|
||||
DebugConsole.ThrowError($"Invalid collider dimensions (r: {limbParams.Radius}, h: {limbParams.Height}, w: {limbParams.Width}) on limb: {limbParams.Name}. Fixing.");
|
||||
limbParams.Radius = 10;
|
||||
}
|
||||
}
|
||||
foreach (var colliderParams in RagdollParams.ColliderParams)
|
||||
{
|
||||
if (!PhysicsBody.IsValidShape(colliderParams.Radius, colliderParams.Height, colliderParams.Width))
|
||||
{
|
||||
DebugConsole.ThrowError("Cannot create the ragdoll: invalid collider dimensions on collider: " + colliderParams.Name);
|
||||
return;
|
||||
DebugConsole.ThrowError($"Invalid collider dimensions (r: {colliderParams.Radius}, h: {colliderParams.Height}, w: {colliderParams.Width}) on collider: {colliderParams.Name}. Fixing.");
|
||||
colliderParams.Radius = 10;
|
||||
}
|
||||
}
|
||||
CreateColliders();
|
||||
@@ -335,11 +335,21 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var kvp in items)
|
||||
{
|
||||
var limb = limbs[kvp.Key.ID];
|
||||
int id = kvp.Key.ID;
|
||||
// This can be the case if we manipulate the ragdoll in runtime (husk appendage, limb severance)
|
||||
if (id > limbs.Length - 1) { continue; }
|
||||
var limb = limbs[id];
|
||||
var itemList = kvp.Value;
|
||||
limb.WearingItems.AddRange(itemList);
|
||||
}
|
||||
}
|
||||
if (character.SpeciesName.ToLowerInvariant() == "humanhusk")
|
||||
{
|
||||
if (Limbs.None(l => l.Name.ToLowerInvariant() == "huskappendage"))
|
||||
{
|
||||
AfflictionHusk.AttachHuskAppendage(character, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Ragdoll(Character character, string seed, RagdollParams ragdollParams = null)
|
||||
@@ -431,12 +441,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
partial void SetupDrawOrder();
|
||||
|
||||
/// <summary>
|
||||
/// Inversed draw order, which is used for drawing the limbs in 3d (deformable sprites).
|
||||
/// </summary>
|
||||
protected Limb[] inversedLimbDrawOrder;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves all serializable data in the currently selected ragdoll params. This method should properly handle character flipping.
|
||||
/// </summary>
|
||||
@@ -495,9 +500,7 @@ namespace Barotrauma
|
||||
|
||||
public void AddJoint(JointParams jointParams)
|
||||
{
|
||||
byte limb1ID = Convert.ToByte(jointParams.Limb1);
|
||||
byte limb2ID = Convert.ToByte(jointParams.Limb2);
|
||||
LimbJoint joint = new LimbJoint(Limbs[limb1ID], Limbs[limb2ID], jointParams, this);
|
||||
LimbJoint joint = new LimbJoint(Limbs[jointParams.Limb1], Limbs[jointParams.Limb2], jointParams, this);
|
||||
GameMain.World.AddJoint(joint);
|
||||
for (int i = 0; i < LimbJoints.Length; i++)
|
||||
{
|
||||
@@ -509,11 +512,6 @@ namespace Barotrauma
|
||||
LimbJoints[LimbJoints.Length - 1] = joint;
|
||||
}
|
||||
|
||||
public void AddJoint(XElement subElement, float scale = 1.0f)
|
||||
{
|
||||
AddJoint(new JointParams(subElement, RagdollParams));
|
||||
}
|
||||
|
||||
protected void AddLimb(LimbParams limbParams)
|
||||
{
|
||||
byte ID = Convert.ToByte(limbParams.ID);
|
||||
@@ -591,7 +589,6 @@ namespace Barotrauma
|
||||
|
||||
public bool OnLimbCollision(Fixture f1, Fixture f2, Contact contact)
|
||||
{
|
||||
Structure structure = f2.Body.UserData as Structure;
|
||||
|
||||
if (f2.Body.UserData is Submarine && character.Submarine == (Submarine)f2.Body.UserData) return false;
|
||||
|
||||
@@ -599,7 +596,7 @@ namespace Barotrauma
|
||||
if (f2.Body.UserData as string == "blocker" && f2.Body != outsideCollisionBlocker) return false;
|
||||
|
||||
//always collides with bodies other than structures
|
||||
if (structure == null)
|
||||
if (!(f2.Body.UserData is Structure structure))
|
||||
{
|
||||
CalculateImpact(f1, f2, contact);
|
||||
return true;
|
||||
@@ -635,8 +632,7 @@ namespace Barotrauma
|
||||
if (contact.Manifold.LocalNormal.Y < 0.0f) 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);
|
||||
contact.GetWorldManifold(out Vector2 normal, out FarseerPhysics.Common.FixedArray2<Vector2> points);
|
||||
if (points[0].Y > Collider.SimPosition.Y) return false;
|
||||
|
||||
//5. in water
|
||||
@@ -671,7 +667,10 @@ namespace Barotrauma
|
||||
float impact = Vector2.Dot(velocity, -normal);
|
||||
if (f1.Body == Collider.FarseerBody)
|
||||
{
|
||||
if (!character.IsRemotePlayer || GameMain.Server != null)
|
||||
bool isNotRemote = true;
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) isNotRemote = !character.IsRemotePlayer;
|
||||
|
||||
if (isNotRemote)
|
||||
{
|
||||
if (impact > ImpactTolerance)
|
||||
{
|
||||
@@ -689,7 +688,7 @@ namespace Barotrauma
|
||||
|
||||
ImpactProjSpecific(impact, f1.Body);
|
||||
}
|
||||
|
||||
|
||||
public void SeverLimbJoint(LimbJoint limbJoint)
|
||||
{
|
||||
if (!limbJoint.CanBeSevered || limbJoint.IsSevered)
|
||||
@@ -713,9 +712,9 @@ namespace Barotrauma
|
||||
|
||||
SeverLimbJointProjSpecific(limbJoint);
|
||||
|
||||
if (GameMain.Server != null)
|
||||
if (GameMain.NetworkMember!=null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(character, new object[] { NetEntityEvent.Type.Status });
|
||||
GameMain.NetworkMember.CreateEntityEvent(character, new object[] { NetEntityEvent.Type.Status });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -985,6 +984,12 @@ namespace Barotrauma
|
||||
|
||||
SetPosition(Collider.SimPosition + moveAmount);
|
||||
character.CursorPosition += moveAmount;
|
||||
|
||||
Collider?.UpdateDrawPosition();
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
limb.body.UpdateDrawPosition();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCollisionCategories()
|
||||
@@ -1025,6 +1030,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (!character.Enabled || Frozen) return;
|
||||
|
||||
CheckValidity();
|
||||
|
||||
UpdateNetPlayerPosition(deltaTime);
|
||||
CheckDistFromCollider();
|
||||
UpdateCollisionCategories();
|
||||
@@ -1158,10 +1165,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (contacts.Contact.Enabled && contacts.Contact.IsTouching)
|
||||
{
|
||||
Vector2 normal;
|
||||
FarseerPhysics.Common.FixedArray2<Vector2> points;
|
||||
|
||||
contacts.Contact.GetWorldManifold(out normal, out points);
|
||||
contacts.Contact.GetWorldManifold(out Vector2 normal, out FarseerPhysics.Common.FixedArray2<Vector2> points);
|
||||
|
||||
switch (contacts.Contact.FixtureA.CollisionCategories)
|
||||
{
|
||||
@@ -1288,6 +1292,55 @@ namespace Barotrauma
|
||||
UpdateProjSpecific(deltaTime);
|
||||
}
|
||||
|
||||
private void CheckValidity()
|
||||
{
|
||||
CheckValidity(Collider);
|
||||
foreach (Limb limb in limbs)
|
||||
{
|
||||
CheckValidity(limb.body);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckValidity(PhysicsBody body)
|
||||
{
|
||||
string errorMsg = null;
|
||||
string bodyName = body.UserData is Limb ? "Limb" : "Collider";
|
||||
if (!MathUtils.IsValid(body.SimPosition) || Math.Abs(body.SimPosition.X) > 1e10f || Math.Abs(body.SimPosition.Y) > 1e10f)
|
||||
{
|
||||
errorMsg = bodyName+ " position invalid (" + body.SimPosition + ", character: " + character.Name + "), resetting the ragdoll.";
|
||||
}
|
||||
else if (!MathUtils.IsValid(body.LinearVelocity) || Math.Abs(body.LinearVelocity.X) > 1000f || Math.Abs(body.LinearVelocity.Y) > 1000f)
|
||||
{
|
||||
errorMsg = bodyName + " velocity invalid (" + body.LinearVelocity + ", character: " + character.Name + "), resetting the ragdoll.";
|
||||
}
|
||||
else if (!MathUtils.IsValid(body.Rotation))
|
||||
{
|
||||
errorMsg = bodyName + " rotation invalid (" + body.Rotation + ", character: " + character.Name + "), resetting the ragdoll.";
|
||||
}
|
||||
else if (!MathUtils.IsValid(body.AngularVelocity) || Math.Abs(body.AngularVelocity) > 1000f)
|
||||
{
|
||||
errorMsg = bodyName + " angular velocity invalid (" + body.AngularVelocity + ", character: " + character.Name + "), resetting the ragdoll.";
|
||||
}
|
||||
if (errorMsg != null)
|
||||
{
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Ragdoll.CheckValidity:" + character.ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
|
||||
if (!MathUtils.IsValid(Collider.SimPosition) || Math.Abs(Collider.SimPosition.X) > 1e10f || Math.Abs(Collider.SimPosition.Y) > 1e10f)
|
||||
{
|
||||
Collider.SetTransform(Vector2.Zero, 0.0f);
|
||||
}
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
limb.body.SetTransform(Collider.SimPosition, 0.0f);
|
||||
limb.body.ResetDynamics();
|
||||
}
|
||||
SetInitialLimbPositions();
|
||||
return;
|
||||
}
|
||||
UpdateProjSpecific(deltaTime);
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime);
|
||||
|
||||
partial void Splash(Limb limb, Hull limbHull);
|
||||
@@ -1365,7 +1418,15 @@ namespace Barotrauma
|
||||
|
||||
Vector2 limbMoveAmount = simPosition - MainLimb.SimPosition;
|
||||
|
||||
Collider.SetTransform(simPosition, Collider.Rotation);
|
||||
if (lerp)
|
||||
{
|
||||
Collider.TargetPosition = simPosition;
|
||||
Collider.MoveToTargetPosition(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Collider.SetTransform(simPosition, Collider.Rotation);
|
||||
}
|
||||
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
@@ -1445,7 +1506,8 @@ namespace Barotrauma
|
||||
prevCollisionCategory = Category.None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
partial void UpdateNetPlayerPositionProjSpecific(float deltaTime, float lowestSubPos);
|
||||
private void UpdateNetPlayerPosition(float deltaTime)
|
||||
{
|
||||
if (GameMain.NetworkMember == null) return;
|
||||
@@ -1467,214 +1529,8 @@ namespace Barotrauma
|
||||
character.MemState[i].TransformOutToInside(currentHull.Submarine);
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.Server != null) return; //the server should not be trying to correct any positions, it's authoritative
|
||||
|
||||
if (character != GameMain.NetworkMember.Character || !character.AllowInput)
|
||||
{
|
||||
//remove states without a timestamp (there may still be ID-based states
|
||||
//in the list when the controlled character switches to timestamp-based interpolation)
|
||||
character.MemState.RemoveAll(m => m.Timestamp == 0.0f);
|
||||
|
||||
//use simple interpolation for other players' characters and characters that can't move
|
||||
if (character.MemState.Count > 0)
|
||||
{
|
||||
CharacterStateInfo serverPos = character.MemState.Last();
|
||||
if (!character.isSynced)
|
||||
{
|
||||
SetPosition(serverPos.Position, false);
|
||||
Collider.LinearVelocity = Vector2.Zero;
|
||||
character.MemLocalState.Clear();
|
||||
character.LastNetworkUpdateID = serverPos.ID;
|
||||
character.isSynced = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (character.MemState[0].Interact == null || character.MemState[0].Interact.Removed)
|
||||
{
|
||||
character.DeselectCharacter();
|
||||
character.SelectedConstruction = null;
|
||||
}
|
||||
else if (character.MemState[0].Interact is Character)
|
||||
{
|
||||
character.SelectCharacter((Character)character.MemState[0].Interact);
|
||||
}
|
||||
else if (character.MemState[0].Interact is Item newSelectedConstruction)
|
||||
{
|
||||
if (newSelectedConstruction != null && character.SelectedConstruction != newSelectedConstruction)
|
||||
{
|
||||
foreach (var ic in newSelectedConstruction.components)
|
||||
{
|
||||
if (ic.CanBeSelected) ic.Select(character);
|
||||
}
|
||||
}
|
||||
character.SelectedConstruction = newSelectedConstruction;
|
||||
}
|
||||
|
||||
if (character.MemState[0].Animation == AnimController.Animation.CPR)
|
||||
{
|
||||
character.AnimController.Anim = AnimController.Animation.CPR;
|
||||
}
|
||||
else if (character.AnimController.Anim == AnimController.Animation.CPR)
|
||||
{
|
||||
character.AnimController.Anim = AnimController.Animation.None;
|
||||
}
|
||||
|
||||
Vector2 newVelocity = Vector2.Zero;
|
||||
Vector2 newPosition = Collider.SimPosition;
|
||||
Collider.CorrectPosition(character.MemState, deltaTime, out newVelocity, out newPosition);
|
||||
|
||||
newVelocity = newVelocity.ClampLength(100.0f);
|
||||
if (!MathUtils.IsValid(newVelocity)) newVelocity = Vector2.Zero;
|
||||
overrideTargetMovement = newVelocity;
|
||||
Collider.LinearVelocity = newVelocity;
|
||||
|
||||
float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition);
|
||||
if (distSqrd > 10.0f)
|
||||
{
|
||||
SetPosition(newPosition);
|
||||
}
|
||||
else if (distSqrd > 0.01f)
|
||||
{
|
||||
Collider.SetTransform(newPosition, Collider.Rotation);
|
||||
}
|
||||
|
||||
//unconscious/dead characters can't correct their position using AnimController movement
|
||||
// -> we need to correct it manually
|
||||
if (!character.AllowInput)
|
||||
{
|
||||
Collider.LinearVelocity = overrideTargetMovement;
|
||||
MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
|
||||
MainLimb.PullJointEnabled = true;
|
||||
}
|
||||
}
|
||||
character.MemLocalState.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
//remove states with a timestamp (there may still timestamp-based states
|
||||
//in the list if the controlled character switches from timestamp-based interpolation to ID-based)
|
||||
character.MemState.RemoveAll(m => m.Timestamp > 0.0f);
|
||||
|
||||
for (int i = 0; i < character.MemLocalState.Count; i++)
|
||||
{
|
||||
if (character.Submarine == null)
|
||||
{
|
||||
//transform in-sub coordinates to outside coordinates
|
||||
if (character.MemLocalState[i].Position.Y > lowestSubPos)
|
||||
{
|
||||
character.MemLocalState[i].TransformInToOutside();
|
||||
}
|
||||
}
|
||||
else if (currentHull?.Submarine != null)
|
||||
{
|
||||
//transform outside coordinates to in-sub coordinates
|
||||
if (character.MemLocalState[i].Position.Y < lowestSubPos)
|
||||
{
|
||||
character.MemLocalState[i].TransformOutToInside(currentHull.Submarine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (character.MemState.Count < 1) return;
|
||||
|
||||
overrideTargetMovement = Vector2.Zero;
|
||||
|
||||
CharacterStateInfo serverPos = character.MemState.Last();
|
||||
|
||||
if (!character.isSynced)
|
||||
{
|
||||
SetPosition(serverPos.Position, false);
|
||||
Collider.LinearVelocity = Vector2.Zero;
|
||||
character.MemLocalState.Clear();
|
||||
character.LastNetworkUpdateID = serverPos.ID;
|
||||
character.isSynced = true;
|
||||
return;
|
||||
}
|
||||
|
||||
int localPosIndex = character.MemLocalState.FindIndex(m => m.ID == serverPos.ID);
|
||||
if (localPosIndex > -1)
|
||||
{
|
||||
CharacterStateInfo localPos = character.MemLocalState[localPosIndex];
|
||||
|
||||
//the entity we're interacting with doesn't match the server's
|
||||
if (localPos.Interact != serverPos.Interact)
|
||||
{
|
||||
if (serverPos.Interact == null || serverPos.Interact.Removed)
|
||||
{
|
||||
character.DeselectCharacter();
|
||||
character.SelectedConstruction = null;
|
||||
}
|
||||
else if (serverPos.Interact is Character)
|
||||
{
|
||||
character.SelectCharacter((Character)serverPos.Interact);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newSelectedConstruction = (Item)serverPos.Interact;
|
||||
if (newSelectedConstruction != null && character.SelectedConstruction != newSelectedConstruction)
|
||||
{
|
||||
newSelectedConstruction.TryInteract(character, true, true);
|
||||
}
|
||||
character.SelectedConstruction = newSelectedConstruction;
|
||||
}
|
||||
}
|
||||
|
||||
if (localPos.Animation != serverPos.Animation)
|
||||
{
|
||||
if (serverPos.Animation == AnimController.Animation.CPR)
|
||||
{
|
||||
character.AnimController.Anim = AnimController.Animation.CPR;
|
||||
}
|
||||
else if (character.AnimController.Anim == AnimController.Animation.CPR)
|
||||
{
|
||||
character.AnimController.Anim = AnimController.Animation.None;
|
||||
}
|
||||
}
|
||||
|
||||
Hull serverHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(serverPos.Position), character.CurrentHull, serverPos.Position.Y < lowestSubPos);
|
||||
Hull clientHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(localPos.Position), serverHull, localPos.Position.Y < lowestSubPos);
|
||||
|
||||
if (serverHull != null && clientHull != null && serverHull.Submarine != clientHull.Submarine)
|
||||
{
|
||||
//hull subs don't match => teleport the camera to the other sub
|
||||
character.Submarine = serverHull.Submarine;
|
||||
character.CurrentHull = currentHull = serverHull;
|
||||
SetPosition(serverPos.Position);
|
||||
character.MemLocalState.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 positionError = serverPos.Position - localPos.Position;
|
||||
float rotationError = serverPos.Rotation - localPos.Rotation;
|
||||
|
||||
for (int i = localPosIndex; i < character.MemLocalState.Count; i++)
|
||||
{
|
||||
Hull pointHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(character.MemLocalState[i].Position), clientHull, character.MemLocalState[i].Position.Y < lowestSubPos);
|
||||
if (pointHull != clientHull && ((pointHull == null) || (clientHull == null) || (pointHull.Submarine == clientHull.Submarine))) break;
|
||||
character.MemLocalState[i].Translate(positionError, rotationError);
|
||||
}
|
||||
|
||||
float errorMagnitude = positionError.Length();
|
||||
if (errorMagnitude > 0.01f)
|
||||
{
|
||||
Collider.SetTransform(Collider.SimPosition + positionError, Collider.Rotation + rotationError);
|
||||
if (errorMagnitude > 0.5f)
|
||||
{
|
||||
character.MemLocalState.Clear();
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
limb.body.SetTransform(limb.body.SimPosition + positionError, limb.body.Rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120);
|
||||
character.MemState.Clear();
|
||||
}
|
||||
UpdateNetPlayerPositionProjSpecific(deltaTime, lowestSubPos);
|
||||
}
|
||||
|
||||
private Vector2 GetFlowForce()
|
||||
@@ -1735,11 +1591,8 @@ namespace Barotrauma
|
||||
{
|
||||
for (int i = 0; i < Collider.FarseerBody.FixtureList.Count; i++)
|
||||
{
|
||||
FarseerPhysics.Collision.AABB aabb;
|
||||
FarseerPhysics.Common.Transform transform;
|
||||
|
||||
Collider.FarseerBody.GetTransform(out transform);
|
||||
Collider.FarseerBody.FixtureList[i].Shape.ComputeAABB(out aabb, ref transform, i);
|
||||
Collider.FarseerBody.GetTransform(out FarseerPhysics.Common.Transform transform);
|
||||
Collider.FarseerBody.FixtureList[i].Shape.ComputeAABB(out FarseerPhysics.Collision.AABB aabb, ref transform, i);
|
||||
|
||||
lowestBound = Math.Min(aabb.LowerBound.Y, lowestBound);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user