Unstable 1.8.4.0
This commit is contained in:
@@ -64,6 +64,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Body> limbBodies = new List<Body>();
|
||||
public IEnumerable<Body> LimbBodies => limbBodies;
|
||||
|
||||
public bool HasMultipleLimbsOfSameType => limbs != null && limbs.Length > limbDictionary.Count;
|
||||
|
||||
private bool frozen;
|
||||
@@ -91,7 +94,7 @@ namespace Barotrauma
|
||||
private bool simplePhysicsEnabled;
|
||||
|
||||
public Character Character => character;
|
||||
protected Character character;
|
||||
protected readonly Character character;
|
||||
|
||||
protected float strongestImpact;
|
||||
|
||||
@@ -108,7 +111,7 @@ namespace Barotrauma
|
||||
|
||||
//a movement vector that overrides targetmovement if trying to steer
|
||||
//a Character to the position sent by server in multiplayer mode
|
||||
protected Vector2 overrideTargetMovement;
|
||||
protected Vector2? overrideTargetMovement;
|
||||
|
||||
protected float floorY, standOnFloorY;
|
||||
protected Fixture floorFixture;
|
||||
@@ -138,6 +141,12 @@ namespace Barotrauma
|
||||
|
||||
private Category prevCollisionCategory = Category.None;
|
||||
|
||||
/// <summary>
|
||||
/// When the character is alive/conscious, the collider drives the character's movement and is used to sync the character's position in MP.
|
||||
/// When unconscious, the ragdoll controls the movement and the collider just sticks to the main limb.
|
||||
/// </summary>
|
||||
public bool ColliderControlsMovement => character.CanMove;
|
||||
|
||||
public bool IsStuck => Limbs.Any(l => l.IsStuck);
|
||||
|
||||
public PhysicsBody Collider
|
||||
@@ -185,7 +194,7 @@ namespace Barotrauma
|
||||
Vector2 pos = collider[colliderIndex].SimPosition;
|
||||
pos.Y -= collider[colliderIndex].Height * 0.5f;
|
||||
pos.Y += collider[value].Height * 0.5f;
|
||||
collider[value].SetTransform(pos, collider[colliderIndex].Rotation);
|
||||
collider[value].SetTransformIgnoreContacts(pos, collider[colliderIndex].Rotation);
|
||||
|
||||
collider[value].LinearVelocity = collider[colliderIndex].LinearVelocity;
|
||||
collider[value].AngularVelocity = collider[colliderIndex].AngularVelocity;
|
||||
@@ -282,7 +291,7 @@ namespace Barotrauma
|
||||
foreach (Limb limb in Limbs)
|
||||
{
|
||||
if (limb.IsSevered || !limb.body.PhysEnabled) { continue; }
|
||||
limb.body.SetTransform(Collider.SimPosition, Collider.Rotation);
|
||||
limb.body.SetTransformIgnoreContacts(Collider.SimPosition, Collider.Rotation);
|
||||
//reset pull joints (they may be somewhere far away if the character has moved from the position where animations were last updated)
|
||||
limb.PullJointEnabled = false;
|
||||
limb.PullJointWorldAnchorB = limb.SimPosition;
|
||||
@@ -297,11 +306,11 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
return (overrideTargetMovement == Vector2.Zero) ? targetMovement : overrideTargetMovement;
|
||||
return overrideTargetMovement ?? targetMovement;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!MathUtils.IsValid(value)) return;
|
||||
if (!MathUtils.IsValid(value)) { return; }
|
||||
targetMovement.X = MathHelper.Clamp(value.X, -MAX_SPEED, MAX_SPEED);
|
||||
targetMovement.Y = MathHelper.Clamp(value.Y, -MAX_SPEED, MAX_SPEED);
|
||||
}
|
||||
@@ -385,15 +394,16 @@ namespace Barotrauma
|
||||
if (ragdollParams != null)
|
||||
{
|
||||
RagdollParams = ragdollParams;
|
||||
if (!character.VariantOf.IsEmpty)
|
||||
{
|
||||
RagdollParams.TryApplyVariantScale(character.Params.VariantFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only re-equip items if the ragdoll doesn't change, because re-equiping items might throw exceptions if the limbs have changed.
|
||||
items = limbs?.ToDictionary(l => l.Params, l => l.WearingItems);
|
||||
}
|
||||
if (character.Params.VariantFile is XDocument variantFile)
|
||||
{
|
||||
RagdollParams.TryApplyVariantScale(variantFile);
|
||||
}
|
||||
foreach (var limbParams in RagdollParams.Limbs)
|
||||
{
|
||||
if (!PhysicsBody.IsValidShape(limbParams.Radius, limbParams.Height, limbParams.Width))
|
||||
@@ -430,18 +440,13 @@ namespace Barotrauma
|
||||
|
||||
if (character.IsHusk && character.Params.UseHuskAppendage)
|
||||
{
|
||||
bool inEditor = false;
|
||||
#if CLIENT
|
||||
inEditor = Screen.Selected == GameMain.CharacterEditorScreen;
|
||||
#endif
|
||||
|
||||
var characterPrefab = CharacterPrefab.FindByFilePath(character.ConfigPath);
|
||||
if (characterPrefab?.ConfigElement != null)
|
||||
{
|
||||
var mainElement = characterPrefab.ConfigElement;
|
||||
foreach (var huskAppendage in mainElement.GetChildElements("huskappendage"))
|
||||
{
|
||||
if (!inEditor && huskAppendage.GetAttributeBool("onlyfromafflictions", false)) { continue; }
|
||||
if (huskAppendage.GetAttributeBool("onlyfromafflictions", false)) { continue; }
|
||||
|
||||
Identifier afflictionIdentifier = huskAppendage.GetAttributeIdentifier("affliction", Identifier.Empty);
|
||||
if (!AfflictionPrefab.Prefabs.TryGet(afflictionIdentifier, out AfflictionPrefab affliction) ||
|
||||
@@ -452,7 +457,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
AfflictionHusk.AttachHuskAppendage(character, matchingAffliction, huskAppendage, ragdoll: this);
|
||||
AfflictionHusk.AttachHuskAppendage(character, matchingAffliction, huskedSpeciesName: character.SpeciesName, huskAppendage, ragdoll: this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,7 +483,7 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError("Invalid collider dimensions: " + cParams.Name);
|
||||
break; ;
|
||||
}
|
||||
var body = new PhysicsBody(cParams);
|
||||
var body = new PhysicsBody(cParams, findNewContacts: false);
|
||||
collider.Add(body);
|
||||
body.UserData = character;
|
||||
body.FarseerBody.OnCollision += OnLimbCollision;
|
||||
@@ -520,7 +525,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (joint == null) { continue; }
|
||||
float angle = (joint.LowerLimit + joint.UpperLimit) / 2.0f;
|
||||
joint.LimbB?.body?.SetTransform(
|
||||
joint.LimbB?.body?.SetTransformIgnoreContacts(
|
||||
(joint.WorldAnchorA - MathUtils.RotatePointAroundTarget(joint.LocalAnchorB, Vector2.Zero, joint.BodyA.Rotation + angle, true)),
|
||||
joint.BodyA.Rotation + angle);
|
||||
}
|
||||
@@ -528,11 +533,13 @@ namespace Barotrauma
|
||||
|
||||
protected void CreateLimbs()
|
||||
{
|
||||
limbBodies.Clear();
|
||||
limbs?.ForEach(l => l.Remove());
|
||||
Mass = 0;
|
||||
DebugConsole.Log($"Creating limbs from {RagdollParams.Name}.");
|
||||
limbDictionary = new Dictionary<LimbType, Limb>();
|
||||
limbs = new Limb[RagdollParams.Limbs.Count];
|
||||
RagdollParams.Limbs.ForEach(l => AddLimb(l));
|
||||
RagdollParams.Limbs.ForEach(AddLimb);
|
||||
if (limbs.Contains(null)) { return; }
|
||||
SetupDrawOrder();
|
||||
}
|
||||
@@ -549,11 +556,11 @@ namespace Barotrauma
|
||||
|
||||
/// <summary>
|
||||
/// Resets the serializable data to the currently selected ragdoll params.
|
||||
/// Force reloading always loads the xml stored on the disk.
|
||||
/// Always loads the xml stored on the disk.
|
||||
/// </summary>
|
||||
public void ResetRagdoll(bool forceReload = false)
|
||||
public void ResetRagdoll()
|
||||
{
|
||||
RagdollParams.Reset(forceReload);
|
||||
RagdollParams.Reset(forceReload: true);
|
||||
ResetJoints();
|
||||
ResetLimbs();
|
||||
}
|
||||
@@ -577,7 +584,7 @@ namespace Barotrauma
|
||||
|
||||
public void AddJoint(JointParams jointParams)
|
||||
{
|
||||
if (!checkLimbIndex(jointParams.Limb2, "Limb1") || !checkLimbIndex(jointParams.Limb2, "Limb2"))
|
||||
if (!checkLimbIndex(jointParams.Limb1, "Limb1") || !checkLimbIndex(jointParams.Limb2, "Limb2"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -621,6 +628,7 @@ namespace Barotrauma
|
||||
{
|
||||
throw new Exception($"Failed to add a limb to the character \"{Character?.ConfigPath ?? "null"}\" (limb index {ID} out of bounds). The ragdoll file may be configured incorrectly.");
|
||||
}
|
||||
limbBodies.Add(limb.body.FarseerBody);
|
||||
Limbs[ID] = limb;
|
||||
Mass += limb.Mass;
|
||||
if (!limbDictionary.ContainsKey(limb.type)) { limbDictionary.Add(limb.type, limb); }
|
||||
@@ -632,6 +640,7 @@ namespace Barotrauma
|
||||
limb.body.FarseerBody.OnCollision += OnLimbCollision;
|
||||
Array.Resize(ref limbs, Limbs.Length + 1);
|
||||
Limbs[Limbs.Length - 1] = limb;
|
||||
limbBodies.Add(limb.body.FarseerBody);
|
||||
Mass += limb.Mass;
|
||||
if (!limbDictionary.ContainsKey(limb.type)) { limbDictionary.Add(limb.type, limb); }
|
||||
SetupDrawOrder();
|
||||
@@ -639,14 +648,14 @@ namespace Barotrauma
|
||||
|
||||
public void RemoveLimb(Limb limb)
|
||||
{
|
||||
if (!Limbs.Contains(limb)) return;
|
||||
if (!Limbs.Contains(limb)) { return; }
|
||||
|
||||
Limb[] newLimbs = new Limb[Limbs.Length - 1];
|
||||
|
||||
int i = 0;
|
||||
foreach (Limb existingLimb in Limbs)
|
||||
{
|
||||
if (existingLimb == limb) continue;
|
||||
if (existingLimb == limb) { continue; }
|
||||
newLimbs[i] = existingLimb;
|
||||
i++;
|
||||
}
|
||||
@@ -684,8 +693,10 @@ namespace Barotrauma
|
||||
LimbJoints = newJoints;
|
||||
}
|
||||
|
||||
SubtractMass(limb);
|
||||
limbBodies.Remove(limb.body.FarseerBody);
|
||||
limb.Remove();
|
||||
System.Diagnostics.Debug.Assert(!limbs.Contains(limb));
|
||||
System.Diagnostics.Debug.Assert(limbs.None(l => l.Removed));
|
||||
foreach (LimbJoint limbJoint in attachedJoints)
|
||||
{
|
||||
GameMain.World.Remove(limbJoint.Joint);
|
||||
@@ -819,9 +830,10 @@ namespace Barotrauma
|
||||
{
|
||||
if (character.DisableImpactDamageTimer > 0.0f) { return; }
|
||||
|
||||
if (f2.Body?.UserData is Item)
|
||||
if (f2.Body?.UserData is Item &&
|
||||
f2.Body.BodyType != BodyType.Static)
|
||||
{
|
||||
//no impact damage from items
|
||||
//no impact damage from items with a non-static body
|
||||
//items that can impact characters (melee weapons, projectiles) should handle the damage themselves
|
||||
return;
|
||||
}
|
||||
@@ -1073,7 +1085,7 @@ namespace Barotrauma
|
||||
Vector2 moveDir = hullDiff.LengthSquared() < 0.001f ? Vector2.UnitY : Vector2.Normalize(hullDiff);
|
||||
|
||||
//find a position 32 units away from the hull
|
||||
if (MathUtils.GetLineRectangleIntersection(
|
||||
if (MathUtils.GetLineWorldRectangleIntersection(
|
||||
newHull.WorldPosition,
|
||||
newHull.WorldPosition + moveDir * Math.Max(newHull.Rect.Width, newHull.Rect.Height),
|
||||
new Rectangle(newHull.WorldRect.X - 32, newHull.WorldRect.Y + 32, newHull.WorldRect.Width + 64, newHull.Rect.Height + 64),
|
||||
@@ -1294,6 +1306,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
|
||||
Collider.LinearVelocity = new Vector2(
|
||||
NetConfig.Quantize(Collider.LinearVelocity.X, -MaxVel, MaxVel, 12),
|
||||
NetConfig.Quantize(Collider.LinearVelocity.Y, -MaxVel, MaxVel, 12));
|
||||
|
||||
if (forceStanding)
|
||||
{
|
||||
inWater = false;
|
||||
@@ -1400,7 +1417,12 @@ namespace Barotrauma
|
||||
limb.Update(deltaTime);
|
||||
}
|
||||
|
||||
if (!inWater && character.AllowInput && levitatingCollider)
|
||||
bool isAttachedToController =
|
||||
character.SelectedItem?.GetComponent<Items.Components.Controller>() is { } controller &&
|
||||
controller.User == character &&
|
||||
controller.IsAttachedUser(controller.User);
|
||||
|
||||
if (!inWater && character.AllowInput && levitatingCollider && !isAttachedToController)
|
||||
{
|
||||
if (onGround && Collider.LinearVelocity.Y > -ImpactTolerance)
|
||||
{
|
||||
@@ -1433,7 +1455,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
// Falling -> ragdoll briefly if we are not moving at all, because we are probably stuck.
|
||||
if (Collider.LinearVelocity == Vector2.Zero)
|
||||
if (Collider.LinearVelocity == Vector2.Zero && !character.IsRemotePlayer)
|
||||
{
|
||||
character.IsRagdolled = true;
|
||||
if (character.IsBot)
|
||||
@@ -1448,6 +1470,30 @@ namespace Barotrauma
|
||||
forceNotStanding = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the logic that needs to run when the ragdoll is what controls the character's movement instead of the collider <see cref="ColliderControlsMovement"/>
|
||||
/// (making the collider stick to the ragdoll's main limb).
|
||||
/// </summary>
|
||||
protected void UpdateRagdollControlsMovement()
|
||||
{
|
||||
levitatingCollider = false;
|
||||
Collider.FarseerBody.FixedRotation = false;
|
||||
if (Collider.Enabled)
|
||||
{
|
||||
//deactivating the collider -> make the main limb inherit the collider's velocity because it'll control the movement now
|
||||
MainLimb.body.LinearVelocity = Collider.LinearVelocity;
|
||||
Collider.Enabled = false;
|
||||
}
|
||||
Collider.LinearVelocity = MainLimb.LinearVelocity;
|
||||
Collider.SetTransformIgnoreContacts(MainLimb.SimPosition, MainLimb.Rotation);
|
||||
//reset pull joints to prevent the character from "hanging" mid-air if pull joints had been active when the character was still moving
|
||||
//(except when dragging, then we need the pull joints)
|
||||
if (!Draggable || character.SelectedBy == null)
|
||||
{
|
||||
ResetPullJoints();
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckBodyInRest(float deltaTime)
|
||||
{
|
||||
if (SimplePhysicsEnabled) { return; }
|
||||
@@ -1910,7 +1956,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
Collider.SetTransform(simPosition, Collider.Rotation);
|
||||
Collider.SetTransformIgnoreContacts(simPosition, Collider.Rotation);
|
||||
}
|
||||
|
||||
if (!MathUtils.NearlyEqual(limbMoveAmount, Vector2.Zero))
|
||||
@@ -2009,7 +2055,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
limb.body.SetTransform(movePos, rotation);
|
||||
limb.body.SetTransformIgnoreContacts(movePos, rotation);
|
||||
limb.PullJointWorldAnchorB = limb.PullJointWorldAnchorA;
|
||||
limb.PullJointEnabled = false;
|
||||
}
|
||||
@@ -2084,7 +2130,7 @@ namespace Barotrauma
|
||||
partial void UpdateNetPlayerPositionProjSpecific(float deltaTime, float lowestSubPos);
|
||||
private void UpdateNetPlayerPosition(float deltaTime)
|
||||
{
|
||||
if (GameMain.NetworkMember == null) return;
|
||||
if (GameMain.NetworkMember == null) { return; }
|
||||
|
||||
float lowestSubPos = float.MaxValue;
|
||||
if (Submarine.Loaded.Any())
|
||||
@@ -2113,26 +2159,48 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Note that if there are multiple limbs of the same type, only the first (valid) limb is returned.
|
||||
/// </summary>
|
||||
public Limb GetLimb(LimbType limbType, bool excludeSevered = true)
|
||||
/// <param name="limbType"></param>
|
||||
/// <param name="excludeSevered">Should we filter out severed limbs?</param>
|
||||
/// <param name="useSecondaryType">Should we target limbs with secondary type instead of (primary) type?</param>
|
||||
/// <param name="excludeLimbsWithSecondaryType">Should we filter out all limbs with a secondary type something else than "None"?</param>
|
||||
/// <returns></returns>
|
||||
public Limb GetLimb(LimbType limbType, bool excludeSevered = true, bool excludeLimbsWithSecondaryType = false, bool useSecondaryType = false)
|
||||
{
|
||||
if (limbDictionary.TryGetValue(limbType, out Limb limb))
|
||||
Limb limb = null;
|
||||
if (!HasMultipleLimbsOfSameType && !useSecondaryType && !excludeLimbsWithSecondaryType)
|
||||
{
|
||||
if (excludeSevered && limb.IsSevered)
|
||||
// Faster method, but doesn't work when there's multiple limbs of the same type or if we want to seek/exclude limbs with different conditions.
|
||||
if (limbDictionary.TryGetValue(limbType, out limb))
|
||||
{
|
||||
limb = null;
|
||||
}
|
||||
if (limb.Removed)
|
||||
{
|
||||
limb = null;
|
||||
}
|
||||
if (excludeSevered && limb is { IsSevered: true } )
|
||||
{
|
||||
limb = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (limb == null && HasMultipleLimbsOfSameType)
|
||||
if (limb == null)
|
||||
{
|
||||
// Didn't find a (valid) limb of the matching type. If there's multiple limbs of the same type, check the other limbs.
|
||||
// Didn't seek or find a (valid) limb of the matching type. If there's multiple limbs of the same type, check the other limbs.
|
||||
foreach (var l in limbs)
|
||||
{
|
||||
if (l.type != limbType) { continue; }
|
||||
if (!excludeSevered || !l.IsSevered)
|
||||
if (l.Removed) { continue; }
|
||||
if (useSecondaryType)
|
||||
{
|
||||
limb = l;
|
||||
break;
|
||||
if (l.Params.SecondaryType != limbType) { continue; }
|
||||
}
|
||||
else if (l.type != limbType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (excludeSevered && l.IsSevered) { continue; }
|
||||
if (excludeLimbsWithSecondaryType && l.Params.SecondaryType != LimbType.None) { continue; }
|
||||
// Found a valid and match
|
||||
limb = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return limb;
|
||||
@@ -2220,6 +2288,7 @@ namespace Barotrauma
|
||||
}
|
||||
limbs = null;
|
||||
}
|
||||
limbBodies.Clear();
|
||||
|
||||
if (collider != null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user