diff --git a/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs b/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs index 9e06587891..3f18cc4953 100644 --- a/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs +++ b/Content.Client/GameObjects/EntitySystems/DragDropSystem.cs @@ -1,5 +1,6 @@ #nullable enable using System.Collections.Generic; +using System.Linq; using Content.Client.State; using Content.Client.Utility; using Content.Shared.GameObjects.EntitySystemMessages; @@ -313,22 +314,10 @@ namespace Content.Client.GameObjects.EntitySystems // check if it's able to be dropped on by current dragged entity var dropArgs = new DragDropEventArgs(_dragger, args.Coordinates, _dragDropHelper.Dragged, entity); - var valid = true; - var anyDragDrop = false; - var dragDropOn = new List(); - foreach (var comp in entity.GetAllComponents()) - { - anyDragDrop = true; + // TODO: Cache valid CanDragDrops + if (ValidDragDrop(dropArgs) != true) continue; - if (!comp.CanDragDropOn(dropArgs)) - { - valid = false; - dragDropOn.Add(comp); - } - } - - if (!valid || !anyDragDrop) continue; if (!dropArgs.InRangeUnobstructed(ignoreInsideBlocker: true)) { outOfRange = true; @@ -345,12 +334,6 @@ namespace Content.Client.GameObjects.EntitySystems draggable.Drop(dropArgs); - // Don't fail if it isn't handled as server may do something with it - foreach (var comp in dragDropOn) - { - if (!comp.DragDropOn(dropArgs)) continue; - } - _dragDropHelper.EndDrag(); return true; } @@ -394,21 +377,11 @@ namespace Content.Client.GameObjects.EntitySystems !inRangeSprite.Visible || pvsEntity == _dragDropHelper.Dragged) continue; - var valid = (bool?) null; // check if it's able to be dropped on by current dragged entity var dropArgs = new DragDropEventArgs(_dragger!, pvsEntity.Transform.Coordinates, _dragDropHelper.Dragged, pvsEntity); - foreach (var comp in pvsEntity.GetAllComponents()) - { - valid = comp.CanDragDropOn(dropArgs); - - if (valid.Value) - break; - } - - // Can't do anything so no highlight - if (!valid.HasValue) - continue; + var valid = ValidDragDrop(dropArgs); + if (valid == null) continue; // We'll do a final check given server-side does this before any dragdrop can take place. if (valid.Value) @@ -434,6 +407,43 @@ namespace Content.Client.GameObjects.EntitySystems _highlightedSprites.Clear(); } + /// + /// Are these args valid for drag-drop? + /// + /// + /// null if the target doesn't support IDragDropOn + private bool? ValidDragDrop(DragDropEventArgs eventArgs) + { + bool? valid = null; + + foreach (var comp in eventArgs.Target.GetAllComponents()) + { + if (!comp.CanDragDropOn(eventArgs)) + { + valid = false; + // dragDropOn.Add(comp); + continue; + } + + valid = true; + break; + } + + if (valid != true) return valid; + + // Need at least one IDraggable to return true or else we can't do shit + valid = false; + + foreach (var comp in eventArgs.User.GetAllComponents()) + { + if (!comp.CanDrop(eventArgs)) continue; + valid = true; + break; + } + + return valid; + } + public override void Update(float frameTime) { base.Update(frameTime); diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 5800574408..70905418b4 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -172,7 +172,6 @@ namespace Content.Client "Matchstick", "Matchbox", "BlockGameArcade", - "Butcherable", "Rehydratable", "Headset", "ComputerBoard", diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index 06d33b1413..0d72aed905 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -168,11 +168,6 @@ namespace Content.Server.GameObjects.Components.Buckle if (!to.TryGetComponent(out strap)) { - var message = Loc.GetString(Owner == user - ? "You can't buckle yourself there!" - : "You can't buckle {0:them} there!", Owner); - Owner.PopupMessage(user, message); - return false; } diff --git a/Content.Server/GameObjects/Components/Kitchen/KitchenSpikeComponent.cs b/Content.Server/GameObjects/Components/Kitchen/KitchenSpikeComponent.cs index 88294a663c..b3378cc852 100644 --- a/Content.Server/GameObjects/Components/Kitchen/KitchenSpikeComponent.cs +++ b/Content.Server/GameObjects/Components/Kitchen/KitchenSpikeComponent.cs @@ -5,6 +5,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameObjects; using Content.Server.Utility; +using Content.Shared.GameObjects.Components.Nutrition; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Kitchen; @@ -69,7 +70,7 @@ namespace Content.Server.GameObjects.Components.Kitchen return true; } - private bool Spikeable(IEntity user, IEntity victim, [NotNullWhen(true)] out ButcherableComponent? butcherable) + private bool Spikeable(IEntity user, IEntity victim, [NotNullWhen(true)] out SharedButcherableComponent? butcherable) { butcherable = null; @@ -93,7 +94,7 @@ namespace Content.Server.GameObjects.Components.Kitchen var victimUid = victim.Uid; if (_beingButchered.Contains(victimUid)) return; - ButcherableComponent? butcherable; + SharedButcherableComponent? butcherable; if (!Spikeable(user, victim, out butcherable)) return; @@ -143,8 +144,11 @@ namespace Content.Server.GameObjects.Components.Kitchen } Owner.PopupMessageEveryone(Loc.GetString("{0:theName} has forced {1:theName} onto the spike, killing them instantly!", user, victim)); + // TODO: Need to be able to leave them on the spike to do DoT, see ss13. victim.Delete(); - return; + + if (SpikeSound != null) + EntitySystem.Get().PlayFromEntity(SpikeSound, Owner); } SuicideKind ISuicideAct.Suicide(IEntity victim, IChatManager chat) diff --git a/Content.Server/GameObjects/Components/Kitchen/ButcherableComponent.cs b/Content.Shared/GameObjects/Components/Nutrition/SharedButcherableComponent.cs similarity index 66% rename from Content.Server/GameObjects/Components/Kitchen/ButcherableComponent.cs rename to Content.Shared/GameObjects/Components/Nutrition/SharedButcherableComponent.cs index 8a6fa76c03..e9e46952a8 100644 --- a/Content.Server/GameObjects/Components/Kitchen/ButcherableComponent.cs +++ b/Content.Shared/GameObjects/Components/Nutrition/SharedButcherableComponent.cs @@ -1,17 +1,18 @@ -#nullable enable +#nullable enable +using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; -namespace Content.Server.GameObjects.Components.Kitchen +namespace Content.Shared.GameObjects.Components.Nutrition { /// /// Indicates that the entity can be thrown on a kitchen spike for butchering. /// [RegisterComponent] - public class ButcherableComponent : Component + public class SharedButcherableComponent : Component, IDraggable { public override string Name => "Butcherable"; @@ -21,6 +22,10 @@ namespace Content.Server.GameObjects.Components.Kitchen [ViewVariables] [DataField("meat")] private string? _meatPrototype; + + public bool CanDrop(CanDropEventArgs args) + { + return true; + } } } - diff --git a/Content.Shared/Kitchen/SharedKitchenSpikeComponent.cs b/Content.Shared/Kitchen/SharedKitchenSpikeComponent.cs index be66710245..caaab10bee 100644 --- a/Content.Shared/Kitchen/SharedKitchenSpikeComponent.cs +++ b/Content.Shared/Kitchen/SharedKitchenSpikeComponent.cs @@ -1,4 +1,5 @@ #nullable enable +using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; @@ -12,22 +13,25 @@ namespace Content.Shared.Kitchen { public override string Name => "KitchenSpike"; - [ViewVariables] [DataField("delay")] protected float SpikeDelay = 10; + [ViewVariables] + [DataField("delay")] + protected float SpikeDelay = 12.0f; + + [ViewVariables(VVAccess.ReadWrite)] + [DataField("sound")] + protected string? SpikeSound = "/Audio/Effects/Fluids/splat.ogg"; bool IDragDropOn.CanDragDropOn(DragDropEventArgs eventArgs) { - if (!eventArgs.Dragged.TryGetComponent(out var state)) + if (eventArgs.User == eventArgs.Dragged || + !eventArgs.Dragged.TryGetComponent(out var state) || + (eventArgs.User.TryGetComponent(out SharedCombatModeComponent? combatMode) && !combatMode.IsInCombatMode)) { return false; } - // TODO: Wouldn't we just need the CanMove check? - if (state.IsDead() || state.IsCritical() || state.IsIncapacitated() || !ActionBlockerSystem.CanMove(eventArgs.Dragged)) - { - return true; - } - - return false; + // TODO: Once we get silicons need to check organic + return !state.IsDead(); } public abstract bool DragDropOn(DragDropEventArgs eventArgs); diff --git a/Resources/Prototypes/Entities/Constructible/Ground/kitchen.yml b/Resources/Prototypes/Entities/Constructible/Ground/kitchen.yml index 67c3ae246c..9f26f057b3 100644 --- a/Resources/Prototypes/Entities/Constructible/Ground/kitchen.yml +++ b/Resources/Prototypes/Entities/Constructible/Ground/kitchen.yml @@ -14,7 +14,7 @@ mask: - Impassable layer: - - Impassable + - MobImpassable - type: Sprite # temp to make clickmask work sprite: Constructible/Misc/kitchen.rsi