diff --git a/Barotrauma/Content/Characters/Carrier/carrier.xml b/Barotrauma/Content/Characters/Carrier/carrier.xml
index 161ed1d71..268b41d76 100644
--- a/Barotrauma/Content/Characters/Carrier/carrier.xml
+++ b/Barotrauma/Content/Characters/Carrier/carrier.xml
@@ -54,10 +54,10 @@
-
-
+
+
-
+
diff --git a/Barotrauma/Content/Characters/Crawler/crawler.xml b/Barotrauma/Content/Characters/Crawler/crawler.xml
index 649123d8a..42bb69cee 100644
--- a/Barotrauma/Content/Characters/Crawler/crawler.xml
+++ b/Barotrauma/Content/Characters/Crawler/crawler.xml
@@ -71,21 +71,21 @@
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/Barotrauma/Content/Characters/Fractalguardian/fractalguardian.xml b/Barotrauma/Content/Characters/Fractalguardian/fractalguardian.xml
index 9cfe763b5..abb438036 100644
--- a/Barotrauma/Content/Characters/Fractalguardian/fractalguardian.xml
+++ b/Barotrauma/Content/Characters/Fractalguardian/fractalguardian.xml
@@ -49,14 +49,14 @@
-
+
-
+
-
+
-
-
+
+
diff --git a/Barotrauma/Content/Characters/Fractalguardian2/fractalguardian2.xml b/Barotrauma/Content/Characters/Fractalguardian2/fractalguardian2.xml
index d665dde72..c3841f2c4 100644
--- a/Barotrauma/Content/Characters/Fractalguardian2/fractalguardian2.xml
+++ b/Barotrauma/Content/Characters/Fractalguardian2/fractalguardian2.xml
@@ -43,11 +43,11 @@
-
-
+
+
-
-
+
+
diff --git a/Barotrauma/Content/Characters/Human/human.xml b/Barotrauma/Content/Characters/Human/human.xml
index 0f2e5d1ed..aaa479462 100644
--- a/Barotrauma/Content/Characters/Human/human.xml
+++ b/Barotrauma/Content/Characters/Human/human.xml
@@ -84,25 +84,25 @@
-
-
+
+
-
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/Barotrauma/Content/Characters/Human/humanhusk.xml b/Barotrauma/Content/Characters/Human/humanhusk.xml
index 303981949..9b8b82df6 100644
--- a/Barotrauma/Content/Characters/Human/humanhusk.xml
+++ b/Barotrauma/Content/Characters/Human/humanhusk.xml
@@ -91,27 +91,27 @@
-
-
+
+
-
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
diff --git a/Barotrauma/Content/Characters/Husk/husk.xml b/Barotrauma/Content/Characters/Husk/husk.xml
index 33952ffb0..3bd593b42 100644
--- a/Barotrauma/Content/Characters/Husk/husk.xml
+++ b/Barotrauma/Content/Characters/Husk/husk.xml
@@ -92,28 +92,28 @@
-
+
-
+
-
+
-
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/Barotrauma/Content/Characters/Mantis/mantis.xml b/Barotrauma/Content/Characters/Mantis/mantis.xml
index 5c337d46d..202f16022 100644
--- a/Barotrauma/Content/Characters/Mantis/mantis.xml
+++ b/Barotrauma/Content/Characters/Mantis/mantis.xml
@@ -81,22 +81,22 @@
-
+
-
+
-
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
diff --git a/Barotrauma/Content/Characters/Moloch/moloch.xml b/Barotrauma/Content/Characters/Moloch/moloch.xml
index 617384afd..30ab3d997 100644
--- a/Barotrauma/Content/Characters/Moloch/moloch.xml
+++ b/Barotrauma/Content/Characters/Moloch/moloch.xml
@@ -54,17 +54,17 @@
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/Barotrauma/Source/Characters/Animation/FishAnimController.cs b/Barotrauma/Source/Characters/Animation/FishAnimController.cs
index bce305169..5b3188d6c 100644
--- a/Barotrauma/Source/Characters/Animation/FishAnimController.cs
+++ b/Barotrauma/Source/Characters/Animation/FishAnimController.cs
@@ -260,7 +260,7 @@ namespace Barotrauma
if (limb.RefJointIndex>-1)
{
- RevoluteJoint refJoint = limbJoints[limb.RefJointIndex];
+ RevoluteJoint refJoint = LimbJoints[limb.RefJointIndex];
footPos.X = refJoint.WorldAnchorA.X;
}
footPos.X += limb.StepOffset.X * Dir;
diff --git a/Barotrauma/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/Source/Characters/Animation/HumanoidAnimController.cs
index d359ce3a0..2be6776b8 100644
--- a/Barotrauma/Source/Characters/Animation/HumanoidAnimController.cs
+++ b/Barotrauma/Source/Characters/Animation/HumanoidAnimController.cs
@@ -1012,7 +1012,7 @@ namespace Barotrauma
itemAngle = (torso.body.Rotation + holdAngle * Dir);
}
- Vector2 shoulderPos = limbJoints[2].WorldAnchorA;
+ Vector2 shoulderPos = LimbJoints[2].WorldAnchorA;
Vector2 transformedHoldPos = shoulderPos;
if (itemPos == Vector2.Zero || Anim == Animation.Climbing || usingController)
@@ -1071,7 +1071,7 @@ namespace Barotrauma
private void HandIK(Limb hand, Vector2 pos, float force = 1.0f)
{
- Vector2 shoulderPos = limbJoints[2].WorldAnchorA;
+ Vector2 shoulderPos = LimbJoints[2].WorldAnchorA;
Limb arm = (hand.type == LimbType.LeftHand) ? GetLimb(LimbType.LeftArm) : GetLimb(LimbType.RightArm);
diff --git a/Barotrauma/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/Source/Characters/Animation/Ragdoll.cs
index f069d5d1f..51cfb642d 100644
--- a/Barotrauma/Source/Characters/Animation/Ragdoll.cs
+++ b/Barotrauma/Source/Characters/Animation/Ragdoll.cs
@@ -28,17 +28,13 @@ namespace Barotrauma
if (frozen == value) return;
frozen = value;
-
- /*foreach (Limb l in Limbs)
- {
- l.body.PhysEnabled = !frozen;
- }*/
+
Collider.PhysEnabled = !frozen;
}
}
private Dictionary limbDictionary;
- public RevoluteJoint[] limbJoints;
+ public LimbJoint[] LimbJoints;
private bool simplePhysicsEnabled;
@@ -166,7 +162,7 @@ namespace Barotrauma
limb.body.Enabled = !simplePhysicsEnabled;
}
- foreach (RevoluteJoint joint in limbJoints)
+ foreach (RevoluteJoint joint in LimbJoints)
{
joint.Enabled = !simplePhysicsEnabled;
}
@@ -278,9 +274,9 @@ namespace Barotrauma
float scale = ToolBox.GetAttributeFloat(element, "scale", 1.0f);
- Limbs = new Limb[element.Elements("limb").Count()];
- limbJoints = new RevoluteJoint[element.Elements("joint").Count()];
- limbDictionary = new Dictionary();
+ Limbs = new Limb[element.Elements("limb").Count()];
+ LimbJoints = new LimbJoint[element.Elements("joint").Count()];
+ limbDictionary = new Dictionary();
headPosition = ToolBox.GetAttributeFloat(element, "headposition", 50.0f);
headPosition = ConvertUnits.ToSimUnits(headPosition);
@@ -346,7 +342,7 @@ namespace Barotrauma
UpdateCollisionCategories();
- foreach (var joint in limbJoints)
+ foreach (var joint in LimbJoints)
{
joint.BodyB.SetTransform(
joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB)*0.1f,
@@ -385,9 +381,8 @@ namespace Barotrauma
Vector2 limb2Pos = ToolBox.GetAttributeVector2(subElement, "limb2anchor", Vector2.Zero) * scale;
limb2Pos = ConvertUnits.ToSimUnits(limb2Pos);
- RevoluteJoint joint = new RevoluteJoint(Limbs[limb1ID].body.FarseerBody, Limbs[limb2ID].body.FarseerBody, limb1Pos, limb2Pos);
-
- joint.CollideConnected = false;
+ LimbJoint joint = new LimbJoint(Limbs[limb1ID], Limbs[limb2ID], limb1Pos, limb2Pos);
+ joint.CanBeSevered = ToolBox.GetAttributeBool(subElement, "canbesevered", false);
if (subElement.Attribute("lowerlimit") != null)
{
@@ -396,22 +391,18 @@ namespace Barotrauma
joint.UpperLimit = float.Parse(subElement.Attribute("upperlimit").Value) * ((float)Math.PI / 180.0f);
}
- joint.MotorEnabled = true;
- joint.MaxMotorTorque = 0.25f;
-
GameMain.World.AddJoint(joint);
- for (int i = 0; i < limbJoints.Length; i++)
+ for (int i = 0; i < LimbJoints.Length; i++)
{
- if (limbJoints[i] != null) continue;
+ if (LimbJoints[i] != null) continue;
- limbJoints[i] = joint;
+ LimbJoints[i] = joint;
return;
}
- Array.Resize(ref limbJoints, limbJoints.Length + 1);
- limbJoints[limbJoints.Length - 1] = joint;
-
+ Array.Resize(ref LimbJoints, LimbJoints.Length + 1);
+ LimbJoints[LimbJoints.Length - 1] = joint;
}
public void AddLimb(Limb limb)
@@ -531,6 +522,51 @@ namespace Barotrauma
}
}
+ public void SeverLimbJoint(LimbJoint limbJoint)
+ {
+ limbJoint.IsSevered = true;
+ limbJoint.Enabled = false;
+
+ List connectedLimbs = new List();
+ List checkedJoints = new List();
+
+ GetConnectedLimbs(connectedLimbs, checkedJoints, MainLimb);
+ foreach (Limb limb in Limbs)
+ {
+ if (!connectedLimbs.Contains(limb))
+ {
+ limb.IsSevered = true;
+ }
+ }
+
+ }
+
+ private void GetConnectedLimbs(List connectedLimbs, List checkedJoints, Limb limb)
+ {
+ connectedLimbs.Add(limb);
+
+ foreach (LimbJoint joint in LimbJoints)
+ {
+ if (joint.IsSevered || checkedJoints.Contains(joint)) continue;
+ if (joint.LimbA == limb)
+ {
+ if (!connectedLimbs.Contains(joint.LimbB))
+ {
+ checkedJoints.Add(joint);
+ GetConnectedLimbs(connectedLimbs, checkedJoints, joint.LimbB);
+ }
+ }
+ else if (joint.LimbB == limb)
+ {
+ if (!connectedLimbs.Contains(joint.LimbA))
+ {
+ checkedJoints.Add(joint);
+ GetConnectedLimbs(connectedLimbs, checkedJoints, joint.LimbA);
+ }
+ }
+ }
+ }
+
public virtual void Draw(SpriteBatch spriteBatch)
{
if (simplePhysicsEnabled) return;
@@ -559,13 +595,15 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), Color.Red, true, 0.01f);
}
- limb.body.DebugDraw(spriteBatch, inWater ? Color.Cyan : Color.White);
+ Color limbColor = inWater ? Color.Cyan : Color.White;
+ if (limb.IsSevered) limbColor = Color.Red;
+ limb.body.DebugDraw(spriteBatch, limbColor);
}
Collider.DebugDraw(spriteBatch, frozen ? Color.Red : (inWater ? Color.SkyBlue : Color.Gray));
GUI.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.ToString(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange);
- foreach (RevoluteJoint joint in limbJoints)
+ foreach (RevoluteJoint joint in LimbJoints)
{
Vector2 pos = ConvertUnits.ToDisplayUnits(joint.WorldAnchorA);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.White, true);
@@ -619,22 +657,22 @@ namespace Barotrauma
{
dir = (dir == Direction.Left) ? Direction.Right : Direction.Left;
- for (int i = 0; i < limbJoints.Length; i++)
+ for (int i = 0; i < LimbJoints.Length; i++)
{
- float lowerLimit = -limbJoints[i].UpperLimit;
- float upperLimit = -limbJoints[i].LowerLimit;
+ float lowerLimit = -LimbJoints[i].UpperLimit;
+ float upperLimit = -LimbJoints[i].LowerLimit;
- limbJoints[i].LowerLimit = lowerLimit;
- limbJoints[i].UpperLimit = upperLimit;
+ LimbJoints[i].LowerLimit = lowerLimit;
+ LimbJoints[i].UpperLimit = upperLimit;
- limbJoints[i].LocalAnchorA = new Vector2(-limbJoints[i].LocalAnchorA.X, limbJoints[i].LocalAnchorA.Y);
- limbJoints[i].LocalAnchorB = new Vector2(-limbJoints[i].LocalAnchorB.X, limbJoints[i].LocalAnchorB.Y);
+ LimbJoints[i].LocalAnchorA = new Vector2(-LimbJoints[i].LocalAnchorA.X, LimbJoints[i].LocalAnchorA.Y);
+ LimbJoints[i].LocalAnchorB = new Vector2(-LimbJoints[i].LocalAnchorB.X, LimbJoints[i].LocalAnchorB.Y);
}
foreach (Limb limb in Limbs)
{
- if (limb == null) continue;
+ if (limb == null || limb.IsSevered) continue;
if (limb.sprite != null)
{
@@ -665,6 +703,7 @@ namespace Barotrauma
Vector2 centerOfMass = Vector2.Zero;
foreach (Limb limb in Limbs)
{
+ if (limb.IsSevered) continue;
centerOfMass += limb.Mass * limb.SimPosition;
}
@@ -769,6 +808,7 @@ namespace Barotrauma
{
foreach (Limb limb in Limbs)
{
+ if (limb.IsSevered) continue;
if (limb.body.FarseerBody.ContactList == null) continue;
ContactEdge ce = limb.body.FarseerBody.ContactList;
@@ -781,6 +821,7 @@ namespace Barotrauma
foreach (Limb limb in Limbs)
{
+ if (limb.IsSevered) continue;
limb.body.LinearVelocity += velocityChange;
}
@@ -805,7 +846,7 @@ namespace Barotrauma
foreach (Limb limb in Limbs)
{
- if (limb.ignoreCollisions) continue;
+ if (limb.ignoreCollisions || limb.IsSevered) continue;
try
{
@@ -1145,6 +1186,7 @@ namespace Barotrauma
foreach (Limb limb in Limbs)
{
+ if (limb.IsSevered) continue;
//check visibility from the new position of the collider to the new position of this limb
Vector2 movePos = limb.SimPosition + limbMoveAmount;
@@ -1208,6 +1250,7 @@ namespace Barotrauma
//(in case the ragdoll has gotten stuck somewhere)
foreach (Limb limb in Limbs)
{
+ if (limb.IsSevered) continue;
limb.body.CollidesWith = Physics.CollisionNone;
}
@@ -1474,11 +1517,11 @@ namespace Barotrauma
b.Remove();
}
- foreach (RevoluteJoint joint in limbJoints)
+ foreach (RevoluteJoint joint in LimbJoints)
{
GameMain.World.RemoveJoint(joint);
}
- limbJoints = null;
+ LimbJoints = null;
list.Remove(this);
}
diff --git a/Barotrauma/Source/Characters/Character.cs b/Barotrauma/Source/Characters/Character.cs
index 0611d161f..86d5956b1 100644
--- a/Barotrauma/Source/Characters/Character.cs
+++ b/Barotrauma/Source/Characters/Character.cs
@@ -1755,10 +1755,31 @@ namespace Barotrauma
AttackResult attackResult = closestLimb.AddDamage(worldPosition, damageType, amount, bleedingAmount, playSound);
+ //sever joints connected to the limb if the character was killed
+ //with an attack stronger than 50% of the characters max health
+ //TODO: maybe add a "CanSever" option to attacks
+ if (health - attackResult.Damage <= minHealth && attackResult.Damage >= MaxHealth * 0.5f)
+ {
+ foreach (LimbJoint joint in AnimController.LimbJoints)
+ {
+ if (joint.CanBeSevered && (joint.LimbA == closestLimb || joint.LimbB == closestLimb))
+ {
+ AnimController.SeverLimbJoint(joint);
+
+ if (joint.LimbA == closestLimb)
+ {
+ joint.LimbB.body.LinearVelocity = closestLimb.LinearVelocity*0.5f;
+ }
+ else
+ {
+ joint.LimbA.body.LinearVelocity = closestLimb.LinearVelocity * 0.5f;
+ }
+ }
+ }
+ }
+
AddDamage(damageType == DamageType.Burn ? CauseOfDeath.Burn : causeOfDeath, attackResult.Damage, null);
-
- //health -= attackResult.Damage;
- //if (health <= 0.0f && damageType == DamageType.Burn) Kill(CauseOfDeath.Burn);
+
if (DoesBleed)
{
Bleeding += attackResult.Bleeding;
@@ -1832,7 +1853,7 @@ namespace Barotrauma
new Vector2(Rand.Range(-50f, 50f), Rand.Range(-100f, 50f)));
}
- foreach (var joint in AnimController.limbJoints)
+ foreach (var joint in AnimController.LimbJoints)
{
joint.LimitEnabled = false;
}
@@ -1895,7 +1916,7 @@ namespace Barotrauma
limb.pullJoint.Enabled = false;
}
- foreach (RevoluteJoint joint in AnimController.limbJoints)
+ foreach (RevoluteJoint joint in AnimController.LimbJoints)
{
joint.MotorEnabled = false;
}
@@ -1914,9 +1935,16 @@ namespace Barotrauma
Health = Math.Max(maxHealth * 0.1f, health);
- foreach (RevoluteJoint joint in AnimController.limbJoints)
+ foreach (LimbJoint joint in AnimController.LimbJoints)
{
joint.MotorEnabled = true;
+ joint.Enabled = true;
+ joint.IsSevered = false;
+ }
+
+ foreach (Limb limb in AnimController.Limbs)
+ {
+ limb.IsSevered = false;
}
if (GameMain.GameSession != null)
diff --git a/Barotrauma/Source/Characters/CharacterNetworking.cs b/Barotrauma/Source/Characters/CharacterNetworking.cs
index 0f52f1c80..83ef5b208 100644
--- a/Barotrauma/Source/Characters/CharacterNetworking.cs
+++ b/Barotrauma/Source/Characters/CharacterNetworking.cs
@@ -638,6 +638,19 @@ namespace Barotrauma
if (isDead)
{
msg.Write((byte)causeOfDeath);
+ List severedJointIndices = new List();
+ for (int i = 0; i < AnimController.LimbJoints.Length; i++)
+ {
+ if (AnimController.LimbJoints[i] != null && AnimController.LimbJoints[i].IsSevered)
+ {
+ severedJointIndices.Add(i);
+ }
+ }
+ msg.Write((byte)severedJointIndices.Count);
+ foreach (int jointIndex in severedJointIndices)
+ {
+ msg.Write((byte)jointIndex);
+ }
}
else
{
@@ -677,6 +690,7 @@ namespace Barotrauma
if (isDead)
{
causeOfDeath = (CauseOfDeath)msg.ReadByte();
+ byte severedLimbCount = msg.ReadByte();
if (causeOfDeath == CauseOfDeath.Pressure)
{
Implode(true);
@@ -685,6 +699,11 @@ namespace Barotrauma
{
Kill(causeOfDeath, true);
}
+ for (int i = 0; i < severedLimbCount; i++)
+ {
+ int severedJointIndex = msg.ReadByte();
+ AnimController.SeverLimbJoint(AnimController.LimbJoints[severedJointIndex]);
+ }
}
else
{
diff --git a/Barotrauma/Source/Characters/Limb.cs b/Barotrauma/Source/Characters/Limb.cs
index 246176e64..1853e2d9f 100644
--- a/Barotrauma/Source/Characters/Limb.cs
+++ b/Barotrauma/Source/Characters/Limb.cs
@@ -19,6 +19,25 @@ namespace Barotrauma
LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist
};
+ class LimbJoint : RevoluteJoint
+ {
+ public bool IsSevered;
+ public bool CanBeSevered;
+
+ public readonly Limb LimbA, LimbB;
+
+ public LimbJoint(Limb limbA, Limb limbB, Vector2 anchor1, Vector2 anchor2)
+ : base(limbA.body.FarseerBody, limbB.body.FarseerBody, anchor1, anchor2)
+ {
+ CollideConnected = false;
+ MotorEnabled = true;
+ MaxMotorTorque = 0.25f;
+
+ LimbA = limbA;
+ LimbB = limbB;
+ }
+ }
+
class Limb
{
private const float LimbDensity = 15;
@@ -66,7 +85,13 @@ namespace Barotrauma
private List wearingItems;
private Vector2 animTargetPos;
+
+ private float scale;
+ public float AttackTimer;
+
+ public bool IsSevered;
+
public bool DoesFlip
{
get { return doesFlip; }
@@ -141,49 +166,17 @@ namespace Barotrauma
get { return burnt; }
set { burnt = MathHelper.Clamp(value,0.0f,100.0f); }
}
-
- private float scale;
-
- public float AttackTimer;
-
- //public float Damage
- //{
- // get { return damage; }
- // set
- // {
- // damage = Math.Max(value, 0.0f);
- // if (damage >=maxHealth) Character.Kill();
- // }
- //}
-
- //public float MaxHealth
- //{
- // get { return maxHealth; }
- //}
-
- //public float Bleeding
- //{
- // get { return bleeding; }
- // set { bleeding = MathHelper.Clamp(value, 0.0f, 100.0f); }
- //}
-
+
public List WearingItems
{
get { return wearingItems; }
- set { wearingItems = value; }
}
-
- //public WearableSprite WearingItemSprite
- //{
- // get { return wearingItemSprite; }
- // set { wearingItemSprite = value; }
- //}
-
+
public Limb (Character character, XElement element, float scale = 1.0f)
{
this.character = character;
- WearingItems = new List();
+ wearingItems = new List();
dir = Direction.Right;
diff --git a/Barotrauma/Source/Screens/EditCharacterScreen.cs b/Barotrauma/Source/Screens/EditCharacterScreen.cs
index 5c70fbd7b..4417ad71b 100644
--- a/Barotrauma/Source/Screens/EditCharacterScreen.cs
+++ b/Barotrauma/Source/Screens/EditCharacterScreen.cs
@@ -217,7 +217,7 @@ namespace Barotrauma
}
jointList.ClearChildren();
- foreach (RevoluteJoint joint in character.AnimController.limbJoints)
+ foreach (RevoluteJoint joint in character.AnimController.LimbJoints)
{
Limb limb1 = (Limb)(joint.BodyA.UserData);
Limb limb2 = (Limb)(joint.BodyB.UserData);
@@ -236,7 +236,7 @@ namespace Barotrauma
private void DrawJoints(SpriteBatch spriteBatch, Limb limb, Vector2 limbBodyPos)
{
- foreach (var joint in editingCharacter.AnimController.limbJoints)
+ foreach (var joint in editingCharacter.AnimController.LimbJoints)
{
Vector2 jointPos = Vector2.Zero;