/// <summary>
        ///     Checks that the user and target of a
        ///     <see cref="AfterInteractEvent"/> are within a  certain distance
        ///     without any entity that matches the collision mask obstructing them.
        ///     If the <paramref name="range"/> is zero or negative,
        ///     this method will only check if nothing obstructs the entity and component.
        /// </summary>
        /// <param name="args">The event args to use.</param>
        /// <param name="range">
        ///     Maximum distance between the two entity and set of map coordinates.
        /// </param>
        /// <param name="collisionMask">The mask to check for collisions.</param>
        /// <param name="predicate">
        ///     A predicate to check whether to ignore an entity or not.
        ///     If it returns true, it will be ignored.
        /// </param>
        /// <param name="ignoreInsideBlocker">
        ///     If true and both the user and target are inside
        ///     the obstruction, ignores the obstruction and considers the interaction
        ///     unobstructed.
        ///     Therefore, setting this to true makes this check more permissive,
        ///     such as allowing an interaction to occur inside something impassable
        ///     (like a wall). The default, false, makes the check more restrictive.
        /// </param>
        /// <param name="popup">
        ///     Whether or not to popup a feedback message on the user entity for
        ///     it to see.
        /// </param>
        /// <returns>
        ///     True if the two points are within a given range without being obstructed.
        /// </returns>
        public bool InRangeUnobstructed(
            AfterInteractEvent args,
            float range = InteractionRange,
            CollisionGroup collisionMask = CollisionGroup.Impassable,
            Ignored?predicate            = null,
            bool ignoreInsideBlocker     = false,
            bool popup = false)
        {
            var user   = args.User;
            var target = args.Target;

            predicate ??= e => e == user;

            MapCoordinates otherPosition;

            if (target == null)
            {
                otherPosition = args.ClickLocation.ToMap(EntityManager);
            }
            else
            {
                otherPosition = target.Transform.MapPosition;
                predicate    += e => e == target;
            }

            return(InRangeUnobstructed(user, otherPosition, range, collisionMask, predicate, ignoreInsideBlocker, popup));
        }
        private void OnAfterInteract(EntityUid uid, RCDAmmoComponent component, AfterInteractEvent args)
        {
            if (args.Handled || !args.CanReach)
            {
                return;
            }

            if (args.Target is not {
                Valid : true
            } target ||
                !EntityManager.TryGetComponent(target, out RCDComponent? rcdComponent))
            {
                return;
            }

            if (rcdComponent.MaxAmmo - rcdComponent.CurrentAmmo < component.RefillAmmo)
            {
                rcdComponent.Owner.PopupMessage(args.User, Loc.GetString("rcd-ammo-component-after-interact-full-text"));
                args.Handled = true;
                return;
            }

            rcdComponent.CurrentAmmo = Math.Min(rcdComponent.MaxAmmo, rcdComponent.CurrentAmmo + component.RefillAmmo);
            rcdComponent.Owner.PopupMessage(args.User, Loc.GetString("rcd-ammo-component-after-interact-refilled-text"));
            EntityManager.QueueDeleteEntity(uid);

            args.Handled = true;
        }
