예제 #1
0
        private void AddEatVerb(EntityUid uid, FoodComponent component, GetInteractionVerbsEvent ev)
        {
            if (component.CancelToken != null)
            {
                return;
            }

            if (uid == ev.User ||
                !ev.CanInteract ||
                !ev.CanAccess ||
                !EntityManager.TryGetComponent(ev.User, out SharedBodyComponent? body) ||
                !_bodySystem.TryGetComponentsOnMechanisms <StomachComponent>(ev.User, out var stomachs, body))
            {
                return;
            }

            if (EntityManager.TryGetComponent <MobStateComponent>(uid, out var mobState) && mobState.IsAlive())
            {
                return;
            }

            Verb verb = new()
            {
                Act = () =>
                {
                    TryUseFood(uid, ev.User, component);
                },
                Text     = Loc.GetString("food-system-verb-eat"),
                Priority = -1
            };

            ev.Verbs.Add(verb);
        }
        private void OnVerb(EntityUid uid, DockingComponent component, GetInteractionVerbsEvent args)
        {
            if (!args.CanInteract ||
                !args.CanAccess)
            {
                return;
            }

            Verb?verb;

            // TODO: Have it open the UI and have the UI do this.
            if (!component.Docked &&
                TryComp(uid, out PhysicsComponent? body) &&
                TryComp(uid, out TransformComponent? xform))
            {
                DockingComponent?otherDock = null;

                if (component.Enabled)
                {
                    otherDock = GetDockable(body, xform);
                }

                verb = new Verb
                {
                    Disabled = otherDock == null,
                    Text     = Loc.GetString("docking-component-dock"),
                    Act      = () =>
                    {
                        if (otherDock == null)
                        {
                            return;
                        }
                        TryDock(component, otherDock);
                    }
                };
            }
            else if (component.Docked)
            {
                verb = new Verb
                {
                    Disabled = !component.Docked,
                    Text     = Loc.GetString("docking-component-undock"),
                    Act      = () =>
                    {
                        if (component.DockedWith == null || !component.Enabled)
                        {
                            return;
                        }

                        Undock(component);
                    }
                };
            }
            else
            {
                return;
            }

            args.Verbs.Add(verb);
        }
        private void AddInsertVerbs(EntityUid uid, IdCardConsoleComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Using == null ||
                !args.CanAccess ||
                !args.CanInteract ||
                !args.Using.HasComponent <IdCardComponent>() ||
                !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            // Can we insert a privileged ID?
            if (component.PrivilegedIDEmpty)
            {
                Verb verb = new();
                verb.Act      = () => component.InsertIdFromHand(args.User, component.PrivilegedIdContainer, args.Hands !);
                verb.Category = VerbCategory.Insert;
                verb.Text     = Loc.GetString("id-card-console-privileged-id");
                args.Verbs.Add(verb);
            }

            // Can we insert a target ID?
            if (component.TargetIDEmpty)
            {
                Verb verb = new();
                verb.Act      = () => component.InsertIdFromHand(args.User, component.TargetIdContainer, args.Hands !);
                verb.Category = VerbCategory.Insert;
                verb.Text     = Loc.GetString("id-card-console-target-id");
                args.Verbs.Add(verb);
            }
        }
