diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs index 48be1e5a0..4ff6428a1 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CharacterEditorScreen.cs @@ -118,6 +118,19 @@ namespace Barotrauma instance = this; } + private void Reset() + { + AnimParams.ForEach(a => a.Reset(true)); + RagdollParams.Reset(true); + RagdollParams.ClearHistory(); + CurrentAnimation.ClearHistory(); + if (!character.Removed) + { + character.Remove(); + } + character = null; + } + public override void Deselect() { base.Deselect(); @@ -128,15 +141,7 @@ namespace Barotrauma isEndlessRunner = false; if (character != null) { - AnimParams.ForEach(a => a.Reset(true)); - RagdollParams.Reset(true); - RagdollParams.ClearHistory(); - CurrentAnimation.ClearHistory(); - if (!character.Removed) - { - character.Remove(); - } - character = null; + Reset(); } GameMain.World.ProcessChanges(); } @@ -393,6 +398,12 @@ namespace Barotrauma } if (!isFreezed) { + if (character.AnimController.Invalid) + { + Reset(); + SpawnCharacter(currentCharacterConfig); + } + Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position); Submarine.MainSub.Update((float)deltaTime); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs index db8b8cb03..669cce537 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs @@ -1031,7 +1031,9 @@ namespace Barotrauma public void Update(float deltaTime, Camera cam) { - if (!character.Enabled || Frozen) return; + if (!character.Enabled || Frozen || Invalid) return; + + CheckValidity(); CheckValidity(); @@ -1295,17 +1297,42 @@ namespace Barotrauma UpdateProjSpecific(deltaTime); } - private void CheckValidity() + public bool Invalid { get; private set; } + private int validityResets; + private bool CheckValidity() { - CheckValidity(Collider); + bool isColliderValid = CheckValidity(Collider); + bool limbsValid = true; foreach (Limb limb in limbs) { if (limb.body == null || !limb.body.Enabled) { continue; } - CheckValidity(limb.body); + if (!CheckValidity(limb.body)) + { + limbsValid = false; + break; + } } + bool isValid = isColliderValid && limbsValid; + if (!isValid) + { + validityResets++; + if (validityResets > 1) + { + Invalid = true; + DebugConsole.ThrowError("Invalid ragdoll physics. Ragdoll freezed to prevent crashes."); + Collider.SetTransform(Vector2.Zero, 0.0f); + foreach (Limb limb in Limbs) + { + limb.body.SetTransform(Collider.SimPosition, 0.0f); + limb.body.ResetDynamics(); + } + Frozen = true; + } + } + return isValid; } - private void CheckValidity(PhysicsBody body) + private bool CheckValidity(PhysicsBody body) { string errorMsg = null; string bodyName = body.UserData is Limb ? "Limb" : "Collider"; @@ -1357,8 +1384,9 @@ namespace Barotrauma limb.body.ResetDynamics(); } SetInitialLimbPositions(); - return; + return false; } + return true; } partial void UpdateProjSpecific(float deltaTime);