예제 #1
0
        /// <summary>
        /// Uses an empty hand on an entity
        /// Finds components with the InteractHand interface and calls their function
        /// NOTE: Does not have an InRangeUnobstructed check
        /// </summary>
        public void InteractHand(EntityUid user, EntityUid target)
        {
            if (!_actionBlockerSystem.CanInteract(user))
            {
                return;
            }

            // all interactions should only happen when in range / unobstructed, so no range check is needed
            var message = new InteractHandEvent(user, target);

            RaiseLocalEvent(target, message);
            _adminLogSystem.Add(LogType.InteractHand, LogImpact.Low, $"{user} interacted with {target}");
            if (message.Handled)
            {
                return;
            }

            var interactHandEventArgs = new InteractHandEventArgs(user, target);

            var interactHandComps = EntityManager.GetComponents <IInteractHand>(target).ToList();

            foreach (var interactHandComp in interactHandComps)
            {
                // If an InteractHand returns a status completion we finish our interaction
#pragma warning disable 618
                if (interactHandComp.InteractHand(interactHandEventArgs))
#pragma warning restore 618
                {
                    return;
                }
            }

            // Else we run Activate.
            InteractionActivate(user, target);
        }
예제 #2
0
 private void OnInteracted(EntityUid uid, SignalSwitchComponent component, InteractHandEvent args)
 {
     component.State = !component.State;
     RaiseLocalEvent(uid, new InvokePortEvent("state", component.State), false);
     RaiseLocalEvent(uid, new InvokePortEvent("stateChange"), false);
     args.Handled = true;
 }
예제 #3
0
        private void OnInteractHand(EntityUid uid, ToiletComponent component, InteractHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            // trying get something from stash?
            if (component.LidOpen)
            {
                var gotItem = _secretStash.TryGetItem(uid, args.User);
                if (gotItem)
                {
                    args.Handled = true;
                    return;
                }
            }

            // just want to up/down seat?
            // check that nobody seats on seat right now
            if (EntityManager.TryGetComponent(uid, out StrapComponent? strap))
            {
                if (strap.BuckledEntities.Count != 0)
                {
                    return;
                }
            }

            ToggleToiletSeat(uid, component);
            args.Handled = true;
        }
예제 #4
0
        /// <summary>
        /// Uses an empty hand on an entity
        /// Finds components with the InteractHand interface and calls their function
        /// NOTE: Does not have any range or can-interact checks. These should all have been done before this function is called.
        /// </summary>
        public override void InteractHand(EntityUid user, EntityUid target)
        {
            // TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.

            // all interactions should only happen when in range / unobstructed, so no range check is needed
            var message = new InteractHandEvent(user, target);

            RaiseLocalEvent(target, message);
            _adminLogSystem.Add(LogType.InteractHand, LogImpact.Low, $"{ToPrettyString(user):user} interacted with {ToPrettyString(target):target}");
            if (message.Handled)
            {
                return;
            }

            var interactHandEventArgs = new InteractHandEventArgs(user, target);

            var interactHandComps = AllComps <IInteractHand>(target).ToList();

            foreach (var interactHandComp in interactHandComps)
            {
                // If an InteractHand returns a status completion we finish our interaction
#pragma warning disable 618
                if (interactHandComp.InteractHand(interactHandEventArgs))
#pragma warning restore 618
                {
                    return;
                }
            }

            // Else we run Activate.
            InteractionActivate(user, target,
                                checkCanInteract: false,
                                checkUseDelay: true,
                                checkAccess: false);
        }
        /// <summary>
        ///     If the cabinet is opened and has an entity, try and take it. Otherwise toggle the cabinet open/closed;
        /// </summary>
        private void OnInteractHand(EntityUid uid, ItemCabinetComponent comp, InteractHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            if (!EntityManager.TryGetComponent(uid, out SharedItemSlotsComponent itemSlots))
            {
                return;
            }

            if (!itemSlots.Slots.TryGetValue(comp.CabinetSlot, out var slot))
            {
                return;
            }

            if (comp.Opened && slot.HasEntity)
            {
                _itemSlotsSystem.TryEjectContent(uid, comp.CabinetSlot, args.User);
            }
            else
            {
                ToggleItemCabinet(uid, comp);
            }

            args.Handled = true;
        }