예제 #4
0
        private void AddInsertVerb(EntityUid uid, PowerCellSlotComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Using == null ||
                !args.CanAccess ||
                !args.CanInteract ||
                component.HasCell ||
                !args.Using.HasComponent <PowerCellComponent>() ||
                !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            Verb verb = new();

            verb.Text     = args.Using.Name;
            verb.Category = VerbCategory.Insert;
            verb.Act      = () => component.InsertCell(args.Using);
            args.Verbs.Add(verb);
        }
        private void AddInsertVerb(EntityUid uid, BaseCharger component, GetInteractionVerbsEvent args)
        {
            if (args.Using == null ||
                !args.CanAccess ||
                !args.CanInteract ||
                component.HasCell ||
                !component.IsEntityCompatible(args.Using) ||
                !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            Verb verb = new();

            verb.Text     = args.Using.Name;
            verb.Category = VerbCategory.Insert;
            verb.Act      = () => component.TryInsertItem(args.Using);
            args.Verbs.Add(verb);
        }
        private void AddToggleWieldVerb(EntityUid uid, WieldableComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Hands == null || !args.CanAccess || !args.CanInteract)
            {
                return;
            }

            // TODO VERB TOOLTIPS Make CanWield or some other function return string, set as verb tooltip and disable
            // verb. Or just don't add it to the list if the action is not executable.

            Verb verb = new();

            // TODO VERBS ICON + localization
            verb.Text = component.Wielded ? "Unwield" : "Wield";
            verb.Act  = component.Wielded
                ? () => AttemptUnwield(component.Owner.Uid, component, args.User)
                : () => AttemptWield(component.Owner.Uid, component, args.User);

            args.Verbs.Add(verb);
        }
예제 #7
0
        private void AddPickupVerb(EntityUid uid, SharedItemComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Hands == null ||
                args.Using != null ||
                !args.CanAccess ||
                !args.CanInteract ||
                !component.CanPickup(args.User, popup: false))
            {
                return;
            }

            Verb verb = new();

            verb.Act         = () => args.Hands.TryPutInActiveHandOrAny(args.Target);
            verb.IconTexture = "/Textures/Interface/VerbIcons/pickup.svg.192dpi.png";

            // if the item already in the user's inventory, change the text
            if (args.Target.TryGetContainer(out var container) && container.Owner == args.User)
            {
                verb.Text = Loc.GetString("pick-up-verb-get-data-text-inventory");
            }
예제 #8
0
        private void AddUnbuckleVerb(EntityUid uid, BuckleComponent component, GetInteractionVerbsEvent args)
        {
            if (!args.CanAccess || !args.CanInteract || !component.Buckled)
            {
                return;
            }

            Verb verb = new();

            verb.Act      = () => component.TryUnbuckle(args.User);
            verb.Category = VerbCategory.Unbuckle;

            if (args.Target == args.User && args.Using == null)
            {
                // A user is left clicking themselves with an empty hand, while buckled.
                // It is very likely they are trying to unbuckle themselves.
                verb.Priority = 1;
            }

            args.Verbs.Add(verb);
        }
예제 #9
0
        private void AddInsertVerb(EntityUid uid, PowerCellSlotComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Using is not {
                Valid : true
            } @using ||
                !args.CanAccess ||
                !args.CanInteract ||
                component.HasCell ||
                !EntityManager.HasComponent <PowerCellComponent>(@using) ||
                !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            Verb verb = new();

            verb.Text     = EntityManager.GetComponent <MetaDataComponent>(@using).EntityName;
            verb.Category = VerbCategory.Insert;
            verb.Act      = () => component.InsertCell(@using);
            args.Verbs.Add(verb);
        }
예제 #10
0
        private void AddUnbuckleVerb(EntityUid uid, BuckleComponent component, GetInteractionVerbsEvent args)
        {
            if (!args.CanAccess || !args.CanInteract || !component.Buckled)
            {
                return;
            }

            Verb verb = new();

            verb.Act         = () => component.TryUnbuckle(args.User);
            verb.Text        = Loc.GetString("verb-categories-unbuckle");
            verb.IconTexture = "/Textures/Interface/VerbIcons/unbuckle.svg.192dpi.png";

            if (args.Target == args.User && args.Using == null)
            {
                // A user is left clicking themselves with an empty hand, while buckled.
                // It is very likely they are trying to unbuckle themselves.
                verb.Priority = 1;
            }

            args.Verbs.Add(verb);
        }
