Artifact container (#7822)
Co-authored-by: Kara <lunarautomaton6@gmail.com>
@@ -145,6 +145,7 @@ namespace Content.Client.Entry
|
|||||||
"VentCritterSpawnLocation",
|
"VentCritterSpawnLocation",
|
||||||
"RadiateArtifact",
|
"RadiateArtifact",
|
||||||
"TemperatureArtifact",
|
"TemperatureArtifact",
|
||||||
|
"SuppressArtifactContainer",
|
||||||
"DisposalHolder",
|
"DisposalHolder",
|
||||||
"DisposalTagger",
|
"DisposalTagger",
|
||||||
"DisposalRouter",
|
"DisposalRouter",
|
||||||
@@ -290,6 +291,7 @@ namespace Content.Client.Entry
|
|||||||
"AmbientOnPowered",
|
"AmbientOnPowered",
|
||||||
"DoorSignalControl",
|
"DoorSignalControl",
|
||||||
"Wieldable",
|
"Wieldable",
|
||||||
|
"ArtifactStorage",
|
||||||
"IncreaseDamageOnWield",
|
"IncreaseDamageOnWield",
|
||||||
"TabletopGame",
|
"TabletopGame",
|
||||||
"LitOnPowered",
|
"LitOnPowered",
|
||||||
|
|||||||
@@ -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<ArtifactComponent>(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -232,51 +232,10 @@ namespace Content.Server.Storage.Components
|
|||||||
if (entity.IsInContainer())
|
if (entity.IsInContainer())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// conditions are complicated because of pizzabox-related issues, so follow this guide
|
if (!CanFit(entity))
|
||||||
// 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<GhostComponent>(entity))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// checks
|
|
||||||
|
|
||||||
var targetIsItem = _entMan.HasComponent<SharedItemComponent>(entity);
|
|
||||||
var targetIsMob = _entMan.HasComponent<SharedBodyComponent>(entity);
|
|
||||||
var storageIsItem = _entMan.HasComponent<SharedItemComponent>(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)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// finally, AddToContents
|
// finally, AddToContents
|
||||||
|
|
||||||
if (!AddToContents(entity))
|
if (!AddToContents(entity))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -292,6 +251,48 @@ namespace Content.Server.Storage.Components
|
|||||||
LastInternalOpenAttempt = default;
|
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<GhostComponent>(entity))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// checks
|
||||||
|
|
||||||
|
var targetIsItem = _entMan.HasComponent<SharedItemComponent>(entity);
|
||||||
|
var targetIsMob = _entMan.HasComponent<SharedBodyComponent>(entity);
|
||||||
|
var storageIsItem = _entMan.HasComponent<SharedItemComponent>(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()
|
protected virtual void OpenStorage()
|
||||||
{
|
{
|
||||||
Open = true;
|
Open = true;
|
||||||
|
|||||||
@@ -28,5 +28,12 @@ public sealed class ArtifactComponent : Component
|
|||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public double CooldownTime = 10;
|
public double CooldownTime = 10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is this artifact under some suppression device?
|
||||||
|
/// If true, will ignore all trigger activations attempts.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool IsSuppressed;
|
||||||
|
|
||||||
public TimeSpan LastActivationTime;
|
public TimeSpan LastActivationTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ public sealed class ArtifactSystem : EntitySystem
|
|||||||
if (!Resolve(uid, ref component))
|
if (!Resolve(uid, ref component))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// check if artifact is under suppression field
|
||||||
|
if (component.IsSuppressed)
|
||||||
|
return false;
|
||||||
|
|
||||||
// check if artifact isn't under cooldown
|
// check if artifact isn't under cooldown
|
||||||
var timeDif = _gameTiming.CurTime - component.LastActivationTime;
|
var timeDif = _gameTiming.CurTime - component.LastActivationTime;
|
||||||
if (timeDif.TotalSeconds < component.CooldownTime)
|
if (timeDif.TotalSeconds < component.CooldownTime)
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Equipment.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Suppress artifact activation, when entity is placed inside this container.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class SuppressArtifactContainerComponent : Component
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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<SuppressArtifactContainerComponent, EntInsertedIntoContainerMessage>(OnInserted);
|
||||||
|
SubscribeLocalEvent<SuppressArtifactContainerComponent, EntRemovedFromContainerMessage>(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -162,6 +162,7 @@
|
|||||||
- AtmosphericsOxygen
|
- AtmosphericsOxygen
|
||||||
- AtmosphericsNitrogen
|
- AtmosphericsNitrogen
|
||||||
- AtmosphericsCarbonDioxide
|
- AtmosphericsCarbonDioxide
|
||||||
|
- ArtifactContainer
|
||||||
- type: CrewMonitoringConsole
|
- type: CrewMonitoringConsole
|
||||||
snap: false
|
snap: false
|
||||||
precision: 3
|
precision: 3
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
abstract: true
|
abstract: true
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
|
drawdepth: SmallObjects
|
||||||
sprite: Objects/Specific/Xenoarchaeology/xeno_artifacts.rsi
|
sprite: Objects/Specific/Xenoarchaeology/xeno_artifacts.rsi
|
||||||
netsync: false
|
netsync: false
|
||||||
state: ano01
|
state: ano01
|
||||||
|
|||||||
@@ -412,6 +412,7 @@
|
|||||||
- AtmosphericsOxygen
|
- AtmosphericsOxygen
|
||||||
- AtmosphericsNitrogen
|
- AtmosphericsNitrogen
|
||||||
- AtmosphericsCarbonDioxide
|
- AtmosphericsCarbonDioxide
|
||||||
|
- ArtifactContainer
|
||||||
# - AtmosphericsWaterVapor
|
# - AtmosphericsWaterVapor
|
||||||
# - AtmosphericsPlasma
|
# - AtmosphericsPlasma
|
||||||
# - AtmosphericsTritium
|
# - AtmosphericsTritium
|
||||||
|
|||||||
|
After Width: | Height: | Size: 494 B |
|
After Width: | Height: | Size: 393 B |
|
After Width: | Height: | Size: 575 B |
|
After Width: | Height: | Size: 404 B |
|
After Width: | Height: | Size: 198 B |
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 203 B |
|
After Width: | Height: | Size: 375 B |