Пример #3
0
    private void OnAfterInteract(EntityUid uid, SharpComponent component, AfterInteractEvent args)
    {
        if (!args.CanReach)
        {
            return;
        }

        if (args.Target is null || !TryComp <SharedButcherableComponent>(args.Target, out var butcher))
        {
            return;
        }

        if (butcher.Type != ButcheringType.Knife)
        {
            return;
        }

        if (TryComp <MobStateComponent>(args.Target, out var mobState) && !mobState.IsDead())
        {
            return;
        }

        if (!component.Butchering.Add(args.Target.Value))
        {
            return;
        }

        var doAfter =
            new DoAfterEventArgs(args.User, component.ButcherDelayModifier * butcher.ButcherDelay, default, args.Target)
Пример #4
0
        private void OnAfterInteract(EntityUid uid, EmagComponent component, AfterInteractEvent args)
        {
            if (!args.CanReach || args.Target == null)
            {
                return;
            }

            if (_tagSystem.HasTag(args.Target.Value, "EmagImmune"))
            {
                return;
            }

            if (component.Charges <= 0)
            {
                _popupSystem.PopupEntity(Loc.GetString("emag-no-charges"), args.User, Filter.Entities(args.User));
                return;
            }

            var emaggedEvent = new GotEmaggedEvent(args.User);

            RaiseLocalEvent(args.Target.Value, emaggedEvent, false);
            if (emaggedEvent.Handled)
            {
                _popupSystem.PopupEntity(Loc.GetString("emag-success", ("target", Identity.Entity(args.Target.Value, EntityManager))), args.User,
                                         Filter.Entities(args.User), PopupType.Medium);
                _adminLogger.Add(LogType.Emag, LogImpact.High, $"{ToPrettyString(args.User):player} emagged {ToPrettyString(args.Target.Value):target}");
                component.Charges--;
                return;
            }
        }
Пример #5
0
        /// <summary>
        /// Feed someone else
        /// </summary>
        private void OnFeedFood(EntityUid uid, FoodComponent foodComponent, AfterInteractEvent args)
        {
            if (args.Handled || args.Target == null)
            {
                return;
            }

            if (!_actionBlockerSystem.CanInteract(args.User) || !_actionBlockerSystem.CanUse(args.User))
            {
                return;
            }

            if (!args.User.InRangeUnobstructed(uid, popup: true))
            {
                args.Handled = true;
                return;
            }

            if (args.User == args.Target)
            {
                args.Handled = TryUseFood(uid, args.User);
                return;
            }

            if (!args.User.InRangeUnobstructed(args.Target.Value, popup: true))
            {
                args.Handled = true;
                return;
            }

            args.Handled = TryForceFeed(uid, args.User, args.Target.Value);
        }
    private void OnInjectorAfterInteract(EntityUid uid, InjectorComponent component, AfterInteractEvent args)
    {
        if (args.Handled || !args.CanReach)
        {
            return;
        }

        if (component.CancelToken != null)
        {
            args.Handled = true;
            return;
        }

        //Make sure we have the attacking entity
        if (args.Target is not {
            Valid : true
        } target ||
            !HasComp <SolutionContainerManagerComponent>(uid))
        {
            return;
        }

        // Is the target a mob? If yes, use a do-after to give them time to respond.
        if (HasComp <MobStateComponent>(target) ||
            HasComp <BloodstreamComponent>(target))
        {
            InjectDoAfter(component, args.User, target);
            args.Handled = true;
            return;
        }

        UseInjector(target, args.User, component);
        args.Handled = true;
    }
        private void OnAfterInteract(EntityUid uid, AgentIDCardComponent component, AfterInteractEvent args)
        {
            if (!TryComp <AccessComponent>(args.Target, out var targetAccess) || !TryComp <IdCardComponent>(uid, out var targetIDCard) || args.Target == null)
            {
                return;
            }

            if (!TryComp <AccessComponent>(uid, out var access) || !TryComp <IdCardComponent>(uid, out var idCard))
            {
                return;
            }

            var beforeLength = access.Tags.Count;

            access.Tags.UnionWith(targetAccess.Tags);
            var addedLength = access.Tags.Count - beforeLength;

            if (addedLength == 0)
            {
                _popupSystem.PopupEntity(Loc.GetString("agent-id-no-new", ("card", args.Target)), args.Target.Value, Filter.Entities(args.User));
                return;
            }
            else if (addedLength == 1)
            {
                _popupSystem.PopupEntity(Loc.GetString("agent-id-new-1", ("card", args.Target)), args.Target.Value, Filter.Entities(args.User));
                return;
            }
            _popupSystem.PopupEntity(Loc.GetString("agent-id-new", ("number", addedLength), ("card", args.Target)), args.Target.Value, Filter.Entities(args.User));
        }
Пример #8
0
        private void OnAfterInteract(EntityUid uid, BibleComponent component, AfterInteractEvent args)
        {
            if (!args.CanReach)
            {
                return;
            }

            var currentTime = _gameTiming.CurTime;

            if (currentTime < component.CooldownEnd)
            {
                return;
            }
            if (args.Target == null || args.Target == args.User || !HasComp <MobStateComponent>(args.Target))
            {
                return;
            }

            component.LastAttackTime = currentTime;
            component.CooldownEnd    = component.LastAttackTime + TimeSpan.FromSeconds(component.CooldownTime);
            RaiseLocalEvent(uid, new RefreshItemCooldownEvent(component.LastAttackTime, component.CooldownEnd), false);

            if (!HasComp <BibleUserComponent>(args.User))
            {
                _popupSystem.PopupEntity(Loc.GetString("bible-sizzle"), args.User, Filter.Entities(args.User));

                SoundSystem.Play(Filter.Pvs(args.User), "/Audio/Effects/lightburn.ogg", args.User);
                _damageableSystem.TryChangeDamage(args.User, component.DamageOnUntrainedUse, true);

                return;
            }

            if (!_invSystem.TryGetSlotEntity(args.Target.Value, "head", out var entityUid))
            {
                if (_random.Prob(component.FailChance))
                {
                    var othersFailMessage = Loc.GetString("bible-heal-fail-others", ("user", args.User), ("target", args.Target), ("bible", uid));
                    _popupSystem.PopupEntity(othersFailMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));

                    var selfFailMessage = Loc.GetString("bible-heal-fail-self", ("target", args.Target), ("bible", uid));
                    _popupSystem.PopupEntity(selfFailMessage, args.User, Filter.Entities(args.User));

                    SoundSystem.Play(Filter.Pvs(args.Target.Value), "/Audio/Effects/hit_kick.ogg", args.User);
                    _damageableSystem.TryChangeDamage(args.Target.Value, component.DamageOnFail, true);
                    return;
                }
            }

            var othersMessage = Loc.GetString("bible-heal-success-others", ("user", args.User), ("target", args.Target), ("bible", uid));

            _popupSystem.PopupEntity(othersMessage, args.User, Filter.Pvs(args.User).RemoveWhereAttachedEntity(puid => puid == args.User));

            var selfMessage = Loc.GetString("bible-heal-success-self", ("target", args.Target), ("bible", uid));

            _popupSystem.PopupEntity(selfMessage, args.User, Filter.Entities(args.User));

            SoundSystem.Play(Filter.Pvs(args.Target.Value), "/Audio/Effects/holy.ogg", args.User);
            _damageableSystem.TryChangeDamage(args.Target.Value, component.Damage, true);
        }
