From 705d05a308e4ca3219c63e8952f9b37ad1f2a375 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Tue, 26 Mar 2019 17:08:53 +0200 Subject: [PATCH] (652745ae0) Fix a crash due to invalid physics when scaling the Mudraptor. If the ragdoll still has invalid settings after trying to reset it, just freeze it to prevent crashing. Return boolean and make CheckValidity public so that we can check and react to the invalid ragdoll state elsewhere. --- .../Source/Screens/CharacterEditorScreen.cs | 29 +++++++++----- .../Source/Characters/Animation/Ragdoll.cs | 40 ++++++++++++++++--- 2 files changed, 54 insertions(+), 15 deletions(-) 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);