diff --git a/Barotrauma/BarotraumaShared/Content/Items/Medical/medical.xml b/Barotrauma/BarotraumaShared/Content/Items/Medical/medical.xml
index e09b4a293..e7e20a0a4 100644
--- a/Barotrauma/BarotraumaShared/Content/Items/Medical/medical.xml
+++ b/Barotrauma/BarotraumaShared/Content/Items/Medical/medical.xml
@@ -26,7 +26,7 @@
-
+
diff --git a/Barotrauma/BarotraumaShared/Content/Items/Weapons/weapons.xml b/Barotrauma/BarotraumaShared/Content/Items/Weapons/weapons.xml
index 7a04b23a5..130d19aba 100644
--- a/Barotrauma/BarotraumaShared/Content/Items/Weapons/weapons.xml
+++ b/Barotrauma/BarotraumaShared/Content/Items/Weapons/weapons.xml
@@ -16,7 +16,7 @@
-
+
@@ -100,7 +100,7 @@
-
+
diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Projectile.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Projectile.cs
index 6eb8cd2ab..c5c079d2e 100644
--- a/Barotrauma/BarotraumaShared/Source/Items/Components/Projectile.cs
+++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Projectile.cs
@@ -12,9 +12,14 @@ namespace Barotrauma.Items.Components
{
class Projectile : ItemComponent
{
- private float launchImpulse;
+ //continuous collision detection is used while the projectile is moving faster than this
+ const float ContinuousCollisionThreshold = 5.0f;
- private bool doesStick;
+ //a duration during which the projectile won't drop from the body it's stuck to
+ private const float PersistentStickJointDuration = 1.0f;
+
+ private float launchImpulse;
+
private PrismaticJoint stickJoint;
private Body stickTarget;
@@ -24,6 +29,8 @@ namespace Barotrauma.Items.Components
public Character User;
+ private float persistentStickJointTimer;
+
[Serialize(10.0f, false)]
public float LaunchImpulse
{
@@ -39,10 +46,32 @@ namespace Barotrauma.Items.Components
}
[Serialize(false, false)]
+ //backwards compatibility, can stick to anything
public bool DoesStick
{
- get { return doesStick; }
- set { doesStick = value; }
+ get;
+ set;
+ }
+
+ [Serialize(false, false)]
+ public bool StickToCharacters
+ {
+ get;
+ set;
+ }
+
+ [Serialize(false, false)]
+ public bool StickToStructures
+ {
+ get;
+ set;
+ }
+
+ [Serialize(false, false)]
+ public bool StickToItems
+ {
+ get;
+ set;
}
[Serialize(false, false)]
@@ -106,7 +135,7 @@ namespace Barotrauma.Items.Components
IsActive = true;
- if (stickJoint == null || !doesStick) return;
+ if (stickJoint == null) return;
if (stickTarget != null)
{
@@ -182,7 +211,7 @@ namespace Barotrauma.Items.Components
//the raycast didn't hit anything -> the projectile flew somewhere outside the level and is permanently lost
if (!hitSomething)
{
- Item.Spawner.AddToRemoveQueue(item);
+ Entity.Spawner.AddToRemoveQueue(item);
}
}
@@ -190,8 +219,23 @@ namespace Barotrauma.Items.Components
{
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
- if (stickJoint != null &&
- (stickJoint.JointTranslation < stickJoint.LowerLimit * 0.9f || stickJoint.JointTranslation > stickJoint.UpperLimit * 0.9f))
+ if (item.body != null && item.body.FarseerBody.IsBullet)
+ {
+ if (item.body.LinearVelocity.LengthSquared() < ContinuousCollisionThreshold * ContinuousCollisionThreshold)
+ {
+ item.body.FarseerBody.IsBullet = false;
+ }
+ }
+
+ if (stickJoint == null) return;
+
+ if (persistentStickJointTimer > 0.0f)
+ {
+ persistentStickJointTimer -= deltaTime;
+ return;
+ }
+
+ if (stickJoint.JointTranslation < stickJoint.LowerLimit * 0.9f || stickJoint.JointTranslation > stickJoint.UpperLimit * 0.9f)
{
if (stickTarget != null)
{
@@ -218,7 +262,7 @@ namespace Barotrauma.Items.Components
stickJoint = null;
- IsActive = false;
+ if (!item.body.FarseerBody.IsBullet) IsActive = false;
}
}
@@ -265,12 +309,9 @@ namespace Barotrauma.Items.Components
ApplyStatusEffects(ActionType.OnUse, 1.0f, character);
ApplyStatusEffects(ActionType.OnImpact, 1.0f, character);
-
- IsActive = false;
-
+
item.body.FarseerBody.OnCollision -= OnProjectileCollision;
- item.body.FarseerBody.IsBullet = false;
item.body.CollisionCategories = Physics.CollisionItem;
item.body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
@@ -283,17 +324,20 @@ namespace Barotrauma.Items.Components
{
item.body.LinearVelocity *= 0.1f;
}
- else if (doesStick)
+ else if (Vector2.Dot(item.body.LinearVelocity, collisionNormal) < 0.0f &&
+ (DoesStick ||
+ (StickToCharacters && target.Body.UserData is Limb) ||
+ (StickToStructures && target.Body.UserData is Structure) ||
+ (StickToItems && target.Body.UserData is Item)))
{
Vector2 dir = new Vector2(
(float)Math.Cos(item.body.Rotation),
(float)Math.Sin(item.body.Rotation));
+
+ StickToTarget(target.Body, dir);
+ item.body.LinearVelocity *= 0.5f;
- if (Vector2.Dot(item.body.LinearVelocity, collisionNormal) < 0.0f)
- {
- StickToTarget(target.Body, dir);
- return Hitscan;
- }
+ return Hitscan;
}
else
{
@@ -336,6 +380,8 @@ namespace Barotrauma.Items.Components
stickJoint.UpperLimit = ConvertUnits.ToSimUnits(item.Sprite.size.X * 0.3f);
}
+ persistentStickJointTimer = PersistentStickJointDuration;
+
item.body.FarseerBody.IgnoreCollisionWith(targetBody);
stickTarget = targetBody;
GameMain.World.AddJoint(stickJoint);