/// <summary>
        ///     Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This
        ///     does not request verbs from the server.
        /// </summary>
        public SortedSet <Verb> GetLocalVerbs(EntityUid target, EntityUid user, List <Type> types, bool force = false)
        {
            SortedSet <Verb> verbs = new();

            // accessibility checks
            bool canAccess = false;

            if (force || target == user)
            {
                canAccess = true;
            }
            else if (EntityManager.EntityExists(target) && _interactionSystem.InRangeUnobstructed(user, target))
            {
                if (ContainerSystem.IsInSameOrParentContainer(user, target))
                {
                    canAccess = true;
                }
                else
                {
                    // the item might be in a backpack that the user has open
                    canAccess = _interactionSystem.CanAccessViaStorage(user, target);
                }
            }

            // A large number of verbs need to check action blockers. Instead of repeatedly having each system individually
            // call ActionBlocker checks, just cache it for the verb request.
            var canInteract = force || _actionBlockerSystem.CanInteract(user, target);

            EntityUid? @using = null;

            if (TryComp(user, out SharedHandsComponent? hands) && (force || _actionBlockerSystem.CanUseHeldEntity(user)))
            {
                @using = hands.ActiveHandEntity;

                // Check whether the "Held" entity is a virtual pull entity. If yes, set that as the entity being "Used".
                // This allows you to do things like buckle a dragged person onto a surgery table, without click-dragging
                // their sprite.

                if (TryComp(@using, out HandVirtualItemComponent? pull))
                {
                    @using = pull.BlockingEntity;
                }
            }

            if (types.Contains(typeof(InteractionVerb)))
            {
                var verbEvent = new GetVerbsEvent <InteractionVerb>(user, target, @using, hands, canInteract, canAccess);
                RaiseLocalEvent(target, verbEvent, true);
                verbs.UnionWith(verbEvent.Verbs);
            }

            if (types.Contains(typeof(UtilityVerb)) &&
                @using != null &&
                @using != target)
            {
                var verbEvent = new GetVerbsEvent <UtilityVerb>(user, target, @using, hands, canInteract, canAccess);
                RaiseLocalEvent(@using.Value, verbEvent, true); // directed at used, not at target
                verbs.UnionWith(verbEvent.Verbs);
            }

            if (types.Contains(typeof(InnateVerb)))
            {
                var verbEvent = new GetVerbsEvent <InnateVerb>(user, target, @using, hands, canInteract, canAccess);
                RaiseLocalEvent(user, verbEvent, true);
                verbs.UnionWith(verbEvent.Verbs);
            }

            if (types.Contains(typeof(AlternativeVerb)))
            {
                var verbEvent = new GetVerbsEvent <AlternativeVerb>(user, target, @using, hands, canInteract, canAccess);
                RaiseLocalEvent(target, verbEvent, true);
                verbs.UnionWith(verbEvent.Verbs);
            }

            if (types.Contains(typeof(ActivationVerb)))
            {
                var verbEvent = new GetVerbsEvent <ActivationVerb>(user, target, @using, hands, canInteract, canAccess);
                RaiseLocalEvent(target, verbEvent, true);
                verbs.UnionWith(verbEvent.Verbs);
            }

            if (types.Contains(typeof(ExamineVerb)))
            {
                var verbEvent = new GetVerbsEvent <ExamineVerb>(user, target, @using, hands, canInteract, canAccess);
                RaiseLocalEvent(target, verbEvent, true);
                verbs.UnionWith(verbEvent.Verbs);
            }

            // generic verbs
            if (types.Contains(typeof(Verb)))
            {
                var verbEvent = new GetVerbsEvent <Verb>(user, target, @using, hands, canInteract, canAccess);
                RaiseLocalEvent(target, verbEvent, true);
                verbs.UnionWith(verbEvent.Verbs);
            }

            return(verbs);
        }
        /// <summary>
        ///     Resolves user interactions with objects.
        /// </summary>
        /// <remarks>
        ///     Checks Whether combat mode is enabled and whether the user can actually interact with the given entity.
        /// </remarks>
        /// <param name="altInteract">Whether to use default or alternative interactions (usually as a result of
        /// alt+clicking). If combat mode is enabled, the alternative action is to perform the default non-combat
        /// interaction. Having an item in the active hand also disables alternative interactions.</param>
        public void UserInteraction(
            EntityUid user,
            EntityCoordinates coordinates,
            EntityUid?target,
            bool altInteract      = false,
            bool checkCanInteract = true,
            bool checkAccess      = true,
            bool checkCanUse      = true)
        {
            if (target != null && Deleted(target.Value))
            {
                return;
            }

            // TODO COMBAT Consider using alt-interact for advanced combat? maybe alt-interact disarms?
            if (!altInteract && TryComp(user, out SharedCombatModeComponent? combatMode) && combatMode.IsInCombatMode)
            {
                DoAttack(user, coordinates, false, target);
                return;
            }

            if (!ValidateInteractAndFace(user, coordinates))
            {
                return;
            }

            if (altInteract && target != null)
            {
                // Perform alternative interactions, using context menu verbs.
                // These perform their own range, can-interact, and accessibility checks.
                AltInteract(user, target.Value);
                return;
            }

            if (checkCanInteract && !_actionBlockerSystem.CanInteract(user, target))
            {
                return;
            }

            // Check if interacted entity is in the same container, the direct child, or direct parent of the user.
            // Also checks if the item is accessible via some storage UI (e.g., open backpack)
            if (checkAccess &&
                target != null &&
                !ContainerSystem.IsInSameOrParentContainer(user, target.Value) &&
                !CanAccessViaStorage(user, target.Value))
            {
                return;
            }

            // Does the user have hands?
            Hand?hand;

            if (!TryComp(user, out SharedHandsComponent? hands) || hands.ActiveHand == null)
            {
                return;
            }

            var inRangeUnobstructed = target == null
                ? !checkAccess || InRangeUnobstructed(user, coordinates)
                : !checkAccess || InRangeUnobstructed(user, target.Value); // permits interactions with wall mounted entities

            // empty-hand interactions
            if (hands.ActiveHandEntity is not EntityUid held)
            {
                if (inRangeUnobstructed && target != null)
                {
                    InteractHand(user, target.Value);
                }

                return;
            }

            // Can the user use the held entity?
            if (checkCanUse && !_actionBlockerSystem.CanUseHeldEntity(user))
            {
                return;
            }

            if (target == held)
            {
                UseInHandInteraction(user, target.Value, checkCanUse: false, checkCanInteract: false);
                return;
            }

            if (inRangeUnobstructed && target != null)
            {
                InteractUsing(
                    user,
                    held,
                    target.Value,
                    coordinates,
                    checkCanInteract: false,
                    checkCanUse: false);

                return;
            }

            InteractUsingRanged(
                user,
                held,
                target,
                coordinates,
                inRangeUnobstructed);
        }