示例#1
0
    /// <summary>
    ///     Updates data periodically in case something died/got deleted in the morgue.
    /// </summary>
    private void CheckContents(EntityUid uid, MorgueComponent?morgue = null, EntityStorageComponent?storage = null, AppearanceComponent?app = null)
    {
        if (!Resolve(uid, ref morgue, ref storage, ref app))
        {
            return;
        }

        if (storage.Contents.ContainedEntities.Count == 0)
        {
            app.SetData(MorgueVisuals.Contents, MorgueContents.Empty);
            return;
        }

        var hasMob = false;

        foreach (var ent in storage.Contents.ContainedEntities)
        {
            if (!hasMob && HasComp <SharedBodyComponent>(ent))
            {
                hasMob = true;
            }

            if (TryComp <ActorComponent?>(ent, out var actor) && actor.PlayerSession != null)
            {
                app.SetData(MorgueVisuals.Contents, MorgueContents.HasSoul);
                return;
            }
        }

        app.SetData(MorgueVisuals.Contents, hasMob ? MorgueContents.HasMob : MorgueContents.HasContents);
    }
示例#2
0
        /// <summary>
        ///     Before locking the entity, check whether it's a locker. If is, prevent it from being locked from the inside or while it is open.
        /// </summary>
        public bool CanToggleLock(EntityUid uid, EntityUid user, EntityStorageComponent?storage = null, bool quiet = true)
        {
            if (!Resolve(uid, ref storage, logMissing: false))
            {
                return(true);
            }

            if (!HasComp <SharedHandsComponent>(user))
            {
                return(false);
            }

            // Cannot lock if the entity is currently opened.
            if (storage.Open)
            {
                return(false);
            }

            // Cannot (un)lock from the inside. Maybe a bad idea? Security jocks could trap nerds in lockers?
            if (storage.Contents.Contains(user))
            {
                return(false);
            }

            return(true);
        }
    public bool Remove(EntityUid toRemove, EntityUid container, EntityStorageComponent?component = null)
    {
        if (!Resolve(container, ref component))
        {
            return(false);
        }

        return(component.Contents.Remove(toRemove, EntityManager));
    }
    public void OpenStorage(EntityUid uid, EntityStorageComponent?component = null)
    {
        if (!Resolve(uid, ref component))
        {
            return;
        }

        component.Open = true;
        EmptyContents(uid, component);
        ModifyComponents(uid, component);
        SoundSystem.Play(component.OpenSound.GetSound(), Filter.Pvs(component.Owner), component.Owner);
        RaiseLocalEvent(uid, new StorageAfterOpenEvent());
    }
    public bool Insert(EntityUid toInsert, EntityUid container, EntityStorageComponent?component = null)
    {
        if (!Resolve(container, ref component))
        {
            return(false);
        }

        if (component.Open)
        {
            Transform(toInsert).WorldPosition = Transform(container).WorldPosition;
            return(true);
        }

        return(component.Contents.Insert(toInsert, EntityManager));
    }
示例#6
0
    public void TryCremate(EntityUid uid, CrematoriumComponent component, EntityStorageComponent?storage = null)
    {
        if (!Resolve(uid, ref storage))
        {
            return;
        }

        if (component.Cooking || storage.Open || storage.Contents.ContainedEntities.Count < 1)
        {
            return;
        }

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

        Cremate(uid, component, storage);
    }
    public void ToggleOpen(EntityUid user, EntityUid target, EntityStorageComponent?component = null)
    {
        if (!Resolve(target, ref component))
        {
            return;
        }

        if (component.Open)
        {
            TryCloseStorage(target);
        }
        else
        {
            TryOpenStorage(user, target);
        }
    }
