2f107db...5202af9

This commit is contained in:
Joonas Rikkonen
2019-03-18 21:42:26 +02:00
parent 58c92888b7
commit 044fd3344b
395 changed files with 27417 additions and 19754 deletions
@@ -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;
}
}
}
@@ -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)
{
@@ -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);
}