Пример #9
0
        private void AfterInteract(EntityUid uid, DrinkComponent component, AfterInteractEvent args)
        {
            if (args.Handled || args.Target == null || !args.CanReach)
            {
                return;
            }

            args.Handled = TryDrink(args.User, args.Target.Value, component);
        }
        /// <summary>
        /// Feed someone else
        /// </summary>
        private void OnFeedFood(EntityUid uid, FoodComponent foodComponent, AfterInteractEvent args)
        {
            if (args.Handled || args.Target == null || !args.CanReach)
            {
                return;
            }

            args.Handled = TryFeed(args.User, args.Target.Value, foodComponent);
        }
Пример #11
0
    private void OnAfterInteract(EntityUid uid, SharpComponent component, AfterInteractEvent args)
    {
        if (args.Target is null || !args.CanReach)
        {
            return;
        }

        TryStartButcherDoafter(uid, args.Target.Value, args.User);
    }
Пример #12
0
    private void OnAfterInteract(EntityUid uid, StickyComponent component, AfterInteractEvent args)
    {
        if (args.Handled || !args.CanReach || args.Target == null)
        {
            return;
        }

        // try stick object to a clicked target entity
        args.Handled = StartSticking(uid, args.User, args.Target.Value, component);
    }
Пример #13
0
    private void OnHealingAfterInteract(EntityUid uid, HealingComponent component, AfterInteractEvent args)
    {
        if (args.Handled || !args.CanReach || args.Target == null)
        {
            return;
        }

        args.Handled = true;
        Heal(uid, args.User, args.Target.Value, component);
    }
        private void OnAfterInteract(EntityUid uid, FloorTileComponent component, AfterInteractEvent args)
        {
            if (!args.CanReach)
            {
                return;
            }

            if (!TryComp <StackComponent>(uid, out var stack))
            {
                return;
            }

            if (component.OutputTiles == null)
            {
                return;
            }

            // this looks a bit sussy but it might be because it needs to be able to place off of grids and expand them
            var location    = args.ClickLocation.AlignWithClosestGridTile();
            var locationMap = location.ToMap(EntityManager);

            if (locationMap.MapId == MapId.Nullspace)
            {
                return;
            }
            _mapManager.TryGetGrid(location.GetGridId(EntityManager), out var mapGrid);

            foreach (var currentTile in component.OutputTiles)
            {
                var currentTileDefinition = (ContentTileDefinition)_tileDefinitionManager[currentTile];

                if (mapGrid != null)
                {
                    var tile     = mapGrid.GetTileRef(location);
                    var baseTurf = (ContentTileDefinition)_tileDefinitionManager[tile.Tile.TypeId];

                    if (HasBaseTurf(currentTileDefinition, baseTurf.ID))
                    {
                        if (!_stackSystem.Use(uid, 1, stack))
                        {
                            continue;
                        }

                        PlaceAt(mapGrid, location, currentTileDefinition.TileId, component.PlaceTileSound);
                    }
                }
                else if (HasBaseTurf(currentTileDefinition, "space"))
                {
                    mapGrid = _mapManager.CreateGrid(locationMap.MapId);
                    mapGrid.WorldPosition = locationMap.Position;
                    location = new EntityCoordinates(mapGrid.GridEntityId, Vector2.Zero);
                    PlaceAt(mapGrid, location, _tileDefinitionManager[component.OutputTiles[0]].TileId, component.PlaceTileSound, mapGrid.TileSize / 2f);
                }
            }
        }
        public void OnAfterInteract(EntityUid uid, HyposprayComponent comp, AfterInteractEvent args)
        {
            if (!args.CanReach)
            {
                return;
            }
            var target = args.Target;
            var user   = args.User;

            comp.TryDoInject(target, user);
        }
 public static bool InRangeUnobstructed(
     this AfterInteractEvent args,
     float range = InteractionRange,
     CollisionGroup collisionMask = CollisionGroup.Impassable,
     Ignored?predicate            = null,
     bool ignoreInsideBlocker     = false,
     bool popup = false)
 {
     return(SharedInteractionSystem.InRangeUnobstructed(args, range, collisionMask, predicate,
                                                        ignoreInsideBlocker, popup));
 }
        private void OnCuffAfterInteract(EntityUid uid, HandcuffComponent component, AfterInteractEvent args)
        {
            if (component.Cuffing)
            {
                return;
            }

            if (args.Target is not {
                Valid : true
            } target ||
                !EntityManager.TryGetComponent <CuffableComponent>(args.Target.Value, out var cuffed))
            {
                return;
            }

            if (component.Broken)
            {
                args.User.PopupMessage(Loc.GetString("handcuff-component-cuffs-broken-error"));
                return;
            }

            if (!EntityManager.TryGetComponent <HandsComponent?>(target, out var hands))
            {
                args.User.PopupMessage(Loc.GetString("handcuff-component-target-has-no-hands-error", ("targetName", args.Target)));
                return;
            }

            if (cuffed.CuffedHandCount >= hands.Count)
            {
                args.User.PopupMessage(Loc.GetString("handcuff-component-target-has-no-free-hands-error", ("targetName", args.Target)));
                return;
            }

            if (!args.CanReach)
            {
                args.User.PopupMessage(Loc.GetString("handcuff-component-too-far-away-error"));
                return;
            }

            if (args.Target == args.User)
            {
                args.User.PopupMessage(Loc.GetString("handcuff-component-target-self"));
            }
            else
            {
                args.User.PopupMessage(Loc.GetString("handcuff-component-start-cuffing-target-message", ("targetName", args.Target)));
                args.User.PopupMessage(target, Loc.GetString("handcuff-component-start-cuffing-by-other-message", ("otherName", args.User)));
            }

            SoundSystem.Play(component.StartCuffSound.GetSound(), Filter.Pvs(uid), uid);

            component.TryUpdateCuff(args.User, target, cuffed);
            args.Handled = true;
        }