예제 #6
0
        private void OnInteractHand(EntityUid uid, EmitterComponent component, InteractHandEvent args)
        {
            args.Handled = true;
            if (EntityManager.TryGetComponent(uid, out LockComponent? lockComp) && lockComp.Locked)
            {
                component.Owner.PopupMessage(args.User, Loc.GetString("comp-emitter-access-locked", ("target", component.Owner)));
                return;
            }

            if (EntityManager.TryGetComponent(component.Owner, out PhysicsComponent? phys) && phys.BodyType == BodyType.Static)
            {
                if (!component.IsOn)
                {
                    SwitchOn(component);
                    component.Owner.PopupMessage(args.User, Loc.GetString("comp-emitter-turned-on", ("target", component.Owner)));
                }
                else
                {
                    SwitchOff(component);
                    component.Owner.PopupMessage(args.User, Loc.GetString("comp-emitter-turned-off", ("target", component.Owner)));
                }

                _adminLog.Add(LogType.Emitter,
                              component.IsOn ? LogImpact.Medium : LogImpact.High,
                              $"{ToPrettyString(args.User):player} toggled {ToPrettyString(uid):emitter}");
            }
            else
            {
                component.Owner.PopupMessage(args.User, Loc.GetString("comp-emitter-not-anchored", ("target", component.Owner)));
            }
        }
        /// <summary>
        /// Uses an empty hand on an entity
        /// Finds components with the InteractHand interface and calls their function
        /// NOTE: Does not have an InRangeUnobstructed check
        /// </summary>
        public void InteractHand(IEntity user, IEntity target)
        {
            if (!Get <ActionBlockerSystem>().CanInteract(user))
            {
                return;
            }

            // all interactions should only happen when in range / unobstructed, so no range check is needed
            var message = new InteractHandEvent(user, target);

            RaiseLocalEvent(target.Uid, message);
            if (message.Handled)
            {
                return;
            }

            var interactHandEventArgs = new InteractHandEventArgs(user, target);

            var interactHandComps = target.GetAllComponents <IInteractHand>().ToList();

            foreach (var interactHandComp in interactHandComps)
            {
                // If an InteractHand returns a status completion we finish our interaction
                if (interactHandComp.InteractHand(interactHandEventArgs))
                {
                    return;
                }
            }

            // Else we run Activate.
            InteractionActivate(user, target);
        }
예제 #8
0
        private void OnInteract(EntityUid uid, AirAlarmComponent component, InteractHandEvent args)
        {
            if (!_interactionSystem.InRangeUnobstructed(args.User, args.Target))
            {
                return;
            }

            if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
            {
                return;
            }

            if (EntityManager.TryGetComponent(uid, out WiresComponent wire) && wire.IsPanelOpen)
            {
                args.Handled = false;
                return;
            }

            if (EntityManager.TryGetComponent(uid, out ApcPowerReceiverComponent recv) && !recv.Powered)
            {
                return;
            }

            _uiSystem.GetUiOrNull(component.Owner, SharedAirAlarmInterfaceKey.Key)?.Open(actor.PlayerSession);
            component.ActivePlayers.Add(actor.PlayerSession.UserId);
            AddActiveInterface(uid);
            SendAddress(uid);
            SendAlarmMode(uid);
            SendThresholds(uid);
            SyncAllDevices(uid);
            SendAirData(uid);
        }
