diff --git a/Content.Server/Content.Server.csproj b/Content.Server/Content.Server.csproj
index acd3bbd290..9d88b66adb 100644
--- a/Content.Server/Content.Server.csproj
+++ b/Content.Server/Content.Server.csproj
@@ -90,6 +90,7 @@
+
diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs
index 757e709fb0..5e4ca02e48 100644
--- a/Content.Server/EntryPoint.cs
+++ b/Content.Server/EntryPoint.cs
@@ -1,4 +1,5 @@
using Content.Server.GameObjects;
+using Content.Server.GameObjects.Components;
using Content.Server.GameObjects.Components.Power;
using Content.Server.GameObjects.Components.Interactable.Tools;
using Content.Server.Interfaces.GameObjects;
@@ -104,6 +105,7 @@ namespace Content.Server
factory.Register();
factory.Register();
factory.Register();
+ factory.Register();
factory.Register();
factory.Register();
diff --git a/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs
new file mode 100644
index 0000000000..54005c96cc
--- /dev/null
+++ b/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs
@@ -0,0 +1,36 @@
+using System.Collections.Generic;
+using Content.Server.GameObjects.Components.Projectiles;
+using Content.Shared.Physics;
+using SS14.Shared.Interfaces.GameObjects;
+using SS14.Shared.Interfaces.GameObjects.Components;
+
+namespace Content.Server.GameObjects.Components
+{
+ class ThrownItemComponent : ProjectileComponent, ICollideBehavior
+ {
+ public override string Name => "ThrownItem";
+
+ void ICollideBehavior.CollideWith(List collidedwith)
+ {
+ foreach (var entity in collidedwith)
+ {
+ if (entity.TryGetComponent(out DamageableComponent damage))
+ {
+ damage.TakeDamage(DamageType.Brute, 10);
+ }
+ }
+
+ // Stop colliding with mobs, this mimics not having enough velocity to do damage
+ // after impacting the first object.
+ // For realism this should actually be changed when the velocity of the object is less than a threshold.
+ // This would allow ricochets off walls, and weird gravity effects from slowing the object.
+ if (collidedwith.Count > 0 && Owner.TryGetComponent(out ICollidableComponent body))
+ {
+ body.CollisionMask &= (int) ~CollisionGroup.Mob;
+
+ // KYS, your job is finished.
+ Owner.RemoveComponent();
+ }
+ }
+ }
+}
diff --git a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs
index cc182a0df5..8b73f7ee00 100644
--- a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs
+++ b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs
@@ -14,7 +14,6 @@ using SS14.Server.GameObjects;
using SS14.Server.GameObjects.EntitySystems;
using SS14.Server.Interfaces.Player;
using SS14.Shared.Interfaces.GameObjects.Components;
-using SS14.Shared.GameObjects.Components.BoundingBox;
using SS14.Shared.Players;
namespace Content.Server.GameObjects.EntitySystems
diff --git a/Content.Server/GameObjects/EntitySystems/HandsSystem.cs b/Content.Server/GameObjects/EntitySystems/HandsSystem.cs
index 75f87135fe..8df657a3f7 100644
--- a/Content.Server/GameObjects/EntitySystems/HandsSystem.cs
+++ b/Content.Server/GameObjects/EntitySystems/HandsSystem.cs
@@ -1,6 +1,9 @@
using System;
+using Content.Server.GameObjects.Components;
using Content.Server.GameObjects.Components.Projectiles;
+using Content.Server.GameObjects.Components.Stack;
using Content.Shared.Input;
+using Content.Shared.Physics;
using SS14.Server.GameObjects;
using SS14.Server.GameObjects.EntitySystems;
using SS14.Server.Interfaces.Player;
@@ -8,7 +11,10 @@ using SS14.Shared.GameObjects;
using SS14.Shared.GameObjects.EntitySystemMessages;
using SS14.Shared.GameObjects.Systems;
using SS14.Shared.Input;
+using SS14.Shared.Interfaces.GameObjects;
using SS14.Shared.Interfaces.GameObjects.Components;
+using SS14.Shared.Interfaces.Timing;
+using SS14.Shared.IoC;
using SS14.Shared.Map;
using SS14.Shared.Maths;
using SS14.Shared.Players;
@@ -17,7 +23,7 @@ namespace Content.Server.GameObjects.EntitySystems
{
internal class HandsSystem : EntitySystem
{
- private const float ThrowSpeed = 1.0f;
+ private const float ThrowForce = 1.5f; // Throwing force of mobs in Newtons
///
public override void Initialize()
@@ -133,42 +139,66 @@ namespace Content.Server.GameObjects.EntitySystems
if (!plyEnt.TryGetComponent(out HandsComponent handsComp))
return;
- if (handsComp.CanDrop(handsComp.ActiveIndex))
+ if (!handsComp.CanDrop(handsComp.ActiveIndex))
+ return;
+
+ var throwEnt = handsComp.GetHand(handsComp.ActiveIndex).Owner;
+
+ // pop off an item, or throw the single item in hand.
+ if (!throwEnt.TryGetComponent(out StackComponent stackComp) || stackComp.Count < 2)
{
- var throwEnt = handsComp.GetHand(handsComp.ActiveIndex).Owner;
handsComp.Drop(handsComp.ActiveIndex, null);
-
- if (!throwEnt.TryGetComponent(out ProjectileComponent projComp))
- {
- projComp = throwEnt.AddComponent();
- }
-
- projComp.IgnoreEntity(plyEnt);
-
- var transform = plyEnt.Transform;
- var dirVec = (coords.ToWorld().Position - transform.WorldPosition).Normalized;
-
- if (!throwEnt.TryGetComponent(out PhysicsComponent physComp))
- {
- physComp = throwEnt.AddComponent();
- }
-
- physComp.LinearVelocity = dirVec * ThrowSpeed;
-
-
- var wHomoDir = Vector3.UnitX;
-
- transform.InvWorldMatrix.Transform(ref wHomoDir, out var lHomoDir);
-
- lHomoDir.Normalize();
- var angle = new Angle(lHomoDir.Xy);
-
- transform.LocalRotation = angle;
}
else
{
- return;
+ stackComp.Use(1);
+ throwEnt = throwEnt.EntityManager.ForceSpawnEntityAt(throwEnt.Prototype.ID, plyEnt.Transform.LocalPosition);
}
+
+ if (!throwEnt.TryGetComponent(out CollidableComponent colComp))
+ {
+ colComp = throwEnt.AddComponent();
+
+ if(!colComp.Running)
+ colComp.Startup();
+ }
+
+ colComp.CollisionEnabled = true;
+ colComp.CollisionLayer |= (int)CollisionGroup.Items;
+ colComp.CollisionMask |= (int)CollisionGroup.Grid;
+
+ // I can now collide with player, so that i can do damage.
+ colComp.CollisionMask |= (int) CollisionGroup.Mob;
+
+ if (!throwEnt.TryGetComponent(out ThrownItemComponent projComp))
+ {
+ projComp = throwEnt.AddComponent();
+ }
+
+ projComp.IgnoreEntity(plyEnt);
+
+ var transform = plyEnt.Transform;
+ var dirVec = (coords.ToWorld().Position - transform.WorldPosition).Normalized;
+
+ if (!throwEnt.TryGetComponent(out PhysicsComponent physComp))
+ {
+ physComp = throwEnt.AddComponent();
+ }
+
+ // TODO: Move this into PhysicsSystem, we need an ApplyForce function.
+ var a = ThrowForce / (float) Math.Max(0.001, physComp.Mass); // a = f / m
+
+ var timing = IoCManager.Resolve();
+ var spd = a / (1f / timing.TickRate); // acceleration is applied in 1 tick instead of 1 second, scale appropriately
+
+ physComp.LinearVelocity = dirVec * spd;
+
+ var wHomoDir = Vector3.UnitX;
+
+ transform.InvWorldMatrix.Transform(ref wHomoDir, out var lHomoDir);
+
+ lHomoDir.Normalize();
+ transform.LocalRotation = new Angle(lHomoDir.Xy);
}
}
}
diff --git a/Content.Shared/Content.Shared.csproj b/Content.Shared/Content.Shared.csproj
index 3de89ebeb9..782fb71ae0 100644
--- a/Content.Shared/Content.Shared.csproj
+++ b/Content.Shared/Content.Shared.csproj
@@ -71,6 +71,7 @@
+
diff --git a/Content.Shared/Physics/CollisionGroup.cs b/Content.Shared/Physics/CollisionGroup.cs
new file mode 100644
index 0000000000..08d481e19c
--- /dev/null
+++ b/Content.Shared/Physics/CollisionGroup.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Content.Shared.Physics
+{
+ ///
+ /// Defined collision groups for the physics system.
+ ///
+ [Flags]
+ public enum CollisionGroup
+ {
+ None = 0x0000,
+ Grid = 0x0001, // Walls
+ Mob = 0x0002, // Mobs, like the player or NPCs
+ Fixture = 0x0004, // wall fixtures, like APC or posters
+ Items = 0x008, // Items on the ground
+ }
+}
diff --git a/engine b/engine
index 307030ec8f..5ae665c3d2 160000
--- a/engine
+++ b/engine
@@ -1 +1 @@
-Subproject commit 307030ec8f46965315488cb1f7ec5b1c6db3cd73
+Subproject commit 5ae665c3d28ba227df6d9bfdaa12c16a6e6c2138