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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -211,6 +211,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool AllowMovement
|
||||
{
|
||||
get { return !IsUnconscious && Stun <= 0.0f && !isDead; }
|
||||
}
|
||||
|
||||
public Vector2 CursorPosition
|
||||
{
|
||||
get { return cursorPosition; }
|
||||
@@ -1302,7 +1307,7 @@ namespace Barotrauma
|
||||
|
||||
if (this != Character.Controlled)
|
||||
{
|
||||
if (GameMain.Server != null && !(this is AICharacter))
|
||||
if (GameMain.Server != null && !(this is AICharacter) && AllowMovement)
|
||||
{
|
||||
if (memInput.Count > 0)
|
||||
{
|
||||
@@ -1333,42 +1338,38 @@ namespace Barotrauma
|
||||
{
|
||||
isStillCountdown = 15;
|
||||
}
|
||||
//DebugConsole.NewMessage(Convert.ToString(memInput.Count), Color.Lime);
|
||||
}
|
||||
else
|
||||
{
|
||||
AnimController.Frozen = true;
|
||||
if (AllowMovement) AnimController.Frozen = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
memLocalPos.Add(new PosInfo(SimPosition, AnimController.TargetDir, LastNetworkUpdateID));
|
||||
memLocalPos.Add(new PosInfo(SimPosition, AnimController.TargetDir, LastNetworkUpdateID));
|
||||
|
||||
InputNetFlags newInput = InputNetFlags.None;
|
||||
if (IsKeyDown(InputType.Left)) newInput |= InputNetFlags.Left;
|
||||
if (IsKeyDown(InputType.Right)) newInput |= InputNetFlags.Right;
|
||||
if (IsKeyDown(InputType.Up)) newInput |= InputNetFlags.Up;
|
||||
if (IsKeyDown(InputType.Down)) newInput |= InputNetFlags.Down;
|
||||
if (IsKeyDown(InputType.Run)) newInput |= InputNetFlags.Run;
|
||||
if (IsKeyDown(InputType.Select)) newInput |= InputNetFlags.Select;
|
||||
if (IsKeyDown(InputType.Use)) newInput |= InputNetFlags.Use;
|
||||
if (IsKeyDown(InputType.Aim)) newInput |= InputNetFlags.Aim;
|
||||
InputNetFlags newInput = InputNetFlags.None;
|
||||
if (IsKeyDown(InputType.Left)) newInput |= InputNetFlags.Left;
|
||||
if (IsKeyDown(InputType.Right)) newInput |= InputNetFlags.Right;
|
||||
if (IsKeyDown(InputType.Up)) newInput |= InputNetFlags.Up;
|
||||
if (IsKeyDown(InputType.Down)) newInput |= InputNetFlags.Down;
|
||||
if (IsKeyDown(InputType.Run)) newInput |= InputNetFlags.Run;
|
||||
if (IsKeyDown(InputType.Select)) newInput |= InputNetFlags.Select;
|
||||
if (IsKeyDown(InputType.Use)) newInput |= InputNetFlags.Use;
|
||||
if (IsKeyDown(InputType.Aim)) newInput |= InputNetFlags.Aim;
|
||||
|
||||
if (AnimController.TargetDir == Direction.Left) newInput |= InputNetFlags.FacingLeft;
|
||||
if (AnimController.TargetDir == Direction.Left) newInput |= InputNetFlags.FacingLeft;
|
||||
|
||||
memInput.Insert(0, newInput);
|
||||
memMousePos.Insert(0, closestItem!=null ? closestItem.Position : cursorPosition);
|
||||
LastNetworkUpdateID++;
|
||||
if (memInput.Count > 60)
|
||||
{
|
||||
memInput.RemoveRange(60, memInput.Count - 60);
|
||||
memMousePos.RemoveRange(60, memMousePos.Count - 60);
|
||||
}
|
||||
}
|
||||
memInput.Insert(0, newInput);
|
||||
memMousePos.Insert(0, closestItem!=null ? closestItem.Position : cursorPosition);
|
||||
LastNetworkUpdateID++;
|
||||
if (memInput.Count > 60)
|
||||
{
|
||||
memInput.RemoveRange(60, memInput.Count - 60);
|
||||
memMousePos.RemoveRange(60, memMousePos.Count - 60);
|
||||
}
|
||||
}
|
||||
|
||||
if (networkUpdateSent)
|
||||
@@ -2113,27 +2114,22 @@ namespace Barotrauma
|
||||
facingRight = msg.ReadBoolean();
|
||||
}
|
||||
|
||||
Vector2 pos = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
||||
Vector2 pos = new Vector2(
|
||||
msg.ReadFloat(),
|
||||
msg.ReadFloat());
|
||||
|
||||
var posInfo =
|
||||
GameMain.NetworkMember.Character == this ?
|
||||
new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, networkUpdateID) :
|
||||
new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, sendingTime);
|
||||
var posInfo = new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, networkUpdateID, sendingTime);
|
||||
|
||||
int index = 0;
|
||||
if (GameMain.NetworkMember.Character == this)
|
||||
if (GameMain.NetworkMember.Character == this && AllowMovement)
|
||||
{
|
||||
while (index < memPos.Count && posInfo.ID > memPos[index].ID)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
while (index < memPos.Count && posInfo.ID > memPos[index].ID)
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (index < memPos.Count && posInfo.Timestamp > memPos[index].Timestamp)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
while (index < memPos.Count && posInfo.Timestamp > memPos[index].Timestamp)
|
||||
index++;
|
||||
}
|
||||
|
||||
memPos.Insert(index, posInfo);
|
||||
@@ -2192,7 +2188,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
Health = msg.ReadRangedSingle(minHealth, maxHealth, 8);
|
||||
health = msg.ReadRangedSingle(minHealth, maxHealth, 8);
|
||||
|
||||
bool lowOxygen = msg.ReadBoolean();
|
||||
if (lowOxygen)
|
||||
|
||||
@@ -269,6 +269,11 @@ namespace Barotrauma
|
||||
|
||||
private static void DrawStatusIcons(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(30, GameMain.GraphicsHeight - 260), "Stun: "+character.Stun, Color.White);
|
||||
}
|
||||
|
||||
if (drowningBar == null)
|
||||
{
|
||||
int width = 100, height = 20;
|
||||
|
||||
@@ -20,21 +20,22 @@ namespace Barotrauma
|
||||
public readonly UInt32 ID;
|
||||
|
||||
public PosInfo(Vector2 pos, Direction dir, float time)
|
||||
: this(pos, dir, 0, time)
|
||||
{
|
||||
Position = pos;
|
||||
Direction = dir;
|
||||
Timestamp = time;
|
||||
|
||||
ID = 0;
|
||||
}
|
||||
|
||||
public PosInfo(Vector2 pos, Direction dir, UInt32 ID)
|
||||
: this(pos, dir, ID, 0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
public PosInfo(Vector2 pos, Direction dir, UInt32 ID, float time)
|
||||
{
|
||||
Position = pos;
|
||||
Direction = dir;
|
||||
this.ID = ID;
|
||||
|
||||
Timestamp = 0.0f;
|
||||
Timestamp = time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user