예제 #9
0
        private void OnInteractHand(EntityUid uid, EmitterComponent component, InteractHandEvent args)
        {
            args.Handled = true;
            if (EntityManager.TryGetComponent(uid, out LockComponent? lockComp) && lockComp.Locked)
            {
                component.Owner.PopupMessage(args.User, Loc.GetString("comp-emitter-access-locked", ("target", component.Owner)));
                return;
            }

            if (EntityManager.TryGetComponent(component.Owner, out PhysicsComponent? phys) && phys.BodyType == BodyType.Static)
            {
                if (!component.IsOn)
                {
                    SwitchOn(component);
                    component.Owner.PopupMessage(args.User, Loc.GetString("comp-emitter-turned-on", ("target", component.Owner)));
                }
                else
                {
                    SwitchOff(component);
                    component.Owner.PopupMessage(args.User, Loc.GetString("comp-emitter-turned-off", ("target", component.Owner)));
                }
            }
            else
            {
                component.Owner.PopupMessage(args.User, Loc.GetString("comp-emitter-not-anchored", ("target", component.Owner)));
            }
        }
        private void OnHandInteract(EntityUid uid, SharedItemComponent component, InteractHandEvent args)
        {
            if (args.Handled || !component.CanPickup)
            {
                return;
            }

            args.Handled = _handsSystem.TryPickup(args.User, uid, animateUser: false);
        }
예제 #11
0
        private void OnInteractHand(EntityUid uid, StrapComponent component, InteractHandEvent args)
        {
            if (!TryComp <BuckleComponent>(args.User, out var buckle))
            {
                return;
            }

            buckle.ToggleBuckle(args.User, uid);
        }
예제 #12
0
    private void OnAmmoBoxInteractHand(EntityUid uid, AmmoBoxComponent component, InteractHandEvent args)
    {
        if (args.Handled)
        {
            return;
        }

        TryUse(args.User, component);
    }
예제 #13
0
        private void OnInteractHand(EntityUid uid, KitchenSpikeComponent component, InteractHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            if (component.MeatParts > 0)
            {
                _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-knife-needed"), uid, Filter.Entities(args.User));
                args.Handled = true;
            }
        }
예제 #14
0
        private void OnInteractHand(EntityUid uid, PoweredLightComponent light, InteractHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            // check if light has bulb to eject
            var bulbUid = GetBulb(uid, light);

            if (bulbUid == null)
            {
                return;
            }

            // check if it's possible to apply burn damage to user
            var userUid = args.User;

            if (EntityManager.TryGetComponent(userUid, out HeatResistanceComponent? heatResist) &&
                EntityManager.TryGetComponent(bulbUid.Value, out LightBulbComponent? lightBulb))
            {
                // get users heat resistance
                var res = heatResist.GetHeatResistance();

                // check heat resistance against user
                var burnedHand = light.CurrentLit && res < lightBulb.BurningTemperature;
                if (burnedHand)
                {
                    // apply damage to users hands and show message with sound
                    var burnMsg = Loc.GetString("powered-light-component-burn-hand");
                    _popupSystem.PopupEntity(burnMsg, uid, Filter.Entities(userUid));

                    var damage = _damageableSystem.TryChangeDamage(userUid, light.Damage);

                    if (damage != null)
                    {
                        _logSystem.Add(LogType.Damaged,
                                       $"{ToPrettyString(args.User):user} burned their hand on {ToPrettyString(args.Target):target} and received {damage.Total:damage} damage");
                    }

                    SoundSystem.Play(Filter.Pvs(uid), light.BurnHandSound.GetSound(), uid);

                    args.Handled = true;
                    return;
                }
            }

            // all checks passed
            // just try to eject bulb
            args.Handled = EjectBulb(uid, userUid, light) != null;
        }
예제 #15
0
 private void OnInteractHand(EntityUid uid, ItemCabinetComponent comp, InteractHandEvent args)
 {
     args.Handled = true;
     if (comp.Opened)
     {
         if (comp.ItemContainer.ContainedEntity == null)
         {
             RaiseLocalEvent(uid, new ToggleItemCabinetEvent(), false);
             return;
         }
         RaiseLocalEvent(uid, new TryEjectItemCabinetEvent(args.User), false);
     }
     else
     {
         RaiseLocalEvent(uid, new ToggleItemCabinetEvent(), false);
     }
 }
