/// <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); }
/// <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)); }
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); } }
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); }