Exemplo n.º 1
0
        /// <summary>
        /// Handle deleting entities and increasing energy
        /// </summary>
        private void DestroyEntities(ServerSingularityComponent component, TransformComponent xform, Vector2 worldPos)
        {
            // The reason we don't /just/ use collision is because we'll be deleting stuff that may not necessarily have physics (e.g. carpets).
            var destroyRange = DestroyTileRange(component);

            foreach (var entity in _lookup.GetEntitiesInRange(xform.MapID, worldPos, destroyRange))
            {
                HandleDestroy(component, entity);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Force bomb to explode immediately
        /// </summary>
        public void ActivateBomb(EntityUid uid, NukeComponent?component = null,
                                 TransformComponent?transform           = null)
        {
            if (!Resolve(uid, ref component, ref transform))
            {
                return;
            }

            // gib anyone in a blast radius
            // its lame, but will work for now
            var pos  = transform.Coordinates;
            var ents = _lookup.GetEntitiesInRange(pos, component.BlastRadius);

            foreach (var ent in ents)
            {
                var entUid = ent;
                if (!EntityManager.EntityExists(entUid))
                {
                    continue;
                }

                if (EntityManager.TryGetComponent(entUid, out SharedBodyComponent? body))
                {
                    body.Gib();
                }
            }

            EntityManager.DeleteEntity(uid);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Raise event to attempt to use held item, or surrounding entities to commit suicide
        /// </summary>
        private void EnvironmentSuicideHandler(EntityUid victim, SuicideEvent suicideEvent)
        {
            // Suicide by held item
            if (EntityManager.TryGetComponent(victim, out HandsComponent? handsComponent) &&
                handsComponent.ActiveHandEntity is { } item)
            {
                RaiseLocalEvent(item, suicideEvent, false);

                if (suicideEvent.Handled)
                {
                    return;
                }
            }

            var itemQuery = GetEntityQuery <ItemComponent>();

            // Suicide by nearby entity (ex: Microwave)
            foreach (var entity in _entityLookupSystem.GetEntitiesInRange(victim, 1, LookupFlags.Approximate | LookupFlags.Anchored))
            {
                // Skip any nearby items that can be picked up, we already checked the active held item above
                if (itemQuery.HasComponent(entity))
                {
                    continue;
                }

                RaiseLocalEvent(entity, suicideEvent, false);

                if (suicideEvent.Handled)
                {
                    break;
                }
            }
        }
        /// <summary>
        /// When activated, blasts everyone in LOS within n tiles
        /// with a high-probability disease infection attempt
        /// </summary>
        private void OnActivate(EntityUid uid, DiseaseArtifactComponent component, ArtifactActivatedEvent args)
        {
            if (component.SpawnDisease == null)
            {
                return;
            }

            var xform        = Transform(uid);
            var carrierQuery = GetEntityQuery <DiseaseCarrierComponent>();

            foreach (var entity in _lookup.GetEntitiesInRange(xform.Coordinates, component.Range))
            {
                if (!carrierQuery.TryGetComponent(entity, out var carrier))
                {
                    continue;
                }

                if (!_interactionSystem.InRangeUnobstructed(uid, entity, component.Range))
                {
                    continue;
                }

                _disease.TryInfect(carrier, component.SpawnDisease, forced: true);
            }
        }
Exemplo n.º 5
0
        public void FlashArea(EntityUid source, EntityUid?user, float range, float duration, float slowTo = 0.8f, bool displayPopup = false, SoundSpecifier?sound = null)
        {
            var transform         = EntityManager.GetComponent <TransformComponent>(source);
            var mapPosition       = transform.MapPosition;
            var flashableEntities = new List <EntityUid>();
            var flashableQuery    = GetEntityQuery <FlashableComponent>();

            foreach (var entity in _entityLookup.GetEntitiesInRange(transform.Coordinates, range))
            {
                if (!flashableQuery.HasComponent(entity))
                {
                    continue;
                }

                flashableEntities.Add(entity);
            }

            foreach (var entity in flashableEntities)
            {
                // Check for unobstructed entities while ignoring the mobs with flashable components.
                if (!_interactionSystem.InRangeUnobstructed(entity, mapPosition, range, CollisionGroup.Opaque, (e) => flashableEntities.Contains(e)))
                {
                    continue;
                }

                // They shouldn't have flash removed in between right?
                Flash(entity, user, source, duration, slowTo, displayPopup, flashableQuery.GetComponent(entity));
            }
            if (sound != null)
            {
                SoundSystem.Play(sound.GetSound(), Filter.Pvs(transform), source);
            }
        }
Exemplo n.º 6
0
        private void OnActionPerform(EntityUid uid, GhostComponent component, BooActionEvent args)
        {
            if (args.Handled)
            {
                return;
            }

            var ents = _lookup.GetEntitiesInRange(args.Performer, component.BooRadius);

            var booCounter = 0;

            foreach (var ent in ents)
            {
                var ghostBoo = new GhostBooEvent();
                RaiseLocalEvent(ent, ghostBoo, true);

                if (ghostBoo.Handled)
                {
                    booCounter++;
                }

                if (booCounter >= component.BooMaxTargets)
                {
                    break;
                }
            }

            args.Handled = true;
        }
        public EntityUid GetNearbyPuddle(EntityUid cleanbot, float range = 10)
        {
            foreach (var entity in _lookup.GetEntitiesInRange(cleanbot, range))
            {
                if (HasComp <PuddleComponent>(entity))
                {
                    return(entity);
                }
            }

            return(default);
Exemplo n.º 8
0
        public EntityUid GetNearbyInjectable(EntityUid medibot, float range = 4)
        {
            foreach (var entity in _lookup.GetEntitiesInRange(medibot, range))
            {
                if (HasComp <InjectableSolutionComponent>(entity) && HasComp <MobStateComponent>(entity))
                {
                    return(entity);
                }
            }

            return(default);
    public void IrradiateRange(MapCoordinates coordinates, float range, float radsPerSecond, float time)
    {
        var lookUp = _lookup.GetEntitiesInRange(coordinates, range);

        foreach (var uid in lookUp)
        {
            if (Deleted(uid))
            {
                continue;
            }

            IrradiateEntity(uid, radsPerSecond, time);
        }
    }
        /// <summary>
        /// When activated, blasts everyone in LOS within 3 tiles
        /// with a high-probability disease infection attempt
        /// </summary>
        private void OnActivate(EntityUid uid, DiseaseArtifactComponent component, ArtifactActivatedEvent args)
        {
            var xform = Transform(uid);

            foreach (var entity in _lookup.GetEntitiesInRange(xform.MapID, xform.WorldPosition, 3f))
            {
                if (!_interactionSystem.InRangeUnobstructed(uid, entity, 3f))
                {
                    continue;
                }

                if (TryComp <DiseaseCarrierComponent>(entity, out var carrier))
                {
                    EntitySystem.Get <DiseaseSystem>().TryInfect(carrier, component.ResolveDisease);
                }
            }
        }
Exemplo n.º 11
0
        private bool NonDronesInRange(EntityUid uid, DroneComponent component)
        {
            var xform = Comp <TransformComponent>(uid);

            foreach (var entity in _lookup.GetEntitiesInRange(xform.MapID, xform.WorldPosition, component.InteractionBlockRange))
            {
                if (HasComp <MindComponent>(entity) && !HasComp <DroneComponent>(entity) && !HasComp <GhostComponent>(entity))
                {
                    if (_gameTiming.IsFirstTimePredicted)
                    {
                        _popupSystem.PopupEntity(Loc.GetString("drone-too-close"), uid, Filter.Entities(uid));
                    }
                    return(true);
                }
            }
            return(false);
        }
    public void CloseStorage(EntityUid uid, EntityStorageComponent?component = null)
    {
        if (!Resolve(uid, ref component))
        {
            return;
        }
        component.Open = false;

        var targetCoordinates = new EntityCoordinates(uid, component.EnteringOffset);

        var entities = _lookup.GetEntitiesInRange(targetCoordinates, component.EnteringRange, LookupFlags.Approximate);

        var ev = new StorageBeforeCloseEvent(uid, entities);

        RaiseLocalEvent(uid, ev, true);
        var count = 0;

        foreach (var entity in ev.Contents)
        {
            if (!ev.BypassChecks.Contains(entity))
            {
                if (!CanFit(entity, uid, component.Whitelist))
                {
                    continue;
                }
            }

            if (!AddToContents(entity, uid, component))
            {
                continue;
            }

            count++;
            if (count >= component.Capacity)
            {
                break;
            }
        }

        ModifyComponents(uid, component);
        SoundSystem.Play(component.CloseSound.GetSound(), Filter.Pvs(uid), uid);
        component.LastInternalOpenAttempt = default;
        RaiseLocalEvent(uid, new StorageAfterCloseEvent());
    }
Exemplo n.º 13
0
        public override void Update(float frameTime)
        {
            base.Update(frameTime);

            _accumulator += frameTime;

            while (_accumulator > RadiationCooldown)
            {
                _accumulator -= RadiationCooldown;

                // All code here runs effectively every RadiationCooldown seconds, so use that as the "frame time".
                foreach (var comp in EntityManager.EntityQuery <RadiationPulseComponent>())
                {
                    comp.Update(RadiationCooldown);
                    var ent = comp.Owner;

                    if (Deleted(ent))
                    {
                        continue;
                    }

                    foreach (var entity in _lookup.GetEntitiesInRange(_entMan.GetComponent <TransformComponent>(ent).Coordinates, comp.Range))
                    {
                        // For now at least still need this because it uses a list internally then returns and this may be deleted before we get to it.
                        if ((!_entMan.EntityExists(entity) ? EntityLifeStage.Deleted : _entMan.GetComponent <MetaDataComponent>(entity).EntityLifeStage) >= EntityLifeStage.Deleted)
                        {
                            continue;
                        }

                        // Note: Radiation is liable for a refactor (stinky Sloth coding a basic version when he did StationEvents)
                        // so this ToArray doesn't really matter.
                        foreach (var radiation in _entMan.GetComponents <IRadiationAct>(entity).ToArray())
                        {
                            radiation.RadiationAct(RadiationCooldown, comp);
                        }
                    }
                }
            }
        }
Exemplo n.º 14
0
        private bool NonDronesInRange(EntityUid uid, DroneComponent component)
        {
            var xform = Comp <TransformComponent>(uid);

            foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, component.InteractionBlockRange))
            {
                // Return true if the entity is/was controlled by a player and is not a drone or ghost.
                if (HasComp <MindComponent>(entity) && !HasComp <DroneComponent>(entity) && !HasComp <GhostComponent>(entity))
                {
                    // Filter out dead ghost roles. Dead normal players are intended to block.
                    if ((TryComp <MobStateComponent>(entity, out var entityMobState) && HasComp <GhostTakeoverAvailableComponent>(entity) && entityMobState.IsDead()))
                    {
                        continue;
                    }
                    if (_gameTiming.IsFirstTimePredicted)
                    {
                        _popupSystem.PopupEntity(Loc.GetString("drone-too-close", ("being", entity)), uid, Filter.Entities(uid));
                    }
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 15
0
    private void OnActivate(EntityUid uid, TelepathicArtifactComponent component, ArtifactActivatedEvent args)
    {
        // try to find victims nearby
        var victims = _lookup.GetEntitiesInRange(uid, component.Range);

        foreach (var victimUid in victims)
        {
            if (!EntityManager.HasComponent <ActorComponent>(victimUid))
            {
                continue;
            }

            // roll if msg should be usual or drastic
            var isDrastic = _random.NextFloat() <= component.DrasticMessageProb;
            var msgArr    = isDrastic ? component.DrasticMessages : component.Messages;

            // pick a random message
            var msgId = _random.Pick(msgArr);
            var msg   = Loc.GetString(msgId);

            // show it as a popup, but only for the victim
            _popupSystem.PopupEntity(msg, victimUid, Filter.Entities(victimUid));
        }
    }
Exemplo n.º 16
0
        /// <summary>
        ///     Get all of the entities in an area for displaying on the context menu.
        /// </summary>
        public bool TryGetEntityMenuEntities(MapCoordinates targetPos, [NotNullWhen(true)] out List <EntityUid>?result)
        {
            result = null;

            if (_stateManager.CurrentState is not GameScreenBase gameScreenBase)
            {
                return(false);
            }

            var player = _playerManager.LocalPlayer?.ControlledEntity;

            if (player == null)
            {
                return(false);
            }

            // If FOV drawing is disabled, we will modify the visibility option to ignore visiblity checks.
            var visibility = _eyeManager.CurrentEye.DrawFov
                ? Visibility
                : Visibility | MenuVisibility.NoFov;

            // Do we have to do FoV checks?
            if ((visibility & MenuVisibility.NoFov) == 0)
            {
                var entitiesUnderMouse = gameScreenBase.GetEntitiesUnderPosition(targetPos);
                bool Predicate(EntityUid e) => e == player || entitiesUnderMouse.Contains(e);

                if (!_examineSystem.CanExamine(player.Value, targetPos, Predicate))
                {
                    return(false);
                }
            }

            // Get entities
            var entities = _entityLookup.GetEntitiesInRange(targetPos, EntityMenuLookupSize)
                           .ToList();

            if (entities.Count == 0)
            {
                return(false);
            }

            if (visibility == MenuVisibility.All)
            {
                result = entities;
                return(true);
            }

            // remove any entities in containers
            if ((visibility & MenuVisibility.InContainer) == 0)
            {
                foreach (var entity in entities.ToList())
                {
                    if (!ContainerSystem.IsInSameOrTransparentContainer(player.Value, entity))
                    {
                        entities.Remove(entity);
                    }
                }
            }

            // remove any invisible entities
            if ((visibility & MenuVisibility.Invisible) == 0)
            {
                foreach (var entity in entities.ToList())
                {
                    if (!EntityManager.TryGetComponent(entity, out ISpriteComponent? spriteComponent) ||
                        !spriteComponent.Visible)
                    {
                        entities.Remove(entity);
                        continue;
                    }

                    if (_tagSystem.HasTag(entity, "HideContextMenu"))
                    {
                        entities.Remove(entity);
                    }
                }
            }

            // Remove any entities that do not have LOS
            if ((visibility & MenuVisibility.NoFov) == 0)
            {
                var playerPos = EntityManager.GetComponent <TransformComponent>(player.Value).MapPosition;
                foreach (var entity in entities.ToList())
                {
                    if (!ExamineSystemShared.InRangeUnOccluded(
                            playerPos,
                            EntityManager.GetComponent <TransformComponent>(entity).MapPosition,
                            ExamineSystemShared.ExamineRange,
                            null))
                    {
                        entities.Remove(entity);
                    }
                }
            }

            if (entities.Count == 0)
            {
                return(false);
            }

            result = entities;
            return(true);
        }
Exemplo n.º 17
0
        /// <summary>
        /// Allows a user to pick up entities by clicking them, or pick up all entities in a certain radius
        /// around a click.
        /// </summary>
        /// <returns></returns>
        private async void AfterInteract(EntityUid uid, ServerStorageComponent storageComp, AfterInteractEvent eventArgs)
        {
            if (!eventArgs.CanReach)
            {
                return;
            }

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

            // Pick up all entities in a radius around the clicked location.
            // The last half of the if is because carpets exist and this is terrible
            if (storageComp.AreaInsert && (eventArgs.Target == null || !HasComp <ItemComponent>(eventArgs.Target.Value)))
            {
                var validStorables = new List <EntityUid>();
                foreach (var entity in _entityLookupSystem.GetEntitiesInRange(eventArgs.ClickLocation, storageComp.AreaInsertRadius, LookupFlags.None))
                {
                    if (entity == eventArgs.User ||
                        !HasComp <ItemComponent>(entity) ||
                        !_interactionSystem.InRangeUnobstructed(eventArgs.User, entity))
                    {
                        continue;
                    }

                    validStorables.Add(entity);
                }

                //If there's only one then let's be generous
                if (validStorables.Count > 1)
                {
                    storageComp.CancelToken = new CancellationTokenSource();
                    var doAfterArgs = new DoAfterEventArgs(eventArgs.User, 0.2f * validStorables.Count, storageComp.CancelToken.Token, uid)
                    {
                        BreakOnStun     = true,
                        BreakOnDamage   = true,
                        BreakOnUserMove = true,
                        NeedHand        = true,
                    };

                    await _doAfterSystem.WaitDoAfter(doAfterArgs);
                }

                // TODO: Make it use the event DoAfter
                var successfullyInserted          = new List <EntityUid>();
                var successfullyInsertedPositions = new List <EntityCoordinates>();
                foreach (var entity in validStorables)
                {
                    // Check again, situation may have changed for some entities, but we'll still pick up any that are valid
                    if (_containerSystem.IsEntityInContainer(entity) ||
                        entity == eventArgs.User ||
                        !HasComp <ItemComponent>(entity))
                    {
                        continue;
                    }

                    if (TryComp <TransformComponent>(uid, out var transformOwner) && TryComp <TransformComponent>(entity, out var transformEnt))
                    {
                        var position = EntityCoordinates.FromMap(transformOwner.Parent?.Owner ?? uid, transformEnt.MapPosition);

                        if (PlayerInsertEntityInWorld(uid, eventArgs.User, entity, storageComp))
                        {
                            successfullyInserted.Add(entity);
                            successfullyInsertedPositions.Add(position);
                        }
                    }
                }

                // If we picked up atleast one thing, play a sound and do a cool animation!
                if (successfullyInserted.Count > 0)
                {
                    if (storageComp.StorageInsertSound is not null)
                    {
                        SoundSystem.Play(storageComp.StorageInsertSound.GetSound(), Filter.Pvs(uid, entityManager: EntityManager), uid, AudioParams.Default);
                    }
                    RaiseNetworkEvent(new AnimateInsertingEntitiesEvent(uid, successfullyInserted, successfullyInsertedPositions));
                }
                return;
            }
            // Pick up the clicked entity
            else if (storageComp.QuickInsert)
            {
                if (eventArgs.Target is not {
                    Valid : true
                } target)
                {
                    return;
                }

                if (_containerSystem.IsEntityInContainer(target) ||
                    target == eventArgs.User ||
                    !HasComp <ItemComponent>(target))
                {
                    return;
                }

                if (TryComp <TransformComponent>(uid, out var transformOwner) && TryComp <TransformComponent>(target, out var transformEnt))
                {
                    var parent = transformOwner.ParentUid;

                    var position = EntityCoordinates.FromMap(
                        parent.IsValid() ? parent : uid,
                        transformEnt.MapPosition);
                    if (PlayerInsertEntityInWorld(uid, eventArgs.User, target, storageComp))
                    {
                        RaiseNetworkEvent(new AnimateInsertingEntitiesEvent(uid,
                                                                            new List <EntityUid> {
                            target
                        },
                                                                            new List <EntityCoordinates> {
                            position
                        }));
                    }
                }
            }
            return;
        }
Exemplo n.º 18
0
        public override void Update(float frameTime)
        {
            base.Update(frameTime);
            foreach (var drain in EntityQuery <DrainComponent>())
            {
                drain.Accumulator += frameTime;
                if (drain.Accumulator < drain.DrainFrequency)
                {
                    continue;
                }
                drain.Accumulator -= drain.DrainFrequency;

                /// Best to do this one every second rather than once every tick...
                _solutionSystem.TryGetSolution(drain.Owner, DrainComponent.SolutionName, out var drainSolution);

                if (drainSolution is null)
                {
                    return;
                }

                /// Remove a bit from the buffer
                _solutionSystem.SplitSolution(drain.Owner, drainSolution, (drain.UnitsDestroyedPerSecond * drain.DrainFrequency));

                /// This will ensure that UnitsPerSecond is per second...
                var amount = drain.UnitsPerSecond * drain.DrainFrequency;
                var xform  = Transform(drain.Owner);
                List <PuddleComponent> puddles = new();

                foreach (var entity in _lookup.GetEntitiesInRange(xform.MapPosition, drain.Range))
                {
                    /// No InRangeUnobstructed because there's no collision group that fits right now
                    /// and these are placed by mappers and not buildable/movable so shouldnt really be a problem...
                    if (TryComp <PuddleComponent>(entity, out var puddleComp))
                    {
                        puddles.Add(puddleComp);
                    }
                }

                if (puddles.Count == 0)
                {
                    _ambientSoundSystem.SetAmbience(drain.Owner, false);
                    continue;
                }

                _ambientSoundSystem.SetAmbience(drain.Owner, true);

                amount /= puddles.Count;

                foreach (var puddle in puddles)
                {
                    /// Queue the solution deletion if it's empty. EvaporationSystem might also do this
                    /// but queuedelete should be pretty safe.
                    if (!_solutionSystem.TryGetSolution(puddle.Owner, puddle.SolutionName, out var puddleSolution))
                    {
                        EntityManager.QueueDeleteEntity(puddle.Owner);
                        continue;
                    }

                    /// Removes the lowest of:
                    /// the drain component's units per second adjusted for # of puddles
                    /// the puddle's remaining volume (making it cleanly zero)
                    /// the drain's remaining volume in its buffer.
                    var transferSolution = _solutionSystem.SplitSolution(puddle.Owner, puddleSolution,
                                                                         FixedPoint2.Min(FixedPoint2.New(amount), puddleSolution.CurrentVolume, drainSolution.AvailableVolume));

                    _solutionSystem.TryAddSolution(drain.Owner, drainSolution, transferSolution);

                    if (puddleSolution.CurrentVolume <= 0)
                    {
                        EntityManager.QueueDeleteEntity(puddle.Owner);
                    }
                }
            }
        }