diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index a4ce1012a2..a9a5a765b8 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -145,6 +145,7 @@ namespace Content.Client.Entry "VentCritterSpawnLocation", "RadiateArtifact", "TemperatureArtifact", + "SuppressArtifactContainer", "DisposalHolder", "DisposalTagger", "DisposalRouter", @@ -290,6 +291,7 @@ namespace Content.Client.Entry "AmbientOnPowered", "DoorSignalControl", "Wieldable", + "ArtifactStorage", "IncreaseDamageOnWield", "TabletopGame", "LitOnPowered", diff --git a/Content.Server/Storage/Components/ArtifactStorageComponent.cs b/Content.Server/Storage/Components/ArtifactStorageComponent.cs new file mode 100644 index 0000000000..13684aee68 --- /dev/null +++ b/Content.Server/Storage/Components/ArtifactStorageComponent.cs @@ -0,0 +1,14 @@ +using Content.Server.Xenoarchaeology.XenoArtifacts; + +namespace Content.Server.Storage.Components; + +[RegisterComponent] +public sealed class ArtifactStorageComponent : EntityStorageComponent +{ + [Dependency] private readonly IEntityManager _entMan = default!; + + public override bool CanFit(EntityUid entity) + { + return _entMan.HasComponent(entity); + } +} diff --git a/Content.Server/Storage/Components/EntityStorageComponent.cs b/Content.Server/Storage/Components/EntityStorageComponent.cs index 6d223e97e5..626935df9c 100644 --- a/Content.Server/Storage/Components/EntityStorageComponent.cs +++ b/Content.Server/Storage/Components/EntityStorageComponent.cs @@ -232,51 +232,10 @@ namespace Content.Server.Storage.Components if (entity.IsInContainer()) continue; - // conditions are complicated because of pizzabox-related issues, so follow this guide - // 0. Accomplish your goals at all costs. - // 1. AddToContents can block anything - // 2. maximum item count can block anything - // 3. ghosts can NEVER be eaten - // 4. items can always be eaten unless a previous law prevents it - // 5. if this is NOT AN ITEM, then mobs can always be eaten unless unless a previous law prevents it - // 6. if this is an item, then mobs must only be eaten if some other component prevents pick-up interactions while a mob is inside (e.g. foldable) - - // Let's not insert admin ghosts, yeah? This is really a a hack and should be replaced by attempt events - if (_entMan.HasComponent(entity)) - continue; - - // checks - - var targetIsItem = _entMan.HasComponent(entity); - var targetIsMob = _entMan.HasComponent(entity); - var storageIsItem = _entMan.HasComponent(Owner); - - var allowedToEat = false; - - if (targetIsItem) - allowedToEat = true; - - // BEFORE REPLACING THIS WITH, I.E. A PROPERTY: - // Make absolutely 100% sure you have worked out how to stop people ending up in backpacks. - // Seriously, it is insanely hacky and weird to get someone out of a backpack once they end up in there. - // And to be clear, they should NOT be in there. - // For the record, what you need to do is empty the backpack onto a PlacableSurface (table, rack) - if (targetIsMob) - { - if (!storageIsItem) - allowedToEat = true; - else - { - // make an exception if this is a foldable-item that is currently un-folded (e.g., body bags). - allowedToEat = _entMan.TryGetComponent(Owner, out FoldableComponent? foldable) && !foldable.IsFolded; - } - } - - if (!allowedToEat) + if (!CanFit(entity)) continue; // finally, AddToContents - if (!AddToContents(entity)) continue; @@ -292,6 +251,48 @@ namespace Content.Server.Storage.Components LastInternalOpenAttempt = default; } + public virtual bool CanFit(EntityUid entity) + { + // conditions are complicated because of pizzabox-related issues, so follow this guide + // 0. Accomplish your goals at all costs. + // 1. AddToContents can block anything + // 2. maximum item count can block anything + // 3. ghosts can NEVER be eaten + // 4. items can always be eaten unless a previous law prevents it + // 5. if this is NOT AN ITEM, then mobs can always be eaten unless unless a previous law prevents it + // 6. if this is an item, then mobs must only be eaten if some other component prevents pick-up interactions while a mob is inside (e.g. foldable) + + // Let's not insert admin ghosts, yeah? This is really a a hack and should be replaced by attempt events + if (_entMan.HasComponent(entity)) + return false; + + // checks + + var targetIsItem = _entMan.HasComponent(entity); + var targetIsMob = _entMan.HasComponent(entity); + var storageIsItem = _entMan.HasComponent(Owner); + + var allowedToEat = targetIsItem; + + // BEFORE REPLACING THIS WITH, I.E. A PROPERTY: + // Make absolutely 100% sure you have worked out how to stop people ending up in backpacks. + // Seriously, it is insanely hacky and weird to get someone out of a backpack once they end up in there. + // And to be clear, they should NOT be in there. + // For the record, what you need to do is empty the backpack onto a PlacableSurface (table, rack) + if (targetIsMob) + { + if (!storageIsItem) + allowedToEat = true; + else + { + // make an exception if this is a foldable-item that is currently un-folded (e.g., body bags). + allowedToEat = _entMan.TryGetComponent(Owner, out FoldableComponent? foldable) && !foldable.IsFolded; + } + } + + return allowedToEat; + } + protected virtual void OpenStorage() { Open = true; diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactComponent.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactComponent.cs index 06f1816326..17e23c4e81 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactComponent.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactComponent.cs @@ -28,5 +28,12 @@ public sealed class ArtifactComponent : Component [ViewVariables(VVAccess.ReadWrite)] public double CooldownTime = 10; + /// + /// Is this artifact under some suppression device? + /// If true, will ignore all trigger activations attempts. + /// + [ViewVariables(VVAccess.ReadWrite)] + public bool IsSuppressed; + public TimeSpan LastActivationTime; } diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs index a5ed618d1c..365e13d81f 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.cs @@ -49,6 +49,10 @@ public sealed class ArtifactSystem : EntitySystem if (!Resolve(uid, ref component)) return false; + // check if artifact is under suppression field + if (component.IsSuppressed) + return false; + // check if artifact isn't under cooldown var timeDif = _gameTiming.CurTime - component.LastActivationTime; if (timeDif.TotalSeconds < component.CooldownTime) diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Equipment/Components/SuppressArtifactContainerComponent.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Equipment/Components/SuppressArtifactContainerComponent.cs new file mode 100644 index 0000000000..fddcf44438 --- /dev/null +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Equipment/Components/SuppressArtifactContainerComponent.cs @@ -0,0 +1,10 @@ +namespace Content.Server.Xenoarchaeology.XenoArtifacts.Equipment.Components; + +/// +/// Suppress artifact activation, when entity is placed inside this container. +/// +[RegisterComponent] +public sealed class SuppressArtifactContainerComponent : Component +{ + +} diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Equipment/Systems/SuppressArtifactContainerSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Equipment/Systems/SuppressArtifactContainerSystem.cs new file mode 100644 index 0000000000..3015b6c11a --- /dev/null +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Equipment/Systems/SuppressArtifactContainerSystem.cs @@ -0,0 +1,30 @@ +using Content.Server.Xenoarchaeology.XenoArtifacts.Equipment.Components; +using Robust.Shared.Containers; + +namespace Content.Server.Xenoarchaeology.XenoArtifacts.Equipment.Systems; + +public sealed class SuppressArtifactContainerSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnInserted); + SubscribeLocalEvent(OnRemoved); + } + + private void OnInserted(EntityUid uid, SuppressArtifactContainerComponent component, EntInsertedIntoContainerMessage args) + { + if (!TryComp(args.Entity, out ArtifactComponent? artifact)) + return; + + artifact.IsSuppressed = true; + } + + private void OnRemoved(EntityUid uid, SuppressArtifactContainerComponent component, EntRemovedFromContainerMessage args) + { + if (!TryComp(args.Entity, out ArtifactComponent? artifact)) + return; + + artifact.IsSuppressed = false; + } +} diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_science.yml b/Resources/Prototypes/Catalog/Cargo/cargo_science.yml index e69de29bb2..3c10051e62 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_science.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_science.yml @@ -0,0 +1,11 @@ +- type: cargoProduct + name: "Artifact Container" + id: ArtifactContainer + description: Used to safely contain and move artifacts. + icon: + sprite: Structures/Storage/Crates/artifact.rsi + state: artifact_container_icon + product: CrateArtifactContainer + cost: 2000 + category: Science + group: market diff --git a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml index 8f8bfdf7b5..d250376306 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml @@ -162,6 +162,7 @@ - AtmosphericsOxygen - AtmosphericsNitrogen - AtmosphericsCarbonDioxide + - ArtifactContainer - type: CrewMonitoringConsole snap: false precision: 3 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/artifact_equipment.yml b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/artifact_equipment.yml new file mode 100644 index 0000000000..82d7eeac12 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/artifact_equipment.yml @@ -0,0 +1,70 @@ +- type: entity + id: CrateArtifactContainer + name: artifact container + description: Used to safely contain and move artifacts. + parent: BaseStructureDynamic + components: + - type: Transform + noRot: true + - type: AccessReader + access: [["Research"], ["Salvage"]] + - type: Lock + - type: Sprite + drawdepth: Objects + netsync: false + sprite: Structures/Storage/Crates/artifact.rsi + layers: + - state: artifact_container + - state: artifact_container_door + map: ["enum.StorageVisualLayers.Door"] + - state: welded + visible: false + map: ["enum.StorageVisualLayers.Welded"] + - state: locked + map: ["enum.StorageVisualLayers.Lock"] + shader: unshaded + - type: InteractionOutline + - type: Physics + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.45 + mass: 150 + mask: + - Impassable + layer: + - Opaque + - MobImpassable + - SmallImpassable + - type: Icon + sprite: Structures/Storage/Crates/artifact.rsi + state: artifact_container_icon + - type: ArtifactStorage + Capacity: 1 + CanWeldShut: true + - type: SuppressArtifactContainer + - type: PlaceableSurface + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Metallic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 50 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - type: PaperLabel + labelSlot: + insertVerbText: Attach Label + ejectVerbText: Remove Label + whitelist: + components: + - Paper + - type: Appearance + visuals: + - type: StorageVisualizer + state_open: artifact_container_open + state_closed: artifact_container_door diff --git a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/artifacts.yml b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/artifacts.yml index fdcc689656..97e651d4bd 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/artifacts.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/artifacts.yml @@ -6,6 +6,7 @@ abstract: true components: - type: Sprite + drawdepth: SmallObjects sprite: Objects/Specific/Xenoarchaeology/xeno_artifacts.rsi netsync: false state: ano01 diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index f265df3597..58f5922e33 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -412,6 +412,7 @@ - AtmosphericsOxygen - AtmosphericsNitrogen - AtmosphericsCarbonDioxide + - ArtifactContainer # - AtmosphericsWaterVapor # - AtmosphericsPlasma # - AtmosphericsTritium diff --git a/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container.png b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container.png new file mode 100644 index 0000000000..124d7c3321 Binary files /dev/null and b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container.png differ diff --git a/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_door.png b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_door.png new file mode 100644 index 0000000000..ad18eb369b Binary files /dev/null and b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_door.png differ diff --git a/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_icon.png b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_icon.png new file mode 100644 index 0000000000..c5285747a0 Binary files /dev/null and b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_icon.png differ diff --git a/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_open.png b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_open.png new file mode 100644 index 0000000000..d7f50625c5 Binary files /dev/null and b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/artifact_container_open.png differ diff --git a/Resources/Textures/Structures/Storage/Crates/artifact.rsi/locked.png b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/locked.png new file mode 100644 index 0000000000..ddc830c2f4 Binary files /dev/null and b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/locked.png differ diff --git a/Resources/Textures/Structures/Storage/Crates/artifact.rsi/meta.json b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/meta.json new file mode 100644 index 0000000000..7a17f38fa5 --- /dev/null +++ b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/meta.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from baystation at commit https://github.com/Baystation12/Baystation12/commit/a929584d9db319eb7484113221be25cfa1d5dc09", + "states": [ + { + "name": "artifact_container" + }, + { + "name": "artifact_container_door" + }, + { + "name": "artifact_container_open" + }, + { + "name": "artifact_container_icon" + }, + { + "name": "locked" + }, + { + "name": "unlocked" + }, + { + "name": "welded" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Structures/Storage/Crates/artifact.rsi/unlocked.png b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/unlocked.png new file mode 100644 index 0000000000..52e00d771c Binary files /dev/null and b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/unlocked.png differ diff --git a/Resources/Textures/Structures/Storage/Crates/artifact.rsi/welded.png b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/welded.png new file mode 100644 index 0000000000..fce9c8fd94 Binary files /dev/null and b/Resources/Textures/Structures/Storage/Crates/artifact.rsi/welded.png differ