From: Kara Date: Sun, 24 Sep 2023 19:47:42 +0000 (-0700) Subject: Allow picking up items in combat mode (#20431) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=657e4d861efe700fc8340de1219ad2b91419c867;p=space-station-14.git Allow picking up items in combat mode (#20431) * Allow picking up items in combat mode * dont hardcode that --- diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 5770af23aa..36fe75fad7 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -152,6 +152,10 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem target = screen.GetClickedEntity(mousePos); } + // Don't light-attack if interaction will be handling this instead + if (Interaction.CombatModeCanHandInteract(entity, target)) + return; + RaisePredictiveEvent(new LightAttackEvent(GetNetEntity(target), GetNetEntity(weaponUid), GetNetCoordinates(coordinates))); } } diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs index 7d55035d5c..00c357814d 100644 --- a/Content.Shared/Interaction/SharedInteractionSystem.cs +++ b/Content.Shared/Interaction/SharedInteractionSystem.cs @@ -262,6 +262,35 @@ namespace Content.Shared.Interaction return !_tagSystem.HasTag(user, "BypassInteractionRangeChecks"); } + /// + /// Returns true if the specified entity should hand interact with the target instead of attacking + /// + /// The user interacting in combat mode + /// The target of the interaction + /// + public bool CombatModeCanHandInteract(EntityUid user, EntityUid? target) + { + // Always allow attack in these cases + if (target == null || !TryComp(user, out var hands) || hands.ActiveHand?.HeldEntity is not null) + return false; + + // Only eat input if: + // - Target isn't an item + // - Target doesn't cancel should-interact event + // This is intended to allow items to be picked up in combat mode, + // but to also allow items to force attacks anyway (like mobs which are items, e.g. mice) + if (!HasComp(target)) + return false; + + var combatEv = new CombatModeShouldHandInteractEvent(); + RaiseLocalEvent(target.Value, ref combatEv); + + if (combatEv.Cancelled) + return false; + + return true; + } + /// /// Resolves user interactions with objects. /// @@ -285,7 +314,8 @@ namespace Content.Shared.Interaction // TODO this needs to be handled better. This probably bypasses many complex can-interact checks in weird roundabout ways. if (_actionBlockerSystem.CanInteract(user, target)) { - UserInteraction(relay.RelayEntity.Value, coordinates, target, altInteract, checkCanInteract, checkAccess, checkCanUse); + UserInteraction(relay.RelayEntity.Value, coordinates, target, altInteract, checkCanInteract, + checkAccess, checkCanUse); return; } } @@ -293,10 +323,10 @@ namespace Content.Shared.Interaction if (target != null && Deleted(target.Value)) return; - if (!altInteract && TryComp(user, out CombatModeComponent? combatMode) && combatMode.IsInCombatMode) + if (!altInteract && TryComp(user, out var combatMode) && combatMode.IsInCombatMode) { - // Eat the input - return; + if (!CombatModeCanHandInteract(user, target)) + return; } if (!ValidateInteractAndFace(user, coordinates)) @@ -326,7 +356,7 @@ namespace Content.Shared.Interaction : !checkAccess || InRangeUnobstructed(user, target.Value); // permits interactions with wall mounted entities // Does the user have hands? - if (!TryComp(user, out HandsComponent? hands) || hands.ActiveHand == null) + if (!TryComp(user, out var hands) || hands.ActiveHand == null) { var ev = new InteractNoHandEvent(user, target, coordinates); RaiseLocalEvent(user, ev); @@ -341,6 +371,8 @@ namespace Content.Shared.Interaction } // empty-hand interactions + // combat mode hand interactions will always be true here -- since + // they check this earlier before returning in if (hands.ActiveHandEntity is not { } held) { if (inRangeUnobstructed && target != null) @@ -1164,4 +1196,12 @@ namespace Content.Shared.Interaction AltInteract = altInteract; } } + + /// + /// Raised directed by-ref on an item to determine if hand interactions should go through. + /// Defaults to allowing hand interactions to go through. Cancel to force the item to be attacked instead. + /// + /// Whether the hand interaction should be cancelled. + [ByRefEvent] + public record struct CombatModeShouldHandInteractEvent(bool Cancelled = false); } diff --git a/Content.Shared/Item/SharedItemSystem.cs b/Content.Shared/Item/SharedItemSystem.cs index bda92c500a..5f890af99f 100644 --- a/Content.Shared/Item/SharedItemSystem.cs +++ b/Content.Shared/Item/SharedItemSystem.cs @@ -75,7 +75,7 @@ public abstract class SharedItemSystem : EntitySystem private void OnHandInteract(EntityUid uid, ItemComponent component, InteractHandEvent args) { - if (args.Handled || _combatMode.IsInCombatMode(args.User)) + if (args.Handled) return; args.Handled = _handsSystem.TryPickup(args.User, uid, animateUser: false); diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs index f4537deede..340a1627d6 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs @@ -1,6 +1,7 @@ using Content.Shared.Bed.Sleep; using Content.Shared.Emoting; using Content.Shared.Hands; +using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; using Content.Shared.Item; @@ -36,6 +37,7 @@ public partial class MobStateSystem SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(CheckAct); SubscribeLocalEvent(OnSleepAttempt); + SubscribeLocalEvent(OnCombatModeShouldHandInteract); } private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state) @@ -139,5 +141,13 @@ public partial class MobStateSystem CheckAct(target, component, args); } + private void OnCombatModeShouldHandInteract(EntityUid uid, MobStateComponent component, ref CombatModeShouldHandInteractEvent args) + { + // Disallow empty-hand-interacting in combat mode + // for non-dead mobs + if (!IsDead(uid, component)) + args.Cancelled = true; + } + #endregion }