예제 #11
0
        private void OnVerb(EntityUid uid, SuitSensorComponent component, GetInteractionVerbsEvent args)
        {
            // check if user can change sensor
            if (component.ControlsLocked)
            {
                return;
            }

            // standard interaction checks
            if (!args.CanAccess || !args.CanInteract || !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            args.Verbs.UnionWith(new[]
            {
                CreateVerb(uid, component, args.User, SuitSensorMode.SensorOff),
                CreateVerb(uid, component, args.User, SuitSensorMode.SensorBinary),
                CreateVerb(uid, component, args.User, SuitSensorMode.SensorVitals),
                CreateVerb(uid, component, args.User, SuitSensorMode.SensorCords)
            });
        }
        private void AddInsertVerb(EntityUid uid, ChemMasterComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Using == null ||
                !args.CanAccess ||
                !args.CanInteract ||
                component.HasBeaker ||
                !args.Using.HasComponent <FitsInDispenserComponent>() ||
                !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            Verb verb = new();

            verb.Act = () =>
            {
                component.BeakerContainer.Insert(args.Using);
                component.UpdateUserInterface();
            };
            verb.Category = VerbCategory.Insert;
            verb.Text     = args.Using.Name;
            args.Verbs.Add(verb);
        }
예제 #13
0
        private void AddPickupVerb(EntityUid uid, SharedItemComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Hands == null ||
                args.Using != null ||
                !args.CanAccess ||
                !args.CanInteract ||
                !args.Hands.CanPickupEntityToActiveHand(args.Target))
            {
                return;
            }

            Verb verb = new();

            verb.Act         = () => args.Hands.TryPickupEntityToActiveHand(args.Target);
            verb.IconTexture = "/Textures/Interface/VerbIcons/pickup.svg.192dpi.png";

            // if the item already in a container (that is not the same as the user's), then change the text.
            // this occurs when the item is in their inventory or in an open backpack
            args.User.TryGetContainer(out var userContainer);
            if (args.Target.TryGetContainer(out var container) && container != userContainer)
            {
                verb.Text = Loc.GetString("pick-up-verb-get-data-text-inventory");
            }
예제 #14
0
        private void AddInsertOtherVerb(EntityUid uid, MedicalScannerComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Using == null ||
                !args.CanAccess ||
                !args.CanInteract ||
                component.IsOccupied ||
                !component.CanInsert(args.Using))
            {
                return;
            }

            Verb verb = new();

            verb.Act      = () => component.InsertBody(args.Using);
            verb.Category = VerbCategory.Insert;
            verb.Text     = args.Using.Name;
            args.Verbs.Add(verb);
        }
예제 #15
0
        private void AddMagazineInteractionVerbs(EntityUid uid, ServerMagazineBarrelComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Hands == null ||
                !args.CanAccess ||
                !args.CanInteract)
            {
                return;
            }

            // Toggle bolt verb
            Verb toggleBolt = new();

            toggleBolt.Text = component.BoltOpen
                ? Loc.GetString("close-bolt-verb-get-data-text")
                : Loc.GetString("open-bolt-verb-get-data-text");
            toggleBolt.Act = () => component.BoltOpen = !component.BoltOpen;
            args.Verbs.Add(toggleBolt);

            // Are we holding a mag that we can insert?
            if (args.Using is not {
                Valid : true
            } @using ||
                !component.CanInsertMagazine(args.User, @using) ||
                !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            // Insert mag verb
            Verb insert = new();

            insert.Text     = EntityManager.GetComponent <MetaDataComponent>(@using).EntityName;
            insert.Category = VerbCategory.Insert;
            insert.Act      = () => component.InsertMagazine(args.User, @using);
            args.Verbs.Add(insert);
        }
