diff --git a/Barotrauma/Barotrauma.csproj b/Barotrauma/Barotrauma.csproj
index dd1990e0e..9eb20d525 100644
--- a/Barotrauma/Barotrauma.csproj
+++ b/Barotrauma/Barotrauma.csproj
@@ -875,6 +875,15 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
diff --git a/Barotrauma/Content/Characters/Charybdis/charybdis.xml b/Barotrauma/Content/Characters/Charybdis/charybdis.xml
index feba14971..7d2c5047e 100644
--- a/Barotrauma/Content/Characters/Charybdis/charybdis.xml
+++ b/Barotrauma/Content/Characters/Charybdis/charybdis.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/Barotrauma/Content/Characters/Coelanth/coelanth.xml b/Barotrauma/Content/Characters/Coelanth/coelanth.xml
index d5a1c1e57..7ab073ad5 100644
--- a/Barotrauma/Content/Characters/Coelanth/coelanth.xml
+++ b/Barotrauma/Content/Characters/Coelanth/coelanth.xml
@@ -26,7 +26,7 @@
-
+
diff --git a/Barotrauma/Content/Characters/Crawler/crawler.xml b/Barotrauma/Content/Characters/Crawler/crawler.xml
index 42bb69cee..abe5f087b 100644
--- a/Barotrauma/Content/Characters/Crawler/crawler.xml
+++ b/Barotrauma/Content/Characters/Crawler/crawler.xml
@@ -44,7 +44,7 @@
-
+
diff --git a/Barotrauma/Content/Characters/Mantis/mantis.xml b/Barotrauma/Content/Characters/Mantis/mantis.xml
index 202f16022..80d9781c5 100644
--- a/Barotrauma/Content/Characters/Mantis/mantis.xml
+++ b/Barotrauma/Content/Characters/Mantis/mantis.xml
@@ -61,7 +61,7 @@
-
+
diff --git a/Barotrauma/Content/Characters/Tigerthresher/tigerthresher.xml b/Barotrauma/Content/Characters/Tigerthresher/tigerthresher.xml
index c6e13719d..d63595917 100644
--- a/Barotrauma/Content/Characters/Tigerthresher/tigerthresher.xml
+++ b/Barotrauma/Content/Characters/Tigerthresher/tigerthresher.xml
@@ -30,7 +30,7 @@
-
+
diff --git a/Barotrauma/Content/Items/Weapons/explosives.xml b/Barotrauma/Content/Items/Weapons/explosives.xml
index 57c683c19..e6a87f07f 100644
--- a/Barotrauma/Content/Items/Weapons/explosives.xml
+++ b/Barotrauma/Content/Items/Weapons/explosives.xml
@@ -13,7 +13,7 @@
-
+
@@ -31,7 +31,7 @@
-
+
@@ -50,7 +50,7 @@
-
+
@@ -69,7 +69,7 @@
-
+
@@ -121,7 +121,7 @@
-
+
diff --git a/Barotrauma/Content/Items/Weapons/railgun.xml b/Barotrauma/Content/Items/Weapons/railgun.xml
index ec3636731..3f73ec4ee 100644
--- a/Barotrauma/Content/Items/Weapons/railgun.xml
+++ b/Barotrauma/Content/Items/Weapons/railgun.xml
@@ -83,7 +83,7 @@
-
+
@@ -115,10 +115,10 @@
-
+
-
+
diff --git a/Barotrauma/Content/Particles/ParticlePrefabs.xml b/Barotrauma/Content/Particles/ParticlePrefabs.xml
index 5c20ebdfb..ca9c81561 100644
--- a/Barotrauma/Content/Particles/ParticlePrefabs.xml
+++ b/Barotrauma/Content/Particles/ParticlePrefabs.xml
@@ -57,26 +57,22 @@
-
-
-
+ velocitychange="0.0, -0.1">
+
+
+
();
-
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
diff --git a/Barotrauma/Source/Characters/Character.cs b/Barotrauma/Source/Characters/Character.cs
index 86d5956b1..45ce8787d 100644
--- a/Barotrauma/Source/Characters/Character.cs
+++ b/Barotrauma/Source/Characters/Character.cs
@@ -1719,64 +1719,73 @@ namespace Barotrauma
public virtual AttackResult AddDamage(IDamageable attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound = false)
{
- var attackResult = AddDamage(worldPosition, attack.DamageType, attack.GetDamage(deltaTime), attack.GetBleedingDamage(deltaTime), attack.Stun, playSound, attack.TargetForce);
+ Limb limbHit = null;
+ var attackResult = AddDamage(worldPosition, attack.DamageType, attack.GetDamage(deltaTime), attack.GetBleedingDamage(deltaTime), attack.Stun, playSound, attack.TargetForce, out limbHit);
+ if (limbHit == null) return new AttackResult();
var attackingCharacter = attacker as Character;
if (attackingCharacter != null && attackingCharacter.AIController == null)
{
GameServer.Log(Name + " attacked by " + attackingCharacter.Name+". Damage: "+attackResult.Damage+" Bleeding damage: "+attackResult.Bleeding, ServerLog.MessageType.Attack);
}
+
+ if (GameMain.Client == null &&
+ health - attackResult.Damage <= minHealth && Rand.Range(0.0f, 1.0f) < attack.SeverLimbsProbability)
+ {
+ foreach (LimbJoint joint in AnimController.LimbJoints)
+ {
+ if (joint.CanBeSevered && (joint.LimbA == limbHit || joint.LimbB == limbHit))
+ {
+ AnimController.SeverLimbJoint(joint);
+
+ if (joint.LimbA == limbHit)
+ {
+ joint.LimbB.body.LinearVelocity += limbHit.LinearVelocity * 0.5f;
+ }
+ else
+ {
+ joint.LimbA.body.LinearVelocity += limbHit.LinearVelocity * 0.5f;
+ }
+ }
+ }
+ }
return attackResult;
}
public AttackResult AddDamage(Vector2 worldPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound, float attackForce = 0.0f)
{
+ Limb temp = null;
+ return AddDamage(worldPosition, damageType, amount, bleedingAmount, stun, playSound, attackForce, out temp);
+ }
+
+ public AttackResult AddDamage(Vector2 worldPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound, float attackForce, out Limb hitLimb)
+ {
+ hitLimb = null;
+
if (Removed) return new AttackResult();
SetStun(stun);
-
- Limb closestLimb = null;
+
float closestDistance = 0.0f;
foreach (Limb limb in AnimController.Limbs)
{
float distance = Vector2.Distance(worldPosition, limb.WorldPosition);
- if (closestLimb == null || distance < closestDistance)
+ if (hitLimb == null || distance < closestDistance)
{
- closestLimb = limb;
+ hitLimb = limb;
closestDistance = distance;
}
}
if (Math.Abs(attackForce) > 0.0f)
{
- closestLimb.body.ApplyForce((closestLimb.WorldPosition - worldPosition) * attackForce);
+ Vector2 diff = hitLimb.WorldPosition - worldPosition;
+ if (diff == Vector2.Zero) diff = Rand.Vector(1.0f);
+ hitLimb.body.ApplyForce(Vector2.Normalize(diff) * attackForce, hitLimb.SimPosition + ConvertUnits.ToSimUnits(diff));
}
- 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;
- }
- }
- }
- }
+ AttackResult attackResult = hitLimb.AddDamage(worldPosition, damageType, amount, bleedingAmount, playSound);
AddDamage(damageType == DamageType.Burn ? CauseOfDeath.Burn : causeOfDeath, attackResult.Damage, null);
diff --git a/Barotrauma/Source/Characters/Limb.cs b/Barotrauma/Source/Characters/Limb.cs
index 1853e2d9f..be5dcae0d 100644
--- a/Barotrauma/Source/Characters/Limb.cs
+++ b/Barotrauma/Source/Characters/Limb.cs
@@ -333,7 +333,7 @@ namespace Barotrauma
bool hitArmor = false;
float totalArmorValue = 0.0f;
- if (armorValue>0.0f && SectorHit(armorSector, position))
+ if (armorValue > 0.0f && SectorHit(armorSector, position))
{
hitArmor = true;
totalArmorValue += armorValue;
@@ -347,8 +347,7 @@ namespace Barotrauma
hitArmor = true;
totalArmorValue += wearable.WearableComponent.ArmorValue;
}
- }
-
+ }
if (hitArmor)
{
@@ -364,24 +363,19 @@ namespace Barotrauma
SoundPlayer.PlayDamageSound(damageSoundType, amount, position);
}
- float bloodAmount = hitArmor || bleedingAmount <= 0.0f ? 0 : (int)Math.Min((int)(amount * 2.0f), 20);
+ float bloodParticleAmount = hitArmor || bleedingAmount <= 0.0f ? 0 : (int)Math.Min(amount / 5, 10);
+ float bloodParticleSize = MathHelper.Clamp(amount / 50.0f, 0.1f, 1.0f);
- for (int i = 0; i < bloodAmount; i++)
+ for (int i = 0; i < bloodParticleAmount; i++)
{
- Vector2 particleVel = WorldPosition - position;
- if (particleVel != Vector2.Zero) particleVel = Vector2.Normalize(particleVel);
-
- GameMain.ParticleManager.CreateParticle("blood",
- WorldPosition,
- particleVel * Rand.Range(100.0f, 300.0f), 0.0f, character.AnimController.CurrentHull);
-
- if (i < bloodAmount / 5)
+ var blood = GameMain.ParticleManager.CreateParticle(inWater ? "waterblood" : "blood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
+ if (blood != null)
{
- GameMain.ParticleManager.CreateParticle("waterblood", WorldPosition, Rand.Vector(10), 0.0f, character.AnimController.CurrentHull);
+ blood.Size *= bloodParticleSize;
}
}
- damage += Math.Max(amount,bleedingAmount) / character.MaxHealth * 100.0f;
+ damage += Math.Max(amount, bleedingAmount) / character.MaxHealth * 100.0f;
return new AttackResult(amount, bleedingAmount, hitArmor);
}
diff --git a/Barotrauma/Source/Items/Components/Projectile.cs b/Barotrauma/Source/Items/Components/Projectile.cs
index 9408d1c80..999c35bb9 100644
--- a/Barotrauma/Source/Items/Components/Projectile.cs
+++ b/Barotrauma/Source/Items/Components/Projectile.cs
@@ -149,7 +149,7 @@ namespace Barotrauma.Items.Components
return false;
}
- AttackResult attackResult = new AttackResult(0.0f, 0.0f);
+ AttackResult attackResult = new AttackResult();
if (attack != null)
{
var submarine = f2.Body.UserData as Submarine;
diff --git a/Barotrauma/Source/Map/Explosion.cs b/Barotrauma/Source/Map/Explosion.cs
index 975dbd521..ff7ebeef5 100644
--- a/Barotrauma/Source/Map/Explosion.cs
+++ b/Barotrauma/Source/Map/Explosion.cs
@@ -81,7 +81,7 @@ namespace Barotrauma
if (force == 0.0f && attack.Stun == 0.0f && attack.GetDamage(1.0f) == 0.0f) return;
- ApplyExplosionForces(worldPosition, attack.Range, force, attack.GetDamage(1.0f), attack.Stun);
+ ApplyExplosionForces(worldPosition, attack, force);
if (flames && GameMain.Client == null)
{
@@ -132,9 +132,9 @@ namespace Barotrauma
yield return CoroutineStatus.Success;
}
- public static void ApplyExplosionForces(Vector2 worldPosition, float range, float force, float damage = 0.0f, float stun = 0.0f)
+ public static void ApplyExplosionForces(Vector2 worldPosition, Attack attack, float force)
{
- if (range <= 0.0f) return;
+ if (attack.Range <= 0.0f) return;
foreach (Character c in Character.CharacterList)
{
@@ -143,6 +143,7 @@ namespace Barotrauma
explosionPos = ConvertUnits.ToSimUnits(explosionPos);
+ bool wasDead = c.IsDead;
foreach (Limb limb in c.AnimController.Limbs)
{
float dist = Vector2.Distance(limb.WorldPosition, worldPosition);
@@ -151,24 +152,36 @@ namespace Barotrauma
//doesn't take the rotation of the limb into account, but should be accurate enough for this purpose
float limbRadius = Math.Max(Math.Max(limb.body.width * 0.5f, limb.body.height * 0.5f), limb.body.radius);
dist = Math.Max(0.0f, dist - FarseerPhysics.ConvertUnits.ToDisplayUnits(limbRadius));
+
+ if (dist > attack.Range) continue;
- if (dist > range) continue;
-
- float distFactor = 1.0f - dist / range;
+ float distFactor = 1.0f - dist / attack.Range;
//solid obstacles between the explosion and the limb reduce the effect of the explosion by 90%
if (Submarine.CheckVisibility(limb.SimPosition, explosionPos) != null) distFactor *= 0.1f;
c.AddDamage(limb.WorldPosition, DamageType.None,
- damage / c.AnimController.Limbs.Length * distFactor, 0.0f, stun * distFactor, false);
+ attack.GetDamage(1.0f) / c.AnimController.Limbs.Length * distFactor,
+ attack.GetBleedingDamage(1.0f) / c.AnimController.Limbs.Length * distFactor,
+ attack.Stun * distFactor,
+ false);
- if (limb.WorldPosition == worldPosition) continue;
-
- if (force > 0.0f)
+ if (limb.WorldPosition != worldPosition && force > 0.0f)
{
limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.WorldPosition - worldPosition) * distFactor * force);
}
- }
+ }
+
+ if (!wasDead && c.IsDead)
+ {
+ foreach (LimbJoint joint in c.AnimController.LimbJoints)
+ {
+ if (Rand.Range(0.0f, 1.0f) < attack.SeverLimbsProbability)
+ {
+ c.AnimController.SeverLimbJoint(joint);
+ }
+ }
+ }
}
}