Пример #18
0
        /// <summary>
        /// Clicked with utensil
        /// </summary>
        private void OnAfterInteract(EntityUid uid, UtensilComponent component, AfterInteractEvent ev)
        {
            if (ev.Target == null)
            {
                return;
            }

            if (TryUseUtensil(ev.User, ev.Target.Value, component))
            {
                ev.Handled = true;
            }
        }
Пример #19
0
    private void OnCrayonAfterInteract(EntityUid uid, CrayonComponent component, AfterInteractEvent args)
    {
        if (args.Handled || !args.CanReach)
        {
            return;
        }

        if (component.Charges <= 0)
        {
            if (component.DeleteEmpty)
            {
                UseUpCrayon(uid, args.User);
            }
            else
            {
                _popup.PopupEntity(Loc.GetString("crayon-interact-not-enough-left-text"), uid, Filter.Entities(args.User));
            }

            args.Handled = true;
            return;
        }

        if (!args.ClickLocation.IsValid(EntityManager))
        {
            _popup.PopupEntity(Loc.GetString("crayon-interact-invalid-location"), uid, Filter.Entities(args.User));
            args.Handled = true;
            return;
        }

        if (!_decals.TryAddDecal(component.SelectedState, args.ClickLocation.Offset(new Vector2(-0.5f, -0.5f)), out _, Color.FromName(component._color), cleanable: true))
        {
            return;
        }

        if (component.UseSound != null)
        {
            SoundSystem.Play(Filter.Pvs(uid), component.UseSound.GetSound(), uid, AudioHelpers.WithVariation(0.125f));
        }

        // Decrease "Ammo"
        component.Charges--;
        Dirty(component);
        _logs.Add(LogType.CrayonDraw, LogImpact.Low, $"{EntityManager.ToPrettyString(args.User):user} drew a {component._color:color} {component.SelectedState}");
        args.Handled = true;

        if (component.DeleteEmpty && component.Charges <= 0)
        {
            UseUpCrayon(uid, args.User);
        }
    }
        private void OnAfterInteract(EntityUid uid, GasAnalyzerComponent component, AfterInteractEvent args)
        {
            if (!args.CanReach)
            {
                _popup.PopupEntity(Loc.GetString("gas-analyzer-component-player-cannot-reach-message"), args.User, Filter.Entities(args.User));
                return;
            }

            if (TryComp(args.User, out ActorComponent? actor))
            {
                component.OpenInterface(actor.PlayerSession, args.ClickLocation);
            }

            args.Handled = true;
        }
    private void OnAfterInteract(EntityUid uid, FireExtinguisherComponent component, AfterInteractEvent args)
    {
        if (args.Target == null || !args.CanReach)
        {
            return;
        }

        if (args.Handled)
        {
            return;
        }

        args.Handled = true;

        if (component.HasSafety && component.Safety)
        {
            _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), uid,
                                     Filter.Entities(args.User));
            return;
        }

        if (args.Target is not {
            Valid : true
        } target ||
            !_solutionContainerSystem.TryGetDrainableSolution(target, out var targetSolution) ||
            !_solutionContainerSystem.TryGetRefillableSolution(uid, out var container))
        {
            return;
        }

        var transfer = container.AvailableVolume;

        if (TryComp <SolutionTransferComponent>(uid, out var solTrans))
        {
            transfer = solTrans.TransferAmount;
        }
        transfer = FixedPoint2.Min(transfer, targetSolution.DrainAvailable);

        if (transfer > 0)
        {
            var drained = _solutionContainerSystem.Drain(target, targetSolution, transfer);
            _solutionContainerSystem.TryAddSolution(uid, container, drained);

            SoundSystem.Play(Filter.Pvs(uid), component.RefillSound.GetSound(), uid);
            _popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-after-interact-refilled-message", ("owner", uid)),
                                     uid, Filter.Entities(args.Target.Value));
        }
    }
        private void OnAfterInteract(EntityUid uid, DoorRemoteComponent component, AfterInteractEvent args)
        {
            if (args.Handled ||
                args.Target == null ||
                !TryComp <DoorComponent>(args.Target, out var doorComponent) || // If it isn't a door we don't use it
                !HasComp <AccessReaderComponent>(args.Target) || // Remotes do not work on doors without access requirements
                !TryComp <AirlockComponent>(args.Target, out var airlockComponent) || // Remotes only work on airlocks
                !_interactionSystem.InRangeUnobstructed(args.User, doorComponent.Owner, -1f, CollisionGroup.Opaque))
            {
                return;
            }

            args.Handled = true;

            if (component.Mode == DoorRemoteComponent.OperatingMode.OpenClose)
            {
                _sharedDoorSystem.TryToggleDoor(doorComponent.Owner, user: args.Used);
            }

            if (component.Mode == DoorRemoteComponent.OperatingMode.ToggleBolts &&
                airlockComponent.IsPowered())
            {
                if (_doorSystem.HasAccess(doorComponent.Owner, args.Used))
                {
                    airlockComponent.SetBoltsWithAudio(!airlockComponent.IsBolted());
                }
                else
                {
                    if (doorComponent.State != DoorState.Open)
                    {
                        _sharedDoorSystem.Deny(airlockComponent.Owner, user: args.User);
                    }
                    else if (doorComponent.DenySound != null)
                    {
                        SoundSystem.Play(Filter.Pvs(args.Target.Value), doorComponent.DenySound.GetSound(), args.Target.Value);
                    }
                }
            }

            if (component.Mode == DoorRemoteComponent.OperatingMode.ToggleEmergencyAccess &&
                airlockComponent.IsPowered())
            {
                if (_doorSystem.HasAccess(doorComponent.Owner, args.Used))
                {
                    _sharedAirlockSystem.ToggleEmergencyAccess(airlockComponent);
                }
            }
        }
        private void OnAfterInteract(EntityUid uid, ResearchDiskComponent component, AfterInteractEvent args)
        {
            if (!args.CanReach)
            {
                return;
            }

            if (!TryComp <ResearchServerComponent>(args.Target, out var server))
            {
                return;
            }

            server.Points += component.Points;
            _popupSystem.PopupEntity(Loc.GetString("research-disk-inserted", ("points", component.Points)), args.Target.Value, Filter.Entities(args.User));
            EntityManager.QueueDeleteEntity(uid);
        }
