From b9e1f9283d7013954c9f24fa15680bab150e4cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Aguilera=20Puerto?= <6766154+Zumorica@users.noreply.github.com> Date: Sun, 26 Jul 2020 20:49:41 +0200 Subject: [PATCH] Adds cursed lockers that teleport anything inside them to other lockers (#1493) --- .../Tests/ContainerOcclusionTest.cs | 1 + .../Inventory/CloseStorageOperator.cs | 1 + .../Inventory/OpenStorageOperator.cs | 1 + .../Containers/TargetAccessibleCon.cs | 1 + .../States/Clothing/NearbyClothingState.cs | 1 + .../Explosion/FlashExplosiveComponent.cs | 3 +- .../Storage/CursedEntityStorageComponent.cs | 60 +++++++++++++++++++ .../Items/Storage/EntityStorageComponent.cs | 40 ++++++------- .../Prototypes/Catalog/Fills/lockers.yml | 9 +++ 9 files changed, 96 insertions(+), 21 deletions(-) create mode 100644 Content.Server/GameObjects/Components/Items/Storage/CursedEntityStorageComponent.cs diff --git a/Content.IntegrationTests/Tests/ContainerOcclusionTest.cs b/Content.IntegrationTests/Tests/ContainerOcclusionTest.cs index f73009c28d..c3b84b42b5 100644 --- a/Content.IntegrationTests/Tests/ContainerOcclusionTest.cs +++ b/Content.IntegrationTests/Tests/ContainerOcclusionTest.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Threading.Tasks; using Content.Server.GameObjects.Components; +using Content.Server.GameObjects.Components.Items.Storage; using NUnit.Framework; using Robust.Client.GameObjects; using Robust.Server.Interfaces.Player; diff --git a/Content.Server/AI/Operators/Inventory/CloseStorageOperator.cs b/Content.Server/AI/Operators/Inventory/CloseStorageOperator.cs index d8aac40278..7876711556 100644 --- a/Content.Server/AI/Operators/Inventory/CloseStorageOperator.cs +++ b/Content.Server/AI/Operators/Inventory/CloseStorageOperator.cs @@ -1,6 +1,7 @@ using Content.Server.AI.Utility; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects.Components; +using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.Utility; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Server/AI/Operators/Inventory/OpenStorageOperator.cs b/Content.Server/AI/Operators/Inventory/OpenStorageOperator.cs index a5216cd76f..b27b58c3ea 100644 --- a/Content.Server/AI/Operators/Inventory/OpenStorageOperator.cs +++ b/Content.Server/AI/Operators/Inventory/OpenStorageOperator.cs @@ -1,6 +1,7 @@ using Content.Server.AI.Utility; using Content.Server.AI.WorldState.States.Inventory; using Content.Server.GameObjects.Components; +using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.Utility; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.Containers; diff --git a/Content.Server/AI/Utility/Considerations/Containers/TargetAccessibleCon.cs b/Content.Server/AI/Utility/Considerations/Containers/TargetAccessibleCon.cs index 6ad25d3b4d..5c017aaa5e 100644 --- a/Content.Server/AI/Utility/Considerations/Containers/TargetAccessibleCon.cs +++ b/Content.Server/AI/Utility/Considerations/Containers/TargetAccessibleCon.cs @@ -1,6 +1,7 @@ using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Server.GameObjects.Components; +using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Movement; using Content.Server.GameObjects.EntitySystems.AI.Pathfinding; using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Accessible; diff --git a/Content.Server/AI/WorldState/States/Clothing/NearbyClothingState.cs b/Content.Server/AI/WorldState/States/Clothing/NearbyClothingState.cs index 83a54abee1..4d231273fa 100644 --- a/Content.Server/AI/WorldState/States/Clothing/NearbyClothingState.cs +++ b/Content.Server/AI/WorldState/States/Clothing/NearbyClothingState.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Content.Server.AI.Utils; using Content.Server.GameObjects; using Content.Server.GameObjects.Components; +using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Movement; using JetBrains.Annotations; using Robust.Shared.Containers; diff --git a/Content.Server/GameObjects/Components/Explosion/FlashExplosiveComponent.cs b/Content.Server/GameObjects/Components/Explosion/FlashExplosiveComponent.cs index 3e493bccf2..4aec5f7fbc 100644 --- a/Content.Server/GameObjects/Components/Explosion/FlashExplosiveComponent.cs +++ b/Content.Server/GameObjects/Components/Explosion/FlashExplosiveComponent.cs @@ -1,4 +1,5 @@ -using Content.Server.GameObjects.Components.Weapon; +using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.Components.Weapon; using Content.Server.Interfaces.GameObjects.Components.Interaction; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.Containers; diff --git a/Content.Server/GameObjects/Components/Items/Storage/CursedEntityStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/CursedEntityStorageComponent.cs new file mode 100644 index 0000000000..7f2c5ab711 --- /dev/null +++ b/Content.Server/GameObjects/Components/Items/Storage/CursedEntityStorageComponent.cs @@ -0,0 +1,60 @@ +using System.Linq; +using Content.Server.Interfaces.GameObjects.Components.Interaction; +using Content.Shared.Audio; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.Interfaces.GameObjects.Components; +using Microsoft.EntityFrameworkCore.Internal; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Random; +using Robust.Shared.IoC; +using Robust.Shared.Log; +using Robust.Shared.Random; + +namespace Content.Server.GameObjects.Components.Items.Storage +{ + [ComponentReference(typeof(EntityStorageComponent))] + [ComponentReference(typeof(IActivate))] + [ComponentReference(typeof(IStorageComponent))] + [RegisterComponent] + public class CursedEntityStorageComponent : EntityStorageComponent + { + [Dependency] private IEntityManager _entityManager = default!; + [Dependency] private IRobustRandom _robustRandom = default!; + + public override string Name => "CursedEntityStorage"; + + public override void CloseStorage() + { + base.CloseStorage(); + + // No contents, we do nothing + if (Contents.ContainedEntities.Count == 0) return; + + var lockers = _entityManager.GetEntities(new TypeEntityQuery(typeof(EntityStorageComponent))).ToList(); + + if (lockers.Contains(Owner)) + lockers.Remove(Owner); + + var lockerEnt = _robustRandom.Pick(lockers); + + if (lockerEnt == null) return; // No valid lockers anywhere. + + var locker = lockerEnt.GetComponent(); + + if(locker.Open) + locker.CloseStorage(); + + foreach (var entity in Contents.ContainedEntities.ToArray()) + { + Contents.ForceRemove(entity); + locker.Insert(entity); + } + + EntitySystem.Get().PlayFromEntity("/Audio/Effects/teleport_departure.ogg", Owner, AudioHelpers.WithVariation(0.125f)); + EntitySystem.Get().PlayFromEntity("/Audio/Effects/teleport_arrival.ogg", lockerEnt, AudioHelpers.WithVariation(0.125f)); + } + } +} diff --git a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs index 5e88608124..5a22ddd354 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs @@ -2,7 +2,6 @@ using System.Linq; using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Interactable; -using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.Interfaces.GameObjects.Components.Interaction; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Interactable; @@ -26,7 +25,7 @@ using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; -namespace Content.Server.GameObjects.Components +namespace Content.Server.GameObjects.Components.Items.Storage { [RegisterComponent] [ComponentReference(typeof(IActivate))] @@ -45,8 +44,6 @@ namespace Content.Server.GameObjects.Components [ViewVariables] private bool _isCollidableWhenOpen; [ViewVariables] - private Container _contents; - [ViewVariables] private IEntityQuery _entityQuery; private bool _showContents; private bool _occludesLight; @@ -55,6 +52,9 @@ namespace Content.Server.GameObjects.Components private int _collisionMaskStorage; private int _collisionLayerStorage; + [ViewVariables] + protected Container Contents; + /// /// Determines if the container contents should be drawn when the container is closed. /// @@ -65,7 +65,7 @@ namespace Content.Server.GameObjects.Components set { _showContents = value; - _contents.ShowContents = _showContents; + Contents.ShowContents = _showContents; } } @@ -76,7 +76,7 @@ namespace Content.Server.GameObjects.Components set { _occludesLight = value; - _contents.OccludesLight = _occludesLight; + Contents.OccludesLight = _occludesLight; } } @@ -109,11 +109,11 @@ namespace Content.Server.GameObjects.Components public override void Initialize() { base.Initialize(); - _contents = ContainerManagerComponent.Ensure(nameof(EntityStorageComponent), Owner); + Contents = ContainerManagerComponent.Ensure(nameof(EntityStorageComponent), Owner); _entityQuery = new IntersectingEntityQuery(Owner); - _contents.ShowContents = _showContents; - _contents.OccludesLight = _occludesLight; + Contents.ShowContents = _showContents; + Contents.OccludesLight = _occludesLight; if (Owner.TryGetComponent(out var placeableSurfaceComponent)) { @@ -140,7 +140,7 @@ namespace Content.Server.GameObjects.Components ToggleOpen(eventArgs.User); } - protected virtual void ToggleOpen(IEntity user) + private void ToggleOpen(IEntity user) { if (IsWeldedShut) { @@ -158,7 +158,7 @@ namespace Content.Server.GameObjects.Components } } - private void CloseStorage() + public virtual void CloseStorage() { Open = false; var entities = Owner.EntityManager.GetEntities(_entityQuery); @@ -256,7 +256,7 @@ namespace Content.Server.GameObjects.Components entity.Transform.WorldPosition += new Vector2(0, collidableComponent.WorldAABB.Top - entityCollidableComponent.WorldAABB.Top); } } - if (_contents.CanInsert(entity)) + if (Contents.CanInsert(entity)) { // Because Insert sets the local position to (0,0), and we want to keep the contents spread out, // we re-apply the world position after inserting. @@ -269,7 +269,7 @@ namespace Content.Server.GameObjects.Components { worldPos = entity.Transform.WorldPosition; } - _contents.Insert(entity); + Contents.Insert(entity); entity.Transform.WorldPosition = worldPos; if (entityCollidableComponent != null) { @@ -282,9 +282,9 @@ namespace Content.Server.GameObjects.Components private void EmptyContents() { - foreach (var contained in _contents.ContainedEntities.ToArray()) + foreach (var contained in Contents.ContainedEntities.ToArray()) { - if(_contents.Remove(contained)) + if(Contents.Remove(contained)) { if (contained.TryGetComponent(out var entityCollidableComponent)) { @@ -331,7 +331,7 @@ namespace Content.Server.GameObjects.Components /// public bool Remove(IEntity entity) { - return _contents.CanRemove(entity); + return Contents.CanRemove(entity); } /// @@ -344,7 +344,7 @@ namespace Content.Server.GameObjects.Components return true; } - return _contents.Insert(entity); + return Contents.Insert(entity); } /// @@ -355,12 +355,12 @@ namespace Content.Server.GameObjects.Components return true; } - if (_contents.ContainedEntities.Count >= _storageCapacityMax) + if (Contents.ContainedEntities.Count >= _storageCapacityMax) { return false; } - return _contents.CanInsert(entity); + return Contents.CanInsert(entity); } bool IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) @@ -372,7 +372,7 @@ namespace Content.Server.GameObjects.Components if (!CanWeldShut) return false; - if (_contents.Contains(eventArgs.User)) + if (Contents.Contains(eventArgs.User)) { Owner.PopupMessage(eventArgs.User, Loc.GetString("It's too Cramped!")); return false; diff --git a/Resources/Prototypes/Catalog/Fills/lockers.yml b/Resources/Prototypes/Catalog/Fills/lockers.yml index a805b806b1..dce7215253 100644 --- a/Resources/Prototypes/Catalog/Fills/lockers.yml +++ b/Resources/Prototypes/Catalog/Fills/lockers.yml @@ -289,3 +289,12 @@ id: WardrobeMixedFilled suffix: Filled parent: WardrobeMixed + +- type: entity + id: LockerCursed + parent: LockerGeneric + name: "closet" + suffix: "cursed" + description: "A standard-issue Nanotrasen storage unit." + components: + - type: CursedEntityStorage