diff --git a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs
index 5f7989073..acdb62496 100644
--- a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs
+++ b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs
@@ -5,7 +5,6 @@ using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Xml.Linq;
namespace Barotrauma
{
diff --git a/Barotrauma/BarotraumaShared/Content/Characters/Endworm/endworm.xml b/Barotrauma/BarotraumaShared/Content/Characters/Endworm/endworm.xml
index 085858637..ac631c8a0 100644
--- a/Barotrauma/BarotraumaShared/Content/Characters/Endworm/endworm.xml
+++ b/Barotrauma/BarotraumaShared/Content/Characters/Endworm/endworm.xml
@@ -54,12 +54,12 @@
-
+
-
+
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs b/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs
index 0f836eae8..6d6aa09cf 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs
@@ -21,6 +21,12 @@ namespace Barotrauma
Any = Blunt | Slash | Burn
}
+ public enum HitDetection
+ {
+ Distance,
+ Contact
+ }
+
struct AttackResult
{
public readonly float Damage;
@@ -39,90 +45,87 @@ namespace Barotrauma
partial class Attack
{
- public readonly float Range;
- public readonly float DamageRange;
- public readonly float Duration;
+ [Serialize(HitDetection.Distance, false)]
+ public HitDetection HitDetectionType { get; private set; }
- public readonly DamageType DamageType;
+ [Serialize(0.0f, false)]
+ public float Range { get; private set; }
- private readonly float structureDamage;
- private readonly float damage;
- private readonly float bleedingDamage;
+ [Serialize(0.0f, false)]
+ public float DamageRange { get; private set; }
- private readonly bool onlyHumans;
+ [Serialize(0.0f, false)]
+ public float Duration { get; private set; }
- private readonly List statusEffects;
+ [Serialize(DamageType.None, false)]
+ public DamageType DamageType { get; private set; }
- public readonly float Force;
+ [Serialize(0.0f, false)]
+ public float StructureDamage { get; private set; }
- public readonly float Torque;
+ [Serialize(0.0f, false)]
+ public float Damage { get; private set; }
- public readonly float TargetForce;
+ [Serialize(0.0f, false)]
+ public float BleedingDamage { get; private set; }
- public readonly float SeverLimbsProbability;
+ [Serialize(0.0f, false)]
+ public float Stun { get; private set; }
+
+ [Serialize(false, false)]
+ public bool OnlyHumans { get; private set; }
+
+ [Serialize(0.0f, false)]
+ public float Force { get; private set; }
+
+ [Serialize(0.0f, false)]
+ public float Torque { get; private set; }
+
+ [Serialize(0.0f, false)]
+ public float TargetForce { get; private set; }
+
+ [Serialize(0.0f, false)]
+ public float SeverLimbsProbability { get; private set; }
+
+ [Serialize(0.0f, false)]
+ public float Priority { get; private set; }
//the indices of the limbs Force is applied on
//(if none, force is applied only to the limb the attack is attached to)
public readonly List ApplyForceOnLimbs;
- public readonly float Stun;
-
- private float priority;
+ private readonly List statusEffects;
public float GetDamage(float deltaTime)
{
- return (Duration == 0.0f) ? damage : damage * deltaTime;
+ return (Duration == 0.0f) ? Damage : Damage * deltaTime;
}
public float GetBleedingDamage(float deltaTime)
{
- return (Duration == 0.0f) ? bleedingDamage : bleedingDamage * deltaTime;
+ return (Duration == 0.0f) ? BleedingDamage : BleedingDamage * deltaTime;
}
public float GetStructureDamage(float deltaTime)
{
- return (Duration == 0.0f) ? structureDamage : structureDamage * deltaTime;
+ return (Duration == 0.0f) ? StructureDamage : StructureDamage * deltaTime;
}
public Attack(float damage, float structureDamage, float bleedingDamage, float range = 0.0f)
{
Range = range;
DamageRange = range;
- this.damage = damage;
- this.structureDamage = structureDamage;
- this.bleedingDamage = bleedingDamage;
+ this.Damage = damage;
+ this.StructureDamage = structureDamage;
+ this.BleedingDamage = bleedingDamage;
}
public Attack(XElement element)
{
- try
- {
- DamageType = (DamageType)Enum.Parse(typeof(DamageType), element.GetAttributeString("damagetype", "None"), true);
- }
- catch
- {
- DamageType = DamageType.None;
- }
-
- damage = element.GetAttributeFloat("damage", 0.0f);
- structureDamage = element.GetAttributeFloat("structuredamage", 0.0f);
- bleedingDamage = element.GetAttributeFloat("bleedingdamage", 0.0f);
- Stun = element.GetAttributeFloat("stun", 0.0f);
-
- SeverLimbsProbability = element.GetAttributeFloat("severlimbsprobability", 0.0f);
-
- Force = element.GetAttributeFloat("force", 0.0f);
- TargetForce = element.GetAttributeFloat("targetforce", 0.0f);
- Torque = element.GetAttributeFloat("torque", 0.0f);
-
- Range = element.GetAttributeFloat("range", 0.0f);
+ SerializableProperty.DeserializeProperties(this, element);
+
DamageRange = element.GetAttributeFloat("damagerange", Range);
- Duration = element.GetAttributeFloat("duration", 0.0f);
-
- priority = element.GetAttributeFloat("priority", 1.0f);
-
- onlyHumans = element.GetAttributeBool("onlyhumans", false);
-
+
InitProjSpecific(element);
string limbIndicesStr = element.GetAttributeString("applyforceonlimbs", "");
@@ -158,7 +161,7 @@ namespace Barotrauma
public AttackResult DoDamage(Character attacker, IDamageable target, Vector2 worldPosition, float deltaTime, bool playSound = true)
{
- if (onlyHumans)
+ if (OnlyHumans)
{
Character character = target as Character;
if (character != null && character.ConfigPath != Character.HumanConfigFile) return new AttackResult();
@@ -189,7 +192,7 @@ namespace Barotrauma
{
if (targetLimb == null) return new AttackResult();
- if (onlyHumans)
+ if (OnlyHumans)
{
if (targetLimb.character != null && targetLimb.character.ConfigPath != Character.HumanConfigFile) return new AttackResult();
}
diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs b/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs
index c0d435e75..9c1e1e2ab 100644
--- a/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs
+++ b/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs
@@ -2,6 +2,7 @@
using Barotrauma.Items.Components;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
+using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using System;
@@ -479,12 +480,69 @@ namespace Barotrauma
body.ApplyTorque(Mass * character.AnimController.Dir * attack.Torque);
- if (dist < attack.DamageRange)
+ bool wasHit = false;
+
+ if (damageTarget != null)
+ {
+ switch (attack.HitDetectionType)
+ {
+ case HitDetection.Distance:
+ wasHit = dist < attack.DamageRange;
+ break;
+ case HitDetection.Contact:
+ List targetBodies = new List();
+ if (damageTarget is Character)
+ {
+ Character targetCharacter = (Character)damageTarget;
+ foreach (Limb limb in targetCharacter.AnimController.Limbs)
+ {
+ if (!limb.IsSevered && limb.body?.FarseerBody != null) targetBodies.Add(limb.body.FarseerBody);
+ }
+ }
+ else if (damageTarget is Structure)
+ {
+ Structure targetStructure = (Structure)damageTarget;
+
+ if (character.Submarine == null && targetStructure.Submarine != null)
+ {
+ targetBodies.Add(targetStructure.Submarine.PhysicsBody.FarseerBody);
+ }
+ else
+ {
+ targetBodies.AddRange(targetStructure.Bodies);
+ }
+ }
+ else if (damageTarget is Item)
+ {
+ Item targetItem = damageTarget as Item;
+ if (targetItem.body?.FarseerBody != null) targetBodies.Add(targetItem.body.FarseerBody);
+ }
+
+ if (targetBodies != null)
+ {
+ ContactEdge contactEdge = body.FarseerBody.ContactList;
+ while (contactEdge != null)
+ {
+ if (contactEdge.Contact != null &&
+ contactEdge.Contact.IsTouching &&
+ targetBodies.Any(b => b == contactEdge.Contact.FixtureA?.Body || b == contactEdge.Contact.FixtureB?.Body))
+ {
+ wasHit = true;
+ break;
+ }
+
+ contactEdge = contactEdge.Next;
+ }
+ }
+ break;
+ }
+ }
+
+ if (wasHit)
{
if (AttackTimer >= attack.Duration && damageTarget != null)
{
attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, (SoundTimer <= 0.0f));
-
SoundTimer = SoundInterval;
}
}
diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
index beb737fb9..86f51b512 100644
--- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
+++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs
@@ -89,6 +89,11 @@ namespace Barotrauma
get { return prefab.Body; }
}
+ public List Bodies
+ {
+ get { return bodies; }
+ }
+
public bool CastShadow
{
get { return prefab.CastShadow; }
@@ -651,23 +656,28 @@ namespace Barotrauma
Vector2 transformedPos = worldPosition;
if (Submarine != null) transformedPos -= Submarine.Position;
- int i = FindSectionIndex(transformedPos);
- if (i == -1) return new AttackResult(0.0f, 0.0f);
-
- float damageAmount = attack.GetStructureDamage(deltaTime);
-
- AddDamage(i, damageAmount, attacker);
+ float damageAmount = 0.0f;
+ for (int i = 0; i < SectionCount; i++)
+ {
+ if (Vector2.DistanceSquared(SectionPosition(i, true), worldPosition) <= attack.DamageRange * attack.DamageRange)
+ {
+ damageAmount = attack.GetStructureDamage(deltaTime);
+ AddDamage(i, damageAmount, attacker);
#if CLIENT
GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f);
+#endif
+ }
+ }
+#if CLIENT
if (playSound)// && !SectionBodyDisabled(i))
{
DamageSoundType damageSoundType = (attack.DamageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash;
SoundPlayer.PlayDamageSound(damageSoundType, damageAmount, worldPosition, tags: Tags);
}
#endif
-
+
return new AttackResult(damageAmount, 0.0f);
}