diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs index c6f95eda7..c2761aeaf 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs @@ -88,13 +88,13 @@ namespace Barotrauma Collider.AngularVelocity = newAngularVelocity; float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition); - float errorTolerance = character.AllowInput ? 0.01f : 0.1f; + float errorTolerance = character.AllowInput ? 0.01f : 0.2f; if (distSqrd > errorTolerance) { if (distSqrd > 10.0f || !character.AllowInput) { Collider.TargetRotation = newRotation; - SetPosition(newPosition, lerp: distSqrd < 1.0f); + SetPosition(newPosition, lerp: distSqrd < 5.0f); } else { @@ -108,8 +108,15 @@ namespace Barotrauma // -> we need to correct it manually if (!character.AllowInput) { - MainLimb.PullJointWorldAnchorB = Collider.SimPosition; - MainLimb.PullJointEnabled = true; + float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, Collider.SimPosition); + float mainLimbErrorTolerance = 0.1f; + //if the main limb is roughly at the correct position and the collider isn't moving (much at least), + //don't attempt to correct the position. + if (mainLimbDistSqrd > mainLimbErrorTolerance || Collider.LinearVelocity.LengthSquared() > 0.05f) + { + MainLimb.PullJointWorldAnchorB = Collider.SimPosition; + MainLimb.PullJointEnabled = true; + } } } character.MemLocalState.Clear(); diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs index 5753c1c97..90d2622fd 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs @@ -211,6 +211,7 @@ namespace Barotrauma Vector2 linearVelocity = new Vector2( msg.ReadRangedSingle(-MaxVel, MaxVel, 12), msg.ReadRangedSingle(-MaxVel, MaxVel, 12)); + linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12); bool fixedRotation = msg.ReadBoolean(); float? rotation = null; @@ -220,6 +221,7 @@ namespace Barotrauma rotation = msg.ReadFloat(); float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity; angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8); + angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8); } bool readStatus = msg.ReadBoolean(); diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs index ec5b88851..cbb751f50 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs @@ -656,6 +656,13 @@ namespace Barotrauma msg.Timer -= deltaTime; msg.Pos += msg.Velocity * deltaTime; } + + foreach (GUIMessage msg in messages) + { + if (!msg.WorldSpace) continue; + msg.Timer -= deltaTime; + msg.Pos += msg.Velocity * deltaTime; + } } messages.RemoveAll(m => m.Timer <= 0.0f); diff --git a/Barotrauma/BarotraumaClient/Source/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaClient/Source/Physics/PhysicsBody.cs index f231c83a0..88e1011e8 100644 --- a/Barotrauma/BarotraumaClient/Source/Physics/PhysicsBody.cs +++ b/Barotrauma/BarotraumaClient/Source/Physics/PhysicsBody.cs @@ -171,9 +171,12 @@ namespace Barotrauma newVelocity = new Vector2( msg.ReadRangedSingle(-MaxVel, MaxVel, 12), msg.ReadRangedSingle(-MaxVel, MaxVel, 12)); + newVelocity = NetConfig.Quantize(newVelocity, -MaxVel, MaxVel, 12); + if (!fixedRotation) { newAngularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8); + newAngularVelocity = NetConfig.Quantize(newAngularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8); } } msg.ReadPadBits(); diff --git a/Barotrauma/BarotraumaServer/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/Source/Characters/CharacterNetworking.cs index d9831f872..8b4d121dc 100644 --- a/Barotrauma/BarotraumaServer/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/Source/Characters/CharacterNetworking.cs @@ -376,8 +376,9 @@ namespace Barotrauma tempBuffer.Write(SimPosition.X); tempBuffer.Write(SimPosition.Y); float MaxVel = NetConfig.MaxPhysicsBodyVelocity; - tempBuffer.WriteRangedSingle(MathHelper.Clamp(AnimController.Collider.LinearVelocity.X, -MaxVel, MaxVel), -MaxVel, MaxVel, 12); - tempBuffer.WriteRangedSingle(MathHelper.Clamp(AnimController.Collider.LinearVelocity.Y, -MaxVel, MaxVel), -MaxVel, MaxVel, 12); + AnimController.Collider.LinearVelocity = NetConfig.Quantize(AnimController.Collider.LinearVelocity, -MaxVel, MaxVel, 12); + tempBuffer.WriteRangedSingle(AnimController.Collider.LinearVelocity.X, -MaxVel, MaxVel, 12); + tempBuffer.WriteRangedSingle(AnimController.Collider.LinearVelocity.Y, -MaxVel, MaxVel, 12); bool fixedRotation = AnimController.Collider.FarseerBody.FixedRotation; tempBuffer.Write(fixedRotation); @@ -385,6 +386,7 @@ namespace Barotrauma { tempBuffer.Write(AnimController.Collider.Rotation); float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity; + AnimController.Collider.AngularVelocity = NetConfig.Quantize(AnimController.Collider.AngularVelocity, -MaxAngularVel, MaxAngularVel, 8); tempBuffer.WriteRangedSingle(MathHelper.Clamp(AnimController.Collider.AngularVelocity, -MaxAngularVel, MaxAngularVel), -MaxAngularVel, MaxAngularVel, 8); } diff --git a/Barotrauma/BarotraumaServer/Source/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaServer/Source/Physics/PhysicsBody.cs index b2276c7f5..10580b11e 100644 --- a/Barotrauma/BarotraumaServer/Source/Physics/PhysicsBody.cs +++ b/Barotrauma/BarotraumaServer/Source/Physics/PhysicsBody.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Barotrauma.Networking; +using Barotrauma.Networking; using Lidgren.Network; using Microsoft.Xna.Framework; +using System; namespace Barotrauma { @@ -37,10 +33,12 @@ namespace Barotrauma if (FarseerBody.Awake) { body.Enabled = true; - msg.WriteRangedSingle(MathHelper.Clamp(body.LinearVelocity.X, -MaxVel, MaxVel), -MaxVel, MaxVel, 12); - msg.WriteRangedSingle(MathHelper.Clamp(body.LinearVelocity.Y, -MaxVel, MaxVel), -MaxVel, MaxVel, 12); + body.LinearVelocity = NetConfig.Quantize(body.LinearVelocity, -MaxVel, MaxVel, 12); + msg.WriteRangedSingle(body.LinearVelocity.X, -MaxVel, MaxVel, 12); + msg.WriteRangedSingle(body.LinearVelocity.Y, -MaxVel, MaxVel, 12); if (!FarseerBody.FixedRotation) { + body.AngularVelocity = NetConfig.Quantize(body.AngularVelocity, -MaxAngularVel, MaxAngularVel, 8); msg.WriteRangedSingle(MathHelper.Clamp(body.AngularVelocity, -MaxAngularVel, MaxAngularVel), -MaxAngularVel, MaxAngularVel, 8); } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index 24b7e331e..983c2091b 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -726,8 +726,7 @@ namespace Barotrauma if (!canAttack && !IsCoolDownRunning) { // If not, reset the attacking limb, if the cooldown is not running - // Don't use the property, because we don't want cancel reversing, if we are reversing. - _attackingLimb = null; + AttackingLimb = null; } } @@ -798,6 +797,7 @@ namespace Barotrauma { UpdateLimbAttack(deltaTime, AttackingLimb, attackSimPos, distance); } + return false; } private bool SteerThroughGap(Structure wall, WallSection section, Vector2 targetWorldPos, float deltaTime) @@ -1169,15 +1169,15 @@ namespace Barotrauma else if (target.Entity is Structure s) { targetingTag = "wall"; - if (!s.HasBody) - { - // Ignore structures that doesn't have a body (not walls) - continue; - } - // Ignore walls when inside. - valueModifier = character.CurrentHull == null ? 1 : 0; if (aggressiveBoarding) { + // Ignore walls when inside. + valueModifier = character.CurrentHull == null ? 2 : 0; + if (valueModifier > 0) + { + // Ignore structures that doesn't have a body (not walls) + valueModifier *= s.HasBody ? 1 : 0; + } for (int i = 0; i < s.Sections.Length; i++) { var section = s.Sections[i]; @@ -1194,17 +1194,37 @@ namespace Barotrauma } } } + } + else + { + targetingTag = "room"; + } + if (door != null) + { + // If there's not a more specific tag for the door + if (string.IsNullOrEmpty(targetingTag) || targetingTag == "room") + { + targetingTag = "door"; + } + bool isOutdoor = door.LinkedGap?.FlowTargetHull != null && !door.LinkedGap.IsRoomToRoom; + bool isOpen = door.IsOpen || door.Item.Condition <= 0.0f; + //increase priority if the character is outside and an aggressive boarder, and the door is from outside to inside + if (aggressiveBoarding) + { + if (character.CurrentHull == null) + { + valueModifier = isOutdoor ? 1 : 0; + valueModifier *= isOpen ? 5 : 1; + } + } else { // Ignore disabled walls bool isDisabled = true; for (int i = 0; i < s.Sections.Length; i++) { - if (!s.SectionBodyDisabled(i)) - { - isDisabled = false; - break; - } + valueModifier = isOutdoor ? 0 : 1; + valueModifier *= isOpen ? 0 : 1; } if (isDisabled) { @@ -1243,6 +1263,10 @@ namespace Barotrauma { continue; } + else if (isOpen) //ignore broken and open doors + { + continue; + } } else if (target.Entity is IDamageable targetDamageable && targetDamageable.Health <= 0.0f) { diff --git a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs index c298546ab..76cf20ef1 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/ItemPrefab.cs @@ -917,6 +917,39 @@ namespace Barotrauma AllowedLinks = element.GetAttributeStringArray("allowedlinks", new string[0], convertToLowerInvariant: true).ToList(); + if (sprite == null) + { + DebugConsole.ThrowError("Item \"" + Name + "\" has no sprite!"); +#if SERVER + sprite = new Sprite("", Vector2.Zero); + sprite.SourceRect = new Rectangle(0, 0, 32, 32); +#else + sprite = new Sprite(TextureLoader.PlaceHolderTexture, null, null) + { + Origin = TextureLoader.PlaceHolderTexture.Bounds.Size.ToVector2() / 2 + }; +#endif + size = sprite.size; + sprite.EntityID = identifier; + } + + if (!category.HasFlag(MapEntityCategory.Legacy) && string.IsNullOrEmpty(identifier)) + { + DebugConsole.ThrowError( + "Item prefab \"" + name + "\" has no identifier. All item prefabs have a unique identifier string that's used to differentiate between items during saving and loading."); + } + if (!string.IsNullOrEmpty(identifier)) + { + MapEntityPrefab existingPrefab = List.Find(e => e.Identifier == identifier); + if (existingPrefab != null) + { + DebugConsole.ThrowError( + "Map entity prefabs \"" + name + "\" and \"" + existingPrefab.Name + "\" have the same identifier!"); + } + } + + AllowedLinks = element.GetAttributeStringArray("allowedlinks", new string[0], convertToLowerInvariant: true).ToList(); + List.Add(this); } diff --git a/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs b/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs index 74b6afcb2..5c7bfa0f0 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs @@ -74,5 +74,23 @@ namespace Barotrauma.Networking if (lengthSqr > 1000.0f) { return Vector2.Zero; } return cursorPositionError *= 0.7f; } + + public static Vector2 Quantize(Vector2 value, float min, float max, int numberOfBits) + { + return new Vector2( + Quantize(value.X, min, max, numberOfBits), + Quantize(value.Y, min, max, numberOfBits)); + } + + public static float Quantize(float value, float min, float max, int numberOfBits) + { + float step = (max - min) / (1 << (numberOfBits + 1)); + if (Math.Abs(value) < step + 0.00001f) + { + return 0.0f; + } + + return MathUtils.RoundTowardsClosest(MathHelper.Clamp(value, min, max), step); + } } }