예제 #16
0
        private void AddToggleBoltVerb(EntityUid uid, BoltActionBarrelComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Hands == null ||
                !args.CanAccess ||
                !args.CanInteract)
            {
                return;
            }

            Verb verb = new();

            verb.Text = component.BoltOpen
                ? Loc.GetString("close-bolt-verb-get-data-text")
                : Loc.GetString("open-bolt-verb-get-data-text");
            verb.Act = () => component.BoltOpen = !component.BoltOpen;
            args.Verbs.Add(verb);
        }
        private void AddInteractionVerbsVerbs(EntityUid uid, ItemSlotsComponent itemSlots, GetInteractionVerbsEvent args)
        {
            if (args.Hands == null || !args.CanAccess || !args.CanInteract)
            {
                return;
            }

            // If there are any slots that eject on left-click, add a "Take <item>" verb.
            if (_actionBlockerSystem.CanPickup(args.User))
            {
                foreach (var slot in itemSlots.Slots.Values)
                {
                    if (!slot.EjectOnInteract || !CanEject(slot))
                    {
                        continue;
                    }

                    var verbSubject = slot.Name != string.Empty
                        ? Loc.GetString(slot.Name)
                        : EntityManager.GetComponent <MetaDataComponent>(slot.Item !.Value).EntityName ?? string.Empty;

                    Verb takeVerb = new();
                    takeVerb.Act         = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true);
                    takeVerb.IconTexture = "/Textures/Interface/VerbIcons/pickup.svg.192dpi.png";

                    if (slot.EjectVerbText == null)
                    {
                        takeVerb.Text = Loc.GetString("take-item-verb-text", ("subject", verbSubject));
                    }
                    else
                    {
                        takeVerb.Text = Loc.GetString(slot.EjectVerbText);
                    }

                    args.Verbs.Add(takeVerb);
                }
            }

            // Next, add the insert-item verbs
            if (args.Using == null || !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            foreach (var slot in itemSlots.Slots.Values)
            {
                if (!CanInsert(uid, args.Using.Value, slot))
                {
                    continue;
                }

                var verbSubject = slot.Name != string.Empty
                    ? Loc.GetString(slot.Name)
                    : Name(args.Using.Value) ?? string.Empty;

                Verb insertVerb = new();
                insertVerb.Act = () => Insert(uid, slot, args.Using.Value, args.User, excludeUserAudio: true);

                if (slot.InsertVerbText != null)
                {
                    insertVerb.Text        = Loc.GetString(slot.InsertVerbText);
                    insertVerb.IconTexture = "/Textures/Interface/VerbIcons/insert.svg.192dpi.png";
                }
                else if (slot.EjectOnInteract)
                {
                    // Inserting/ejecting is a primary interaction for this entity. Instead of using the insert
                    // category, we will use a single "Place <item>" verb.
                    insertVerb.Text        = Loc.GetString("place-item-verb-text", ("subject", verbSubject));
                    insertVerb.IconTexture = "/Textures/Interface/VerbIcons/drop.svg.192dpi.png";
                }
                else
                {
                    insertVerb.Category = VerbCategory.Insert;
                    insertVerb.Text     = verbSubject;
                }

                args.Verbs.Add(insertVerb);
            }
        }
예제 #18
0
        private void OnConsoleInteract(EntityUid uid, ShuttleConsoleComponent component, GetInteractionVerbsEvent args)
        {
            if (!args.CanAccess ||
                !args.CanInteract)
            {
                return;
            }

            var xform = EntityManager.GetComponent <TransformComponent>(uid);

            // Maybe move mode onto the console instead?
            if (!_mapManager.TryGetGrid(xform.GridID, out var grid) ||
                !EntityManager.TryGetComponent(grid.GridEntityId, out ShuttleComponent? shuttle))
            {
                return;
            }

            Verb verb = new()
            {
                Text     = Loc.GetString("shuttle-mode-toggle"),
                Act      = () => ToggleShuttleMode(args.User, component, shuttle),
                Disabled = !xform.Anchored || EntityManager.TryGetComponent(uid, out ApcPowerReceiverComponent? receiver) && !receiver.Powered,
            };

            args.Verbs.Add(verb);
        }
        private void AddInsertVerbs(EntityUid uid, SharedItemSlotsComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Using == null ||
                !args.CanAccess ||
                !args.CanInteract ||
                !_actionBlockerSystem.CanDrop(args.User))
            {
                return;
            }

            foreach (var(slotName, slot) in component.Slots)
            {
                if (!CanInsertContent(args.Using, slot))
                {
                    continue;
                }

                Verb verb = new();
                verb.Text     = slot.Name != string.Empty ? slot.Name : args.Using.Name;
                verb.Category = VerbCategory.Insert;
                verb.Act      = () => InsertContent(component, slot, slotName, args.Using);
                args.Verbs.Add(verb);
            }
        }
        private void AddOpenUIVerbs(EntityUid uid, DisposalRouterComponent component, GetInteractionVerbsEvent args)
        {
            if (!args.CanAccess || !args.CanInteract)
            {
                return;
            }

            if (!args.User.TryGetComponent <ActorComponent>(out var actor))
            {
                return;
            }
            var player = actor.PlayerSession;

            Verb verb = new();

            verb.Text        = Loc.GetString("configure-verb-get-data-text");
            verb.IconTexture = "/Textures/Interface/VerbIcons/settings.svg.192dpi.png";
            verb.Act         = () => component.OpenUserInterface(actor);
            args.Verbs.Add(verb);
        }
