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