예제 #16
0
        private void OnInteractHand(EntityUid uid, KnockedDownComponent knocked, InteractHandEvent args)
        {
            if (args.Handled || knocked.HelpTimer > 0f)
            {
                return;
            }

            // Set it to half the help interval so helping is actually useful...
            knocked.HelpTimer = knocked.HelpInterval / 2f;

            _statusEffectSystem.TryRemoveTime(uid, "KnockedDown", TimeSpan.FromSeconds(knocked.HelpInterval));

            SoundSystem.Play(Filter.Pvs(uid), knocked.StunAttemptSound.GetSound(), uid, AudioHelpers.WithVariation(0.05f));

            knocked.Dirty();

            args.Handled = true;
        }
예제 #17
0
        private void OnHandInteract(EntityUid uid, SharedItemComponent component, InteractHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            if (!TryComp(args.User, out SharedHandsComponent? hands))
            {
                return;
            }

            if (hands.ActiveHand == null)
            {
                return;
            }

            args.Handled = hands.TryPickupEntity(hands.ActiveHand, uid, false, animateUser: false);
        }
예제 #18
0
        /// <summary>
        ///     Attempt to take an item from a slot, if any are set to EjectOnInteract.
        /// </summary>
        private void OnInteractHand(EntityUid uid, ItemSlotsComponent itemSlots, InteractHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            foreach (var slot in itemSlots.Slots.Values)
            {
                if (slot.Locked || !slot.EjectOnInteract || slot.Item == null)
                {
                    continue;
                }

                args.Handled = true;
                TryEjectToHands(uid, slot, args.User);
                break;
            }
        }
예제 #19
0
        /// <summary>
        /// Toggles the state of the switch and sents a <see cref="DeviceNetworkConstants.CmdSetState"/> command with the
        /// <see cref="DeviceNetworkConstants.StateEnabled"/> value set to state.
        /// </summary>
        private void OnInteracted(EntityUid uid, ApcNetSwitchComponent component, InteractHandEvent args)
        {
            if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? networkComponent))
            {
                return;
            }

            component.State = !component.State;

            var payload = new NetworkPayload
            {
                [DeviceNetworkConstants.Command]      = DeviceNetworkConstants.CmdSetState,
                [DeviceNetworkConstants.StateEnabled] = component.State,
            };

            _deviceNetworkSystem.QueuePacket(uid, DeviceNetworkConstants.NullAddress, networkComponent.Frequency, payload, true);

            args.Handled = true;
        }
        private void OnPumpInteractHand(EntityUid uid, GasVolumePumpComponent pump, InteractHandEvent args)
        {
            if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
            {
                return;
            }

            if (EntityManager.GetComponent <TransformComponent>(pump.Owner).Anchored)
            {
                _userInterfaceSystem.TryOpen(uid, GasVolumePumpUiKey.Key, actor.PlayerSession);
                DirtyUI(uid, pump);
            }
            else
            {
                args.User.PopupMessageCursor(Loc.GetString("comp-gas-pump-ui-needs-anchor"));
            }

            args.Handled = true;
        }
예제 #21
0
        private void OnInteractHand(EntityUid uid, FireAlarmComponent component, InteractHandEvent args)
        {
            if (!_interactionSystem.InRangeUnobstructed(args.User, args.Target))
            {
                return;
            }

            if (EntityManager.TryGetComponent(args.User, out ActorComponent? actor) &&
                EntityManager.TryGetComponent(uid, out AtmosMonitorComponent? monitor) &&
                this.IsPowered(uid, EntityManager))
            {
                if (monitor.HighestAlarmInNetwork == AtmosMonitorAlarmType.Normal)
                {
                    _monitorSystem.Alert(uid, AtmosMonitorAlarmType.Danger);
                }
                else
                {
                    _monitorSystem.ResetAll(uid);
                }
            }
        }