Пример #24
0
    private void OnAfterInteract(EntityUid uid, PriceGunComponent component, AfterInteractEvent args)
    {
        if (!args.CanReach || args.Target == null)
        {
            return;
        }

        if (TryComp(args.Used, out UseDelayComponent? useDelay) && useDelay.ActiveDelay)
        {
            return;
        }

        var price = _pricingSystem.GetPrice(args.Target.Value);

        _popupSystem.PopupEntity(Loc.GetString("price-gun-pricing-result", ("object", args.Target.Value), ("price", $"{price:F2}")), args.User, Filter.Entities(args.User));
        _useDelay.BeginDelay(uid, useDelay);
    }
Пример #25
0
        /// <summary>
        ///     Used for melee weapons that want some behavior on AfterInteract,
        ///     but also want the cooldown (stun batons, flashes)
        /// </summary>
        private void OnAfterInteract(EntityUid uid, MeleeWeaponComponent comp, AfterInteractEvent args)
        {
            if (!args.CanReach)
            {
                return;
            }

            var curTime = _gameTiming.CurTime;

            if (curTime < comp.CooldownEnd)
            {
                return;
            }

            var owner = EntityManager.GetEntity(uid);

            if (args.Target == null)
            {
                return;
            }

            var location = args.User.Transform.Coordinates;
            var diff     = args.ClickLocation.ToMapPos(owner.EntityManager) - location.ToMapPos(owner.EntityManager);
            var angle    = Angle.FromWorldVec(diff);

            var hitEvent = new MeleeInteractEvent(args.Target, args.User);

            RaiseLocalEvent(uid, hitEvent, false);

            if (!hitEvent.CanInteract)
            {
                return;
            }
            SendAnimation(comp.ClickArc, angle, args.User, owner, new List <IEntity>()
            {
                args.Target
            }, comp.ClickAttackEffect, false);

            comp.LastAttackTime = curTime;
            comp.CooldownEnd    = comp.LastAttackTime + TimeSpan.FromSeconds(comp.CooldownTime);

            RaiseLocalEvent(uid, new RefreshItemCooldownEvent(comp.LastAttackTime, comp.CooldownEnd), false);
        }
        private void OnAfterInteract(EntityUid uid, ForensicPadComponent component, AfterInteractEvent args)
        {
            if (component.CancelToken != null || !args.CanReach || args.Target == null)
            {
                return;
            }

            if (HasComp <ForensicScannerComponent>(args.Target))
            {
                return;
            }

            args.Handled = true;

            if (component.Used)
            {
                _popupSystem.PopupEntity(Loc.GetString("forensic-pad-already-used"), args.Target.Value, Filter.Entities(args.User));
                return;
            }

            if (_inventory.TryGetSlotEntity(args.Target.Value, "gloves", out var gloves))
            {
                _popupSystem.PopupEntity(Loc.GetString("forensic-pad-gloves", ("target", Identity.Entity(args.Target.Value, EntityManager))), args.Target.Value, Filter.Entities(args.User));
                return;
            }

            if (TryComp <FingerprintComponent>(args.Target, out var fingerprint) && fingerprint.Fingerprint != null)
            {
                if (args.User != args.Target)
                {
                    _popupSystem.PopupEntity(Loc.GetString("forensic-pad-start-scan-user", ("target", Identity.Entity(args.Target.Value, EntityManager))), args.Target.Value, Filter.Entities(args.User));
                    _popupSystem.PopupEntity(Loc.GetString("forensic-pad-start-scan-target", ("user", Identity.Entity(args.User, EntityManager))), args.Target.Value, Filter.Entities(args.Target.Value));
                }
                StartScan(args.User, args.Target.Value, component, fingerprint.Fingerprint);
                return;
            }

            if (TryComp <FiberComponent>(args.Target, out var fiber))
            {
                StartScan(args.User, args.Target.Value, component, string.IsNullOrEmpty(fiber.FiberColor) ? Loc.GetString("forensic-fibers", ("material", fiber.FiberMaterial)) : Loc.GetString("forensic-fibers-colored", ("color", fiber.FiberColor), ("material", fiber.FiberMaterial)));
            }
        }
