]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Allow picking up items in combat mode (#20431)
authorKara <lunarautomaton6@gmail.com>
Sun, 24 Sep 2023 19:47:42 +0000 (12:47 -0700)
committerGitHub <noreply@github.com>
Sun, 24 Sep 2023 19:47:42 +0000 (15:47 -0400)
* Allow picking up items in combat mode

* dont hardcode that

Content.Client/Weapons/Melee/MeleeWeaponSystem.cs
Content.Shared/Interaction/SharedInteractionSystem.cs
Content.Shared/Item/SharedItemSystem.cs
Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs

index 5770af23aa5e97338048dafbdbefa17f549f4f7a..36fe75fad7fcb952b35fabb7bcdce4cbe668db8f 100644 (file)
@@ -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)));
         }
     }
index 7d55035d5c1736e648178e564f2292822bd9565c..00c357814d7cb1eb0fb4a52a821d59ec4b327168 100644 (file)
@@ -262,6 +262,35 @@ namespace Content.Shared.Interaction
             return !_tagSystem.HasTag(user, "BypassInteractionRangeChecks");
         }
 
+        /// <summary>
+        ///     Returns true if the specified entity should hand interact with the target instead of attacking
+        /// </summary>
+        /// <param name="user">The user interacting in combat mode</param>
+        /// <param name="target">The target of the interaction</param>
+        /// <returns></returns>
+        public bool CombatModeCanHandInteract(EntityUid user, EntityUid? target)
+        {
+            // Always allow attack in these cases
+            if (target == null || !TryComp<HandsComponent>(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<ItemComponent>(target))
+                return false;
+
+            var combatEv = new CombatModeShouldHandInteractEvent();
+            RaiseLocalEvent(target.Value, ref combatEv);
+
+            if (combatEv.Cancelled)
+                return false;
+
+            return true;
+        }
+
         /// <summary>
         ///     Resolves user interactions with objects.
         /// </summary>
@@ -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<CombatModeComponent>(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<HandsComponent>(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;
         }
     }
+
+    /// <summary>
+    ///     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.
+    /// </summary>
+    /// <param name="Cancelled">Whether the hand interaction should be cancelled.</param>
+    [ByRefEvent]
+    public record struct CombatModeShouldHandInteractEvent(bool Cancelled = false);
 }
index bda92c500a1195c6a2c6693721fdd72a671394f9..5f890af99fdb41b5dd481b994dd2d4baa4aed181 100644 (file)
@@ -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);
index f4537deede4c2e5ab0e93fd7ae1bb87543674221..340a1627d6dfeff1ec4247c719e7cefe7afb0f90 100644 (file)
@@ -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<MobStateComponent, UpdateCanMoveEvent>(CheckAct);
         SubscribeLocalEvent<MobStateComponent, StandAttemptEvent>(CheckAct);
         SubscribeLocalEvent<MobStateComponent, TryingToSleepEvent>(OnSleepAttempt);
+        SubscribeLocalEvent<MobStateComponent, CombatModeShouldHandInteractEvent>(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
 }