예제 #21
0
        // TODO ECS BUCKLE/STRAP These 'Strap' verbs are an incestuous mess of buckle component and strap component
        // functions. Whenever these are fully ECSed, maybe do it in a way that allows for these verbs to be handled in
        // a sensible manner in a single system?

        private void AddStrapVerbs(EntityUid uid, StrapComponent component, GetInteractionVerbsEvent args)
        {
            if (args.Hands == null || !args.CanAccess || !args.CanInteract)
            {
                return;
            }

            // Note that for whatever bloody reason, buckle component has its own interaction range. Additionally, this
            // range can be set per-component, so we have to check a modified InRangeUnobstructed for every verb.

            // Add unstrap verbs for every strapped entity.
            foreach (var entity in component.BuckledEntities)
            {
                var buckledComp = entity.GetComponent <BuckleComponent>();

                if (!_interactionSystem.InRangeUnobstructed(args.User, args.Target, range: buckledComp.Range))
                {
                    continue;
                }

                Verb verb = new();
                verb.Act      = () => buckledComp.TryUnbuckle(args.User);
                verb.Category = VerbCategory.Unbuckle;
                if (entity == args.User)
                {
                    verb.Text = Loc.GetString("verb-self-target-pronoun");
                }
                else
                {
                    verb.Text = entity.Name;
                }

                // In the event that you have more than once entity with the same name strapped to the same object,
                // these two verbs will be identical according to Verb.CompareTo, and only one with actually be added to
                // the verb list. However this should rarely ever be a problem. If it ever is, it could be fixed by
                // appending an integer to verb.Text to distinguish the verbs.

                args.Verbs.Add(verb);
            }

            // Add a verb to buckle the user.
            if (args.User.TryGetComponent <BuckleComponent>(out var buckle) &&
                buckle.BuckledTo != component &&
                args.User != component.Owner &&
                component.HasSpace(buckle) &&
                _interactionSystem.InRangeUnobstructed(args.User, args.Target, range: buckle.Range))
            {
                Verb verb = new();
                verb.Act      = () => buckle.TryBuckle(args.User, args.Target);
                verb.Category = VerbCategory.Buckle;
                verb.Text     = Loc.GetString("verb-self-target-pronoun");
                args.Verbs.Add(verb);
            }

            // If the user is currently holding/pulling an entity that can be buckled, add a verb for that.
            if (args.Using != null &&
                args.Using.TryGetComponent <BuckleComponent>(out var usingBuckle) &&
                component.HasSpace(usingBuckle) &&
                _interactionSystem.InRangeUnobstructed(args.Using, args.Target, range: usingBuckle.Range))
            {
                // Check that the entity is unobstructed from the target (ignoring the user).
                bool Ignored(IEntity entity) => entity == args.User || entity == args.Target || entity == args.Using;

                if (!_interactionSystem.InRangeUnobstructed(args.Using, args.Target, usingBuckle.Range, predicate: Ignored))
                {
                    return;
                }

                Verb verb = new();
                verb.Act      = () => usingBuckle.TryBuckle(args.User, args.Target);
                verb.Category = VerbCategory.Buckle;
                verb.Text     = args.Using.Name;

                // If the used entity is a person being pulled, prioritize this verb. Conversely, if it is
                // just a held object, the user is probably just trying to sit down.
                verb.Priority = args.Using.HasComponent <ActorComponent>() ? 1 : -1;

                args.Verbs.Add(verb);
            }
        }