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); + } + } + } } }