예제 #22
0
        private void OnInteractHand(EntityUid uid, TwoWayLeverComponent component, InteractHandEvent args)
        {
            component.State = component.State switch
            {
                TwoWayLeverSignal.Middle => component.NextSignalLeft ? TwoWayLeverSignal.Left : TwoWayLeverSignal.Right,
                TwoWayLeverSignal.Right => TwoWayLeverSignal.Middle,
                TwoWayLeverSignal.Left => TwoWayLeverSignal.Middle,
                _ => throw new ArgumentOutOfRangeException()
            };

            if (component.State == TwoWayLeverSignal.Middle)
            {
                component.NextSignalLeft = !component.NextSignalLeft;
            }

            if (EntityManager.TryGetComponent <AppearanceComponent>(uid, out var appearanceComponent))
            {
                appearanceComponent.SetData(TwoWayLeverVisuals.State, component.State);
            }

            RaiseLocalEvent(uid, new InvokePortEvent("state", component.State));
            args.Handled = true;
        }
    }
예제 #23
0
 private void OnInteractHand(EntityUid uid, SignalButtonComponent component, InteractHandEvent args)
 {
     RaiseLocalEvent(uid, new InvokePortEvent("pressed"), false);
     args.Handled = true;
 }
예제 #24
0
 private void HandleInteractHand(EntityUid uid, BuckleComponent component, InteractHandEvent args)
 {
     args.Handled = component.TryUnbuckle(args.User);
 }
예제 #25
0
        private void OnInteractHand(EntityUid uid, PoweredLightComponent light, InteractHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            if (light.CancelToken != null)
            {
                return;
            }

            // check if light has bulb to eject
            var bulbUid = GetBulb(uid, light);

            if (bulbUid == null)
            {
                return;
            }

            // check if it's possible to apply burn damage to user
            var userUid = args.User;

            if (EntityManager.TryGetComponent(userUid, out HeatResistanceComponent? heatResist) &&
                EntityManager.TryGetComponent(bulbUid.Value, out LightBulbComponent? lightBulb))
            {
                // get users heat resistance
                var res = heatResist.GetHeatResistance();

                // check heat resistance against user
                var burnedHand = light.CurrentLit && res < lightBulb.BurningTemperature;
                if (burnedHand)
                {
                    // apply damage to users hands and show message with sound
                    var burnMsg = Loc.GetString("powered-light-component-burn-hand");
                    _popupSystem.PopupEntity(burnMsg, uid, Filter.Entities(userUid));

                    var damage = _damageableSystem.TryChangeDamage(userUid, light.Damage);

                    if (damage != null)
                    {
                        _adminLogger.Add(LogType.Damaged,
                                         $"{ToPrettyString(args.User):user} burned their hand on {ToPrettyString(args.Target):target} and received {damage.Total:damage} damage");
                    }

                    SoundSystem.Play(light.BurnHandSound.GetSound(), Filter.Pvs(uid), uid);

                    args.Handled = true;
                    return;
                }
            }


            //removing a broken/burned bulb, so allow instant removal
            if (TryComp <LightBulbComponent>(bulbUid.Value, out var bulb) && bulb.State != LightBulbState.Normal)
            {
                args.Handled = EjectBulb(uid, userUid, light) != null;
                return;
            }

            // removing a working bulb, so require a delay
            light.CancelToken = new CancellationTokenSource();
            _doAfterSystem.DoAfter(new DoAfterEventArgs((EntityUid)userUid, light.EjectBulbDelay, light.CancelToken.Token, uid)
            {
                BreakOnUserMove     = true,
                BreakOnDamage       = true,
                BreakOnStun         = true,
                TargetFinishedEvent = new EjectBulbCompleteEvent()
                {
                    Component = light,
                    User      = userUid,
                    Target    = uid,
                },
                TargetCancelledEvent = new EjectBulbCancelledEvent()
                {
                    Component = light,
                }
            });

            args.Handled = true;
        }
