Fixes to unconscious character pos syncing:

- main limb is anchored to collider
- server ignores inputs from unconscious characters and doesn't freeze them
- using timestamp-based interpolation on the client's own character instead of IDs
This commit is contained in:
Regalis
2017-01-03 23:49:37 +02:00
parent 1eea373117
commit bb685019a2
5 changed files with 81 additions and 58 deletions

View File

@@ -59,7 +59,7 @@ namespace Barotrauma
ColliderIndex = Crouching ? 1 : 0;
if (!Crouching && ColliderIndex == 1) Crouching = true;
if (character.IsDead || character.IsUnconscious || stunTimer > 0.0f)
if (!character.AllowMovement)
{
levitatingCollider = false;
Collider.FarseerBody.FixedRotation = false;
@@ -921,13 +921,15 @@ namespace Barotrauma
target.AnimController.IgnorePlatforms = IgnorePlatforms;
if (target.Stun > 0.0f || target.IsUnconscious || target.IsDead)
if (!target.AllowMovement)
{
target.AnimController.TargetMovement = TargetMovement;
}
else if (target is AICharacter)
{
target.AnimController.TargetMovement = Vector2.Lerp(target.AnimController.TargetMovement, (character.SimPosition + Vector2.UnitX * Dir) - target.SimPosition, 0.5f);
target.AnimController.TargetMovement = Vector2.Lerp(
target.AnimController.TargetMovement,
(character.SimPosition + Vector2.UnitX * Dir) - target.SimPosition, 0.5f);
}
}

View File

@@ -1170,12 +1170,20 @@ namespace Barotrauma
protected void CheckDistFromCollider()
{
float allowedDist = Math.Max(Math.Max(Collider.radius, Collider.width), Collider.height) * 2.0f;
float allowedDist = Math.Max(Math.Max(Collider.radius, Collider.width), Collider.height) * 2.0f;
float resetDist = allowedDist * 10.0f;
//if the ragdoll is too far from the collider, disable collisions until it's close enough
//(in case the ragdoll has gotten stuck somewhere)
if (Vector2.DistanceSquared(Collider.SimPosition, MainLimb.SimPosition) > allowedDist*allowedDist)
float distSqrd = Vector2.DistanceSquared(Collider.SimPosition, MainLimb.SimPosition);
if (distSqrd > resetDist * resetDist)
{
//ragdoll way too far, reset position
SetPosition(Collider.SimPosition, true);
}
if (distSqrd > allowedDist * allowedDist)
{
//ragdoll too far from the collider, disable collisions until it's close enough
//(in case the ragdoll has gotten stuck somewhere)
foreach (Limb limb in Limbs)
{
limb.body.CollidesWith = Physics.CollisionNone;
@@ -1197,20 +1205,31 @@ namespace Barotrauma
{
if (GameMain.NetworkMember == null) return;
if (character != GameMain.NetworkMember.Character ||
character.IsUnconscious || character.Stun > 0.0f)
if (character != GameMain.NetworkMember.Character || !character.AllowMovement)
{
//use simple interpolation for other players' characters and unconscious characters
//use simple interpolation for other players' characters and characters that can't move
if (character.MemPos.Count > 0)
{
Collider.LinearVelocity = Vector2.Zero;
Collider.CorrectPosition(character.MemPos, deltaTime, out overrideTargetMovement);
}
//unconscious/dead characters can't correct their position using AnimController movement
// -> we need to correct it manually
if (character.AllowMovement)
{
Collider.LinearVelocity = overrideTargetMovement;
MainLimb.pullJoint.WorldAnchorB = Collider.SimPosition;
MainLimb.pullJoint.Enabled = true;
}
}
character.MemLocalPos.Clear();
}
else
{
if (character.MemPos.Count < 1) return;
overrideTargetMovement = Vector2.Zero;
PosInfo serverPos = character.MemPos.Last();
int localPosIndex = character.MemLocalPos.FindIndex(m => m.ID == serverPos.ID);