示例#8
0
    public void Cremate(EntityUid uid, CrematoriumComponent?component = null, EntityStorageComponent?storage = null)
    {
        if (!Resolve(uid, ref component, ref storage))
        {
            return;
        }

        if (TryComp <AppearanceComponent>(uid, out var app))
        {
            app.SetData(CrematoriumVisuals.Burning, true);
        }
        component.Cooking = true;

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

        component.CremateCancelToken?.Cancel();
        component.CremateCancelToken = new CancellationTokenSource();
        uid.SpawnTimer(component.BurnMilis, () =>
        {
            if (Deleted(uid))
            {
                return;
            }
            if (TryComp <AppearanceComponent>(uid, out var app))
            {
                app.SetData(CrematoriumVisuals.Burning, false);
            }
            component.Cooking = false;

            if (storage.Contents.ContainedEntities.Count > 0)
            {
                for (var i = storage.Contents.ContainedEntities.Count - 1; i >= 0; i--)
                {
                    var item = storage.Contents.ContainedEntities[i];
                    storage.Contents.Remove(item);
                    EntityManager.DeleteEntity(item);
                }

                var ash = Spawn("Ash", Transform(uid).Coordinates);
                storage.Contents.Insert(ash);
            }

            _entityStorage.OpenStorage(uid, storage);

            SoundSystem.Play(component.CremateFinishSound.GetSound(), Filter.Pvs(uid), uid);
        }, component.CremateCancelToken.Token);
    }
    public bool CanOpen(EntityUid user, EntityUid target, bool silent = false, EntityStorageComponent?component = null)
    {
        if (!Resolve(target, ref component))
        {
            return(false);
        }

        if (!HasComp <SharedHandsComponent>(user))
        {
            return(false);
        }

        if (component.IsWeldedShut)
        {
            if (!silent && !component.Contents.Contains(user))
            {
                _popupSystem.PopupEntity(Loc.GetString("entity-storage-component-welded-shut-message"), target, Filter.Pvs(target));
            }

            return(false);
        }

        //Checks to see if the opening position, if offset, is inside of a wall.
        if (component.EnteringOffset != (0, 0)) //if the entering position is offset
        {
            var targetXform = Transform(target);
            var newCoords   = new EntityCoordinates(target, component.EnteringOffset);
            if (!_interactionSystem.InRangeUnobstructed(target, newCoords, collisionMask: component.EnteringOffsetCollisionFlags))
            {
                if (!silent)
                {
                    _popupSystem.PopupEntity(Loc.GetString("entity-storage-component-cannot-open-no-space"), target, Filter.Pvs(target));
                }

                return(false);
            }
        }

        var ev = new StorageOpenAttemptEvent(silent);

        RaiseLocalEvent(target, ev, true);

        return(!ev.Cancelled);
    }
    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());
    }
    public bool CanInsert(EntityUid container, EntityStorageComponent?component = null)
    {
        if (!Resolve(container, ref component))
        {
            return(false);
        }

        if (component.Open)
        {
            return(true);
        }

        if (component.Contents.ContainedEntities.Count >= component.Capacity)
        {
            return(false);
        }

        return(true);
    }
    public void EmptyContents(EntityUid uid, EntityStorageComponent?component = null)
    {
        if (!Resolve(uid, ref component))
        {
            return;
        }

        var uidXform     = Transform(uid);
        var containedArr = component.Contents.ContainedEntities.ToArray();

        foreach (var contained in containedArr)
        {
            if (component.Contents.Remove(contained))
            {
                Transform(contained).WorldPosition =
                    uidXform.WorldPosition + uidXform.WorldRotation.RotateVec(component.EnteringOffset);
            }
        }
    }
    public void EmptyContents(EntityUid uid, EntityStorageComponent?component = null)
    {
        if (!Resolve(uid, ref component))
        {
            return;
        }

        var containedArr = component.Contents.ContainedEntities.ToArray();

        foreach (var contained in containedArr)
        {
            if (component.Contents.Remove(contained))
            {
                Transform(contained).WorldPosition = component.ContentsDumpPosition();
                if (TryComp(contained, out IPhysBody? physics))
                {
                    physics.CanCollide = true;
                }
            }
        }
    }
    public bool AddToContents(EntityUid toAdd, EntityUid container, EntityStorageComponent?component = null)
    {
        if (!Resolve(container, ref component))
        {
            return(false);
        }

        if (toAdd == container)
        {
            return(false);
        }

        if (TryComp <IPhysBody>(toAdd, out var phys))
        {
            if (component.MaxSize < phys.GetWorldAABB().Size.X || component.MaxSize < phys.GetWorldAABB().Size.Y)
            {
                return(false);
            }
        }

        return(Insert(toAdd, container, component));
    }
    public void ModifyComponents(EntityUid uid, EntityStorageComponent?component = null)
    {
        if (!Resolve(uid, ref component))
        {
            return;
        }

        if (!component.IsCollidableWhenOpen && TryComp <FixturesComponent>(uid, out var fixtures) && fixtures.Fixtures.Count > 0)
        {
            // currently only works for single-fixture entities. If they have more than one fixture, then
            // RemovedMasks needs to be tracked separately for each fixture, using a fixture Id Dictionary. Also the
            // fixture IDs probably cant be automatically generated without causing issues, unless there is some
            // guarantee that they will get deserialized with the same auto-generated ID when saving+loading the map.
            var fixture = fixtures.Fixtures.Values.First();

            if (component.Open)
            {
                component.RemovedMasks  = fixture.CollisionLayer & component.MasksToRemove;
                fixture.CollisionLayer &= ~component.MasksToRemove;
            }
            else
            {
                fixture.CollisionLayer |= component.RemovedMasks;
                component.RemovedMasks  = 0;
            }
        }

        if (TryComp <PlaceableSurfaceComponent>(uid, out var surface))
        {
            _placeableSurface.SetPlaceable(uid, true, surface);
        }

        if (TryComp <AppearanceComponent>(uid, out var appearance))
        {
            appearance.SetData(StorageVisuals.Open, component.Open);
            appearance.SetData(StorageVisuals.HasContents, component.Contents.ContainedEntities.Count() > 0);
        }
    }
    private void AttemptResist(EntityUid user, EntityUid target, EntityStorageComponent?storageComponent = null, ResistLockerComponent?resistLockerComponent = null)
    {
        if (!Resolve(target, ref storageComponent, ref resistLockerComponent))
        {
            return;
        }

        resistLockerComponent.CancelToken = new();
        var doAfterEventArgs = new DoAfterEventArgs(user, resistLockerComponent.ResistTime, resistLockerComponent.CancelToken.Token, target)
        {
            BreakOnTargetMove    = false,
            BreakOnUserMove      = true,
            BreakOnDamage        = true,
            BreakOnStun          = true,
            NeedHand             = false, //No hands 'cause we be kickin'
            TargetFinishedEvent  = new ResistDoAfterComplete(user, target),
            TargetCancelledEvent = new ResistDoAfterCancelled(user)
        };

        resistLockerComponent.IsResisting = true;
        _popupSystem.PopupEntity(Loc.GetString("resist-locker-component-start-resisting"), user, Filter.Entities(user));
        _doAfterSystem.DoAfter(doAfterEventArgs);
    }