Пример #27
0
        public static bool InRangeUnobstructed(
            this AfterInteractEvent args,
            float range = InteractionRange,
            CollisionGroup collisionMask = CollisionGroup.Impassable,
            Ignored?predicate            = null,
            bool ignoreInsideBlocker     = false,
            bool popup = false)
        {
            var user   = args.User;
            var target = args.Target;

            if (target == null)
            {
                return(SharedInteractionSystem.InRangeUnobstructed(user, args.ClickLocation, range, collisionMask, predicate, ignoreInsideBlocker, popup));
            }
            else
            {
                return(SharedInteractionSystem.InRangeUnobstructed(user, target.Value, range, collisionMask, predicate, ignoreInsideBlocker, popup));
            }
        }
Пример #28
0
        private void OnAfterInteract(EntityUid uid, TelecrystalComponent component, AfterInteractEvent args)
        {
            if (args.Handled || !args.CanReach)
            {
                return;
            }

            if (args.Target == null || !EntityManager.TryGetComponent(args.Target.Value, out UplinkComponent? uplink))
            {
                return;
            }

            // TODO: when uplink will have some auth logic (like PDA ringtone code)
            // check if uplink open before adding TC
            // No metagaming by using this on every PDA around just to see if it gets used up.

            var acc = uplink.UplinkAccount;

            if (acc == null)
            {
                return;
            }

            EntityManager.TryGetComponent(uid, out SharedStackComponent? stack);

            var tcCount = stack != null ? stack.Count : 1;

            if (!_accounts.AddToBalance(acc, tcCount))
            {
                return;
            }

            var msg = Loc.GetString("telecrystal-component-sucs-inserted",
                                    ("source", args.Used), ("target", args.Target));

            args.User.PopupMessage(args.User, msg);

            EntityManager.DeleteEntity(uid);

            args.Handled = true;
        }
