diff --git a/Content.Server/Fluids/Components/SpillableComponent.cs b/Content.Server/Fluids/Components/SpillableComponent.cs index fd5afd6e66..21c5e8a3a2 100644 --- a/Content.Server/Fluids/Components/SpillableComponent.cs +++ b/Content.Server/Fluids/Components/SpillableComponent.cs @@ -3,25 +3,13 @@ using Content.Shared.Interaction; using Robust.Shared.GameObjects; using Robust.Shared.Serialization.Manager.Attributes; -namespace Content.Server.Fluids.Components +namespace Content.Server.Fluids.Components; + +[RegisterComponent] +public class SpillableComponent : Component { - [RegisterComponent] - public class SpillableComponent : Component, IDropped - { - public override string Name => "Spillable"; + public override string Name => "Spillable"; - [DataField("solution")] - public string SolutionName = "puddle"; - - void IDropped.Dropped(DroppedEventArgs eventArgs) - { - if (!eventArgs.Intentional - && EntitySystem.Get().TryGetSolution(Owner.Uid, SolutionName, out var solutionComponent)) - { - EntitySystem.Get() - .Drain(Owner.Uid, solutionComponent, solutionComponent.DrainAvailable) - .SpillAt(Owner.Transform.Coordinates, "PuddleSmear"); - } - } - } + [DataField("solution")] + public string SolutionName = "puddle"; } diff --git a/Content.Server/Fluids/EntitySystems/SpillableSystem.cs b/Content.Server/Fluids/EntitySystems/SpillableSystem.cs new file mode 100644 index 0000000000..a780346bb4 --- /dev/null +++ b/Content.Server/Fluids/EntitySystems/SpillableSystem.cs @@ -0,0 +1,33 @@ +using Content.Server.Chemistry.EntitySystems; +using Content.Server.Construction.Components; +using Content.Server.Fluids.Components; +using Content.Shared.Examine; +using Content.Shared.Throwing; +using Content.Shared.Verbs; +using JetBrains.Annotations; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; + +namespace Content.Server.Fluids.EntitySystems; + +[UsedImplicitly] +public class SpillableSystem : EntitySystem +{ + [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(SpillOnLand); + } + + void SpillOnLand(EntityUid uid, SpillableComponent component, LandEvent args) { + if (args.User != null && _solutionContainerSystem.TryGetSolution(uid, component.SolutionName, out var solutionComponent)) + { + _solutionContainerSystem + .Drain(uid, solutionComponent, solutionComponent.DrainAvailable) + .SpillAt(EntityManager.GetComponent(uid).Coordinates, "PuddleSmear"); + } + } + +} diff --git a/Content.Server/Hands/Systems/HandsSystem.cs b/Content.Server/Hands/Systems/HandsSystem.cs index df33833923..6fc0496b96 100644 --- a/Content.Server/Hands/Systems/HandsSystem.cs +++ b/Content.Server/Hands/Systems/HandsSystem.cs @@ -166,18 +166,6 @@ namespace Content.Server.Hands.Systems hands.ActivateHeldEntity(msg.HandName); } - protected override void DropAllItemsInHands(IEntity entity, bool doMobChecks = true) - { - base.DropAllItemsInHands(entity, doMobChecks); - - if (!entity.TryGetComponent(out HandsComponent? hands)) return; - - foreach (var heldItem in hands.GetAllHeldItems()) - { - hands.Drop(heldItem.Owner, doMobChecks, false); - } - } - //TODO: Actually shows all items/clothing/etc. private void HandleExamined(EntityUid uid, HandsComponent component, ExaminedEvent args) { diff --git a/Content.Server/Standing/StandingStateSystem.cs b/Content.Server/Standing/StandingStateSystem.cs new file mode 100644 index 0000000000..d92da48a8a --- /dev/null +++ b/Content.Server/Standing/StandingStateSystem.cs @@ -0,0 +1,41 @@ +using Content.Server.Hands.Components; +using Content.Shared.Standing; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Maths; +using Robust.Shared.Random; + +namespace Content.Server.Standing; + +public class StandingStateSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + + private void FallOver(EntityUid uid, StandingStateComponent component, DropHandItemsEvent args) + { + var direction = EntityManager.TryGetComponent(uid, out PhysicsComponent? comp) ? comp.LinearVelocity / 50 : Vector2.Zero; + var dropAngle = _random.NextFloat(0.8f, 1.2f); + + if (EntityManager.TryGetComponent(uid, out HandsComponent? hands)) + { + foreach (var heldItem in hands.GetAllHeldItems()) + { + if (hands.Drop(heldItem.Owner)) + { + Throwing.ThrowHelper.TryThrow(heldItem.Owner, + _random.NextAngle().RotateVec(direction / dropAngle + + EntityManager.GetEntity(uid).Transform.WorldRotation.ToVec() / 50), + 0.5f * dropAngle * _random.NextFloat(-0.9f, 1.1f), + EntityManager.GetEntity(uid), 0); + } + } + } + } + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(FallOver); + } + +} diff --git a/Content.Server/Throwing/ThrowHelper.cs b/Content.Server/Throwing/ThrowHelper.cs index e268d50326..2c5af74fd6 100644 --- a/Content.Server/Throwing/ThrowHelper.cs +++ b/Content.Server/Throwing/ThrowHelper.cs @@ -33,7 +33,6 @@ namespace Content.Server.Throwing internal static void TryThrow(this IEntity entity, Vector2 direction, float strength = 1.0f, IEntity? user = null, float pushbackRatio = 1.0f) { if (entity.Deleted || - direction == Vector2.Zero || strength <= 0f || !entity.TryGetComponent(out PhysicsComponent? physicsComponent)) { @@ -61,7 +60,7 @@ namespace Content.Server.Throwing { physicsComponent.ApplyAngularImpulse(ThrowAngularImpulse); } - else + else if(direction != Vector2.Zero) { entity.Transform.LocalRotation = direction.ToWorldAngle() - Math.PI; } @@ -79,6 +78,7 @@ namespace Content.Server.Throwing if (time < FlyTime) { physicsComponent.BodyStatus = BodyStatus.OnGround; + EntitySystem.Get().LandComponent(comp); } else { diff --git a/Content.Shared/Hands/Components/SharedHandsComponent.cs b/Content.Shared/Hands/Components/SharedHandsComponent.cs index bbd3ad1776..45b8d984cc 100644 --- a/Content.Shared/Hands/Components/SharedHandsComponent.cs +++ b/Content.Shared/Hands/Components/SharedHandsComponent.cs @@ -146,7 +146,7 @@ namespace Content.Shared.Hands.Components private void RemoveHand(Hand hand) { - DropHeldEntityToFloor(hand, intentionalDrop: false); + DropHeldEntityToFloor(hand); hand.Container?.Shutdown(); Hands.Remove(hand); @@ -306,34 +306,34 @@ namespace Content.Shared.Hands.Components /// /// Tries to drop the contents of the active hand to the target location. /// - public bool TryDropActiveHand(EntityCoordinates targetDropLocation, bool doMobChecks = true, bool intentional = true) + public bool TryDropActiveHand(EntityCoordinates targetDropLocation, bool doMobChecks = true) { if (!TryGetActiveHand(out var hand)) return false; - return TryDropHeldEntity(hand, targetDropLocation, doMobChecks, intentional); + return TryDropHeldEntity(hand, targetDropLocation, doMobChecks); } /// /// Tries to drop the contents of a hand to the target location. /// - public bool TryDropHand(string handName, EntityCoordinates targetDropLocation, bool checkActionBlocker = true, bool intentional = true) + public bool TryDropHand(string handName, EntityCoordinates targetDropLocation, bool checkActionBlocker = true) { if (!TryGetHand(handName, out var hand)) return false; - return TryDropHeldEntity(hand, targetDropLocation, checkActionBlocker, intentional); + return TryDropHeldEntity(hand, targetDropLocation, checkActionBlocker); } /// /// Tries to drop a held entity to the target location. /// - public bool TryDropEntity(IEntity entity, EntityCoordinates coords, bool doMobChecks = true, bool intentional = true) + public bool TryDropEntity(IEntity entity, EntityCoordinates coords, bool doMobChecks = true) { if (!TryGetHandHoldingEntity(entity, out var hand)) return false; - return TryDropHeldEntity(hand, coords, doMobChecks, intentional); + return TryDropHeldEntity(hand, coords, doMobChecks); } /// @@ -369,23 +369,23 @@ namespace Content.Shared.Hands.Components /// /// Tries to drop the contents of a hand directly under the player. /// - public bool Drop(string handName, bool checkActionBlocker = true, bool intentionalDrop = true) + public bool Drop(string handName, bool checkActionBlocker = true) { if (!TryGetHand(handName, out var hand)) return false; - return TryDropHeldEntity(hand, Owner.Transform.Coordinates, checkActionBlocker, intentionalDrop); + return TryDropHeldEntity(hand, Owner.Transform.Coordinates, checkActionBlocker); } /// /// Tries to drop a held entity directly under the player. /// - public bool Drop(IEntity entity, bool checkActionBlocker = true, bool intentionalDrop = true) + public bool Drop(IEntity entity, bool checkActionBlocker = true) { if (!TryGetHandHoldingEntity(entity, out var hand)) return false; - return TryDropHeldEntity(hand, Owner.Transform.Coordinates, checkActionBlocker, intentionalDrop); + return TryDropHeldEntity(hand, Owner.Transform.Coordinates, checkActionBlocker); } /// @@ -467,7 +467,7 @@ namespace Content.Shared.Hands.Components /// /// Drops a hands contents to the target location. /// - public void DropHeldEntity(Hand hand, EntityCoordinates targetDropLocation, bool intentionalDrop = true) + public void DropHeldEntity(Hand hand, EntityCoordinates targetDropLocation) { var heldEntity = hand.HeldEntity; @@ -476,7 +476,7 @@ namespace Content.Shared.Hands.Components RemoveHeldEntityFromHand(hand); - EntitySystem.Get().DroppedInteraction(Owner, heldEntity, intentionalDrop); + EntitySystem.Get().DroppedInteraction(Owner, heldEntity); heldEntity.Transform.WorldPosition = GetFinalDropCoordinates(targetDropLocation); @@ -510,7 +510,7 @@ namespace Content.Shared.Hands.Components /// /// Tries to drop a hands contents to the target location. /// - private bool TryDropHeldEntity(Hand hand, EntityCoordinates location, bool checkActionBlocker, bool intentionalDrop = true) + private bool TryDropHeldEntity(Hand hand, EntityCoordinates location, bool checkActionBlocker) { if (!CanRemoveHeldEntityFromHand(hand)) return false; @@ -518,16 +518,16 @@ namespace Content.Shared.Hands.Components if (checkActionBlocker && !PlayerCanDrop()) return false; - DropHeldEntity(hand, location, intentionalDrop); + DropHeldEntity(hand, location); return true; } /// /// Drops the contents of a hand directly under the player. /// - private void DropHeldEntityToFloor(Hand hand, bool intentionalDrop = true) + private void DropHeldEntityToFloor(Hand hand) { - DropHeldEntity(hand, Owner.Transform.Coordinates, intentionalDrop); + DropHeldEntity(hand, Owner.Transform.Coordinates); } private bool CanPutHeldEntityIntoContainer(Hand hand, IContainer targetContainer, bool checkActionBlocker) diff --git a/Content.Shared/Hands/SharedHandsSystem.cs b/Content.Shared/Hands/SharedHandsSystem.cs index 9f7226d760..e3aeeb7a06 100644 --- a/Content.Shared/Hands/SharedHandsSystem.cs +++ b/Content.Shared/Hands/SharedHandsSystem.cs @@ -18,47 +18,6 @@ namespace Content.Shared.Hands SubscribeAllEvent(HandleSetHand); } - public void DropHandItems(IEntity entity, bool doMobChecks = true) - { - DropHandItems(entity.Uid, doMobChecks); - } - - public void DropHandItems(EntityUid uid, bool doMobChecks = true, SharedHandsComponent? hands = null) - { - if (!Resolve(uid, ref hands)) - return; - - DropHandItems(hands, doMobChecks); - } - - private void DropHandItems(SharedHandsComponent handsComponent, bool doMobChecks = true) - { - var msg = new DropHandItemsAttemptEvent(); - var entity = handsComponent.Owner; - var uid = entity.Uid; - var eventBus = EntityManager.EventBus; - - eventBus.RaiseLocalEvent(uid, msg); - - if (msg.Cancelled) - return; - - if (entity.TryGetContainerMan(out var containerManager)) - { - var parentMsg = new ContainedEntityDropHandItemsAttemptEvent(uid); - eventBus.RaiseLocalEvent(containerManager.OwnerUid, parentMsg); - - if (parentMsg.Cancelled) - return; - } - - DropAllItemsInHands(entity, doMobChecks); - } - - protected virtual void DropAllItemsInHands(IEntity entity, bool doMobChecks = true) - { - } - private static void HandleSetHand(RequestSetHandEvent msg, EntitySessionEventArgs eventArgs) { var entity = eventArgs.SenderSession.AttachedEntity; @@ -78,18 +37,6 @@ namespace Content.Shared.Hands } } - public sealed class ContainedEntityDropHandItemsAttemptEvent : CancellableEntityEventArgs - { - public EntityUid EntityUid { get; } - - public ContainedEntityDropHandItemsAttemptEvent(EntityUid uid) - { - EntityUid = uid; - } - } - - public sealed class DropHandItemsAttemptEvent : CancellableEntityEventArgs {} - [Serializable, NetSerializable] public class RequestSetHandEvent : EntityEventArgs { diff --git a/Content.Shared/Interaction/IDropped.cs b/Content.Shared/Interaction/IDropped.cs index 2b4e465556..8158524eaa 100644 --- a/Content.Shared/Interaction/IDropped.cs +++ b/Content.Shared/Interaction/IDropped.cs @@ -17,15 +17,12 @@ namespace Content.Shared.Interaction public class DroppedEventArgs : EventArgs { - public DroppedEventArgs(IEntity user, bool intentional) + public DroppedEventArgs(IEntity user) { User = user; - Intentional = intentional; } public IEntity User { get; } - - public bool Intentional { get; } } /// @@ -44,16 +41,10 @@ namespace Content.Shared.Interaction /// public EntityUid DroppedUid { get; } - /// - /// If the item was dropped intentionally. - /// - public bool Intentional { get; } - - public DroppedEvent(EntityUid user, EntityUid dropped, bool intentional) + public DroppedEvent(EntityUid user, EntityUid dropped) { UserUid = user; DroppedUid = dropped; - Intentional = intentional; } } } diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs index fe6e234e5f..fbdaf41e0a 100644 --- a/Content.Shared/Interaction/SharedInteractionSystem.cs +++ b/Content.Shared/Interaction/SharedInteractionSystem.cs @@ -658,11 +658,11 @@ namespace Content.Shared.Interaction /// Activates the Dropped behavior of an object /// Verifies that the user is capable of doing the drop interaction first /// - public bool TryDroppedInteraction(IEntity user, IEntity item, bool intentional) + public bool TryDroppedInteraction(IEntity user, IEntity item) { if (user == null || item == null || !_actionBlockerSystem.CanDrop(user.Uid)) return false; - DroppedInteraction(user, item, intentional); + DroppedInteraction(user, item); return true; } @@ -670,21 +670,21 @@ namespace Content.Shared.Interaction /// Calls Dropped on all components that implement the IDropped interface /// on an entity that has been dropped. /// - public void DroppedInteraction(IEntity user, IEntity item, bool intentional) + public void DroppedInteraction(IEntity user, IEntity item) { - var dropMsg = new DroppedEvent(user.Uid, item.Uid, intentional); + var dropMsg = new DroppedEvent(user.Uid, item.Uid); RaiseLocalEvent(item.Uid, dropMsg); if (dropMsg.Handled) return; - item.Transform.LocalRotation = intentional ? Angle.Zero : (_random.Next(0, 100) / 100f) * MathHelper.TwoPi; + item.Transform.LocalRotation = Angle.Zero; var comps = item.GetAllComponents().ToList(); // Call Land on all components that implement the interface foreach (var comp in comps) { - comp.Dropped(new DroppedEventArgs(user, intentional)); + comp.Dropped(new DroppedEventArgs(user)); } } #endregion diff --git a/Content.Shared/Standing/StandingStateSystem.cs b/Content.Shared/Standing/StandingStateSystem.cs index 7e5c3758e0..4e551dedae 100644 --- a/Content.Shared/Standing/StandingStateSystem.cs +++ b/Content.Shared/Standing/StandingStateSystem.cs @@ -43,7 +43,7 @@ namespace Content.Shared.Standing // and ultimately this is just to avoid boilerplate in Down callers + keep their behavior consistent. if (dropHeldItems && hands != null) { - _sharedHandsSystem.DropHandItems(uid, false, hands); + RaiseLocalEvent(uid, new DropHandItemsEvent(), false); } var msg = new DownAttemptEvent(); @@ -97,6 +97,10 @@ namespace Content.Shared.Standing } } + public sealed class DropHandItemsEvent : EventArgs + { + } + /// /// Subscribe if you can potentially block a down attempt. ///