예제 #26
0
        private void OnCanisterInteractHand(EntityUid uid, GasCanisterComponent component, InteractHandEvent args)
        {
            if (!args.User.TryGetComponent(out ActorComponent? actor))
            {
                return;
            }

            component.Owner.GetUIOrNull(GasCanisterUiKey.Key)?.Open(actor.PlayerSession);
            args.Handled = true;
        }
    private void OnInteractHand(EntityUid uid, InteractionPopupComponent component, InteractHandEvent args)
    {
        if (args.Handled)
        {
            return;
        }

        var curTime = _gameTiming.CurTime;

        if (curTime < component.LastInteractTime + component.InteractDelay)
        {
            return;
        }

        if (TryComp <MobStateComponent>(uid, out var state) && // if it has a MobStateComponent,
            !state.IsAlive())                              // AND if that state is not Alive (e.g. dead/incapacitated/critical)
        {
            return;
        }

        string msg = "";   // Stores the text to be shown in the popup message
        string?sfx = null; // Stores the filepath of the sound to be played

        if (_random.Prob(component.SuccessChance))
        {
            if (component.InteractSuccessString != null)
            {
                msg = Loc.GetString(component.InteractSuccessString, ("target", uid)); // Success message (localized).
            }
            if (component.InteractSuccessSound != null)
            {
                sfx = component.InteractSuccessSound.GetSound();
            }
        }
        else
        {
            if (component.InteractFailureString != null)
            {
                msg = Loc.GetString(component.InteractFailureString, ("target", uid)); // Failure message (localized).
            }
            if (component.InteractFailureSound != null)
            {
                sfx = component.InteractFailureSound.GetSound();
            }
        }

        if (component.PopupPerceivedByOthers)
        {
            _popupSystem.PopupEntity(msg, uid, Filter.Pvs(uid)); //play for everyone in range
        }
        else
        {
            _popupSystem.PopupEntity(msg, uid, Filter.Entities(args.User)); //play only for the initiating entity.
        }
        if (sfx is not null)                                                //not all cases will have sound.
        {
            if (component.SoundPerceivedByOthers)
            {
                SoundSystem.Play(Filter.Pvs(args.Target), sfx, args.Target); //play for everyone in range
            }
            else
            {
                SoundSystem.Play(Filter.Entities(args.User, args.Target), sfx, args.Target); //play only for the initiating entity and its target.
            }
        }

        component.LastInteractTime = curTime;
        args.Handled = true;
    }
    private void OnInteract(EntityUid uid, ArtifactInteractionTriggerComponent component, InteractHandEvent args)
    {
        if (args.Handled)
        {
            return;
        }

        if (!component.EmptyHandActivation)
        {
            return;
        }

        args.Handled = _artifactSystem.TryActivateArtifact(uid, args.User);
    }
        private void OnInteract(EntityUid uid, ContainmentFieldGeneratorComponent component, InteractHandEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            if (TryComp(component.Owner, out TransformComponent? transformComp) && transformComp.Anchored)
            {
                if (!component.Enabled)
                {
                    TurnOn(component);
                }
                else if (component.Enabled && component.IsConnected)
                {
                    _popupSystem.PopupEntity(Loc.GetString("comp-containment-anchor-warning"), args.User, Filter.Entities(args.User));
                    return;
                }
                else
                {
                    TurnOff(component);
                }
            }

            args.Handled = true;
        }
        private void OnElectrifiedHandInteract(EntityUid uid, ElectrifiedComponent electrified, InteractHandEvent args)
        {
            if (!electrified.OnHandInteract)
            {
                return;
            }

            TryDoElectrifiedAct(uid, args.User, 1, electrified);
        }