Пример #29
0
        private void AfterInteract(EntityUid uid, DrinkComponent component, AfterInteractEvent args)
        {
            if (args.Handled || args.Target == null)
            {
                return;
            }

            if (!_actionBlockerSystem.CanInteract(args.User) || !_actionBlockerSystem.CanUse(args.User))
            {
                return;
            }

            if (!args.User.InRangeUnobstructed(uid, popup: true))
            {
                args.Handled = true;
                return;
            }

            if (args.User == args.Target)
            {
                args.Handled = TryUseDrink(uid, args.User);
                return;
            }

            if (!args.User.InRangeUnobstructed(args.Target.Value, popup: true))
            {
                args.Handled = true;
                return;
            }

            if (args.User == args.Target)
            {
                args.Handled = TryUseDrink(uid, args.User, component);
            }
            else
            {
                args.Handled = TryForceDrink(uid, args.User, args.Target.Value, component);
            }
        }
    private void OnAfterInteract(EntityUid uid, AbsorbentComponent component, AfterInteractEvent args)
    {
        if (!args.CanReach) // if user cannot reach the target
        {
            return;
        }

        if (args.Handled) // if the event was already handled
        {
            return;
        }

        _solutionSystem.TryGetSolution(args.Used, AbsorbentComponent.SolutionName, out var absorbedSolution);

        if (absorbedSolution is null)
        {
            return;
        }

        var toolAvailableVolume = absorbedSolution.AvailableVolume;
        var toolCurrentVolume   = absorbedSolution.CurrentVolume;

        // For adding liquid to an empty floor tile
        if (args.Target is null) // if a tile is clicked
        {
            ReleaseToFloor(args.ClickLocation, component, absorbedSolution);
            args.Handled = true;
            args.User.PopupMessage(args.User, Loc.GetString("mopping-system-release-to-floor"));
            return;
        }
        else if (args.Target is not null)
        {
            // Handle our do_after logic
            HandleDoAfter(args.User, args.Used, args.Target.Value, component, toolCurrentVolume, toolAvailableVolume);
        }

        args.Handled = true;
        return;
    }