From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
Date: Mon, 10 Apr 2023 04:38:20 +0000 (-0400)
Subject: Material Reclaimer (#14969)
X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=57f2a768a07ac12dd30458557070852965d64d4d;p=space-station-14.git
Material Reclaimer (#14969)
* Material Reclaimer
* Fix this test
* autostack output, tweak volume, add upgrade examine
* whitelist AND blacklist support
why not
* trying so hard to get this fucking test to work
* EmoGarbage delves into MaterialArbitrageTest, never to return
* VV and restore cloth to glory
* make the system more robust
* even more stuff has composition; add blacklist for important items
* fix test fails
* convert recycling
* forgor :sadge:
* lol
* simply a modiCUM of doc commentary
---
diff --git a/Content.Client/Materials/MaterialReclaimerSystem.cs b/Content.Client/Materials/MaterialReclaimerSystem.cs
new file mode 100644
index 0000000000..eec55eac3c
--- /dev/null
+++ b/Content.Client/Materials/MaterialReclaimerSystem.cs
@@ -0,0 +1,9 @@
+using Content.Shared.Materials;
+
+namespace Content.Client.Materials;
+
+///
+public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
+{
+
+}
diff --git a/Content.Client/Recycling/RecyclerVisualizer.cs b/Content.Client/Recycling/RecyclerVisualizer.cs
deleted file mode 100644
index 856ebffc5e..0000000000
--- a/Content.Client/Recycling/RecyclerVisualizer.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using Content.Shared.Conveyor;
-using Content.Shared.Recycling;
-using JetBrains.Annotations;
-using Robust.Client.GameObjects;
-using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
-using Robust.Shared.Serialization.Manager.Attributes;
-
-namespace Content.Client.Recycling
-{
- [UsedImplicitly]
- public sealed class RecyclerVisualizer : AppearanceVisualizer
- {
- [DataField("state_on")]
- private string _stateOn = "grinder-o1";
-
- [DataField("state_off")]
- private string _stateOff = "grinder-o0";
-
- [Obsolete("Subscribe to your component being initialised instead.")]
- public override void InitializeEntity(EntityUid entity)
- {
- base.InitializeEntity(entity);
-
- var entMan = IoCManager.Resolve();
- if (!entMan.TryGetComponent(entity, out SpriteComponent? sprite) ||
- !entMan.TryGetComponent(entity, out AppearanceComponent? appearance))
- {
- return;
- }
-
- UpdateAppearance(appearance, sprite);
- }
-
- [Obsolete("Subscribe to AppearanceChangeEvent instead.")]
- public override void OnChangeData(AppearanceComponent component)
- {
- base.OnChangeData(component);
-
- var entities = IoCManager.Resolve();
- if (!entities.TryGetComponent(component.Owner, out SpriteComponent? sprite))
- {
- return;
- }
-
- UpdateAppearance(component, sprite);
- }
-
- private void UpdateAppearance(AppearanceComponent component, SpriteComponent sprite)
- {
- var state = _stateOff;
- if (component.TryGetData(ConveyorVisuals.State, out ConveyorState conveyorState) && conveyorState != ConveyorState.Off)
- {
- state = _stateOn;
- }
-
- if (component.TryGetData(RecyclerVisuals.Bloody, out bool bloody) && bloody)
- {
- state += "bld";
- }
-
- sprite.LayerSetState(RecyclerVisualLayers.Main, state);
- }
- }
-
- public enum RecyclerVisualLayers : byte
- {
- Main
- }
-}
diff --git a/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs b/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs
index de8b78a55f..406b5aad81 100644
--- a/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs
+++ b/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs
@@ -14,10 +14,12 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using System;
-using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
+using Content.Shared.Chemistry.Reagent;
using Content.Shared.Construction.Components;
+using Content.Shared.FixedPoint;
+using Content.Shared.Materials;
namespace Content.IntegrationTests.Tests;
@@ -31,10 +33,7 @@ public sealed class MaterialArbitrageTest
[Test]
public async Task NoMaterialArbitrage()
{
- // TODO check lathe resource prices?
- // I CBF doing that atm because I know that will probably fail for most lathe recipies.
-
- await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings() {NoClient = true});
+ await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings {NoClient = true});
var server = pairTracker.Pair.Server;
var testMap = await PoolManager.CreateTestMap(pairTracker);
@@ -51,8 +50,9 @@ public sealed class MaterialArbitrageTest
var compFact = server.ResolveDependency();
var constructionName = compFact.GetComponentName(typeof(ConstructionComponent));
+ var compositionName = compFact.GetComponentName(typeof(PhysicalCompositionComponent));
+ var materialName = compFact.GetComponentName(typeof(MaterialComponent));
var destructibleName = compFact.GetComponentName(typeof(DestructibleComponent));
- var stackName = compFact.GetComponentName(typeof(StackComponent));
// construct inverted lathe recipe dictionary
Dictionary latheRecipes = new();
@@ -84,6 +84,9 @@ public sealed class MaterialArbitrageTest
{
var materials = new Dictionary();
var graph = protoManager.Index(comp.Graph);
+ if (graph.Start == null)
+ continue;
+
if (!graph.TryPath(graph.Start, comp.Node, out var path) || path.Length == 0)
continue;
@@ -93,10 +96,25 @@ public sealed class MaterialArbitrageTest
var edge = cur.GetEdge(node.Name);
cur = node;
+ if (edge == null)
+ continue;
+
foreach (var step in edge.Steps)
{
- if (step is MaterialConstructionGraphStep materialStep)
- materials[materialStep.MaterialPrototypeId] = materialStep.Amount + materials.GetValueOrDefault(materialStep.MaterialPrototypeId);
+ if (step is not MaterialConstructionGraphStep materialStep)
+ continue;
+
+ var stackProto = protoManager.Index(materialStep.MaterialPrototypeId);
+ var spawnProto = protoManager.Index(stackProto.Spawn);
+
+ if (!spawnProto.Components.TryGetValue(materialName, out var matreg))
+ continue;
+
+ var mat = (MaterialComponent) matreg.Component;
+ foreach (var (matId, amount) in mat.Materials)
+ {
+ materials[matId] = materialStep.Amount * amount + materials.GetValueOrDefault(matId);
+ }
}
}
constructionMaterials.Add(id, materials);
@@ -136,11 +154,16 @@ public sealed class MaterialArbitrageTest
spawnedEnts[key] = spawnedEnts.GetValueOrDefault(key) + value.Max;
var spawnProto = protoManager.Index(key);
- if (!spawnProto.Components.TryGetValue(stackName, out var reg))
+
+ // get the amount of each material included in the entity
+ if (!spawnProto.Components.TryGetValue(materialName, out var matreg))
continue;
+ var mat = (MaterialComponent) matreg.Component;
- var stack = (StackComponent) reg.Component;
- spawnedMats[stack.StackTypeId] = value.Max + spawnedMats.GetValueOrDefault(stack.StackTypeId);
+ foreach (var (matId, amount) in mat.Materials)
+ {
+ spawnedMats[matId] = value.Max * amount + spawnedMats.GetValueOrDefault(matId);
+ }
}
}
}
@@ -211,18 +234,21 @@ public sealed class MaterialArbitrageTest
continue;
var spawnProto = protoManager.Index(spawnCompletion.Prototype);
- if (!spawnProto.Components.TryGetValue(stackName, out var reg))
- continue;
- var stack = (StackComponent) reg.Component;
+ if (!spawnProto.Components.TryGetValue(materialName, out var matreg))
+ continue;
- materials[stack.StackTypeId] = spawnCompletion.Amount + materials.GetValueOrDefault(stack.StackTypeId);
+ var mat = (MaterialComponent) matreg.Component;
+ foreach (var (matId, amount) in mat.Materials)
+ {
+ materials[matId] = spawnCompletion.Amount * amount + materials.GetValueOrDefault(matId);
+ }
}
}
deconstructionMaterials.Add(id, materials);
}
- // This is functionally the same loop as before, but now testinng deconstruction rather than destruction.
+ // This is functionally the same loop as before, but now testing deconstruction rather than destruction.
// This is pretty braindead. In principle construction graphs can have loops and whatnot.
Assert.Multiple(async () =>
@@ -258,6 +284,58 @@ public sealed class MaterialArbitrageTest
}
});
+ // create phyiscal composition dictionary
+ // this doesn't account for the chemicals in the composition
+ Dictionary physicalCompositions = new();
+ foreach (var proto in protoManager.EnumeratePrototypes())
+ {
+ if (proto.NoSpawn || proto.Abstract)
+ continue;
+
+ if (!proto.Components.TryGetValue(compositionName, out var composition))
+ continue;
+
+ var comp = (PhysicalCompositionComponent) composition.Component;
+ physicalCompositions.Add(proto.ID, comp);
+ }
+
+ // This is functionally the same loop as before, but now testing composition rather than destruction or deconstruction.
+ // This doesn't take into account chemicals generated when deconstructing. Maybe it should.
+ Assert.Multiple(async () =>
+ {
+ foreach (var (id, compositionComponent) in physicalCompositions)
+ {
+ // Check cargo sell price
+ var materialPrice = await GetDeconstructedPrice(compositionComponent.MaterialComposition);
+ var chemicalPrice = await GetChemicalCompositionPrice(compositionComponent.ChemicalComposition);
+ var sumPrice = materialPrice + chemicalPrice;
+ var price = await GetPrice(id);
+ if (sumPrice > 0 && price > 0)
+ Assert.LessOrEqual(sumPrice, price, $"{id} increases in price after decomposed into raw materials");
+
+ // Check lathe production
+ if (latheRecipes.TryGetValue(id, out var recipe))
+ {
+ foreach (var (matId, amount) in recipe.RequiredMaterials)
+ {
+ var actualAmount = SharedLatheSystem.AdjustMaterial(amount, recipe.ApplyMaterialDiscount, multiplier);
+ if (compositionComponent.MaterialComposition.TryGetValue(matId, out var numSpawned))
+ Assert.LessOrEqual(numSpawned, actualAmount, $"The physical composition of {id} has more {matId} than required to produce via an (upgraded) lathe.");
+ }
+ }
+
+ // Check construction.
+ if (constructionMaterials.TryGetValue(id, out var constructionMats))
+ {
+ foreach (var (matId, amount) in constructionMats)
+ {
+ if (compositionComponent.MaterialComposition.TryGetValue(matId, out var numSpawned))
+ Assert.LessOrEqual(numSpawned, amount, $"The physical composition of {id} has more {matId} than required to construct it.");
+ }
+ }
+ }
+ });
+
await server.WaitPost(() => mapManager.DeleteMap(testMap.MapId));
await pairTracker.CleanReturnAsync();
@@ -293,8 +371,20 @@ public sealed class MaterialArbitrageTest
double price = 0;
foreach (var (id, num) in mats)
{
- var matProto = protoManager.Index(id).Spawn;
- price += num * await GetPrice(matProto);
+ var matProto = protoManager.Index(id);
+ price += num * matProto.Price;
+ }
+ return price;
+ }
+
+
+ async Task GetChemicalCompositionPrice(Dictionary mats)
+ {
+ double price = 0;
+ foreach (var (id, num) in mats)
+ {
+ var reagentProto = protoManager.Index(id);
+ price += num.Double() * reagentProto.PricePerUnit;
}
return price;
}
diff --git a/Content.Server/Cargo/Systems/PricingSystem.cs b/Content.Server/Cargo/Systems/PricingSystem.cs
index 6a1125ef36..3d4bd64a4c 100644
--- a/Content.Server/Cargo/Systems/PricingSystem.cs
+++ b/Content.Server/Cargo/Systems/PricingSystem.cs
@@ -213,7 +213,7 @@ public sealed class PricingSystem : EntitySystem
{
double price = 0;
- if (TryComp(uid, out var material) && !HasComp(uid))
+ if (TryComp(uid, out var material))
{
var matPrice = GetMaterialPrice(material);
if (TryComp(uid, out var stack))
@@ -229,8 +229,7 @@ public sealed class PricingSystem : EntitySystem
{
double price = 0;
- if (prototype.Components.TryGetValue(_factory.GetComponentName(typeof(MaterialComponent)), out var materials) &&
- !prototype.Components.ContainsKey(_factory.GetComponentName(typeof(StackPriceComponent))))
+ if (prototype.Components.TryGetValue(_factory.GetComponentName(typeof(MaterialComponent)), out var materials))
{
var materialsComp = (MaterialComponent) materials.Component;
var matPrice = GetMaterialPrice(materialsComp);
@@ -276,7 +275,8 @@ public sealed class PricingSystem : EntitySystem
var price = 0.0;
if (TryComp(uid, out var stackPrice) &&
- TryComp(uid, out var stack))
+ TryComp(uid, out var stack) &&
+ !HasComp(uid)) // don't double count material prices
{
price += stack.Count * stackPrice.Price;
}
@@ -289,7 +289,8 @@ public sealed class PricingSystem : EntitySystem
var price = 0.0;
if (prototype.Components.TryGetValue(_factory.GetComponentName(typeof(StackPriceComponent)), out var stackpriceProto) &&
- prototype.Components.TryGetValue(_factory.GetComponentName(typeof(StackComponent)), out var stackProto))
+ prototype.Components.TryGetValue(_factory.GetComponentName(typeof(StackComponent)), out var stackProto) &&
+ !prototype.Components.ContainsKey(_factory.GetComponentName(typeof(MaterialComponent))))
{
var stackPrice = (StackPriceComponent) stackpriceProto.Component;
var stack = (StackComponent) stackProto.Component;
diff --git a/Content.Server/Materials/MaterialReclaimerSystem.cs b/Content.Server/Materials/MaterialReclaimerSystem.cs
new file mode 100644
index 0000000000..80c4a40bb6
--- /dev/null
+++ b/Content.Server/Materials/MaterialReclaimerSystem.cs
@@ -0,0 +1,261 @@
+using System.Linq;
+using Content.Server.Chemistry.Components.SolutionManager;
+using Content.Server.Chemistry.EntitySystems;
+using Content.Server.Construction;
+using Content.Server.Fluids.EntitySystems;
+using Content.Server.GameTicking;
+using Content.Server.Nutrition.Components;
+using Content.Server.Players;
+using Content.Server.Popups;
+using Content.Server.Power.Components;
+using Content.Server.Stack;
+using Content.Server.Wires;
+using Content.Shared.Body.Systems;
+using Content.Shared.Chemistry.Components;
+using Content.Shared.FixedPoint;
+using Content.Shared.IdentityManagement;
+using Content.Shared.Interaction;
+using Content.Shared.Interaction.Events;
+using Content.Shared.Materials;
+using Robust.Server.GameObjects;
+using Robust.Shared.Player;
+using Robust.Shared.Utility;
+
+namespace Content.Server.Materials;
+
+///
+public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
+{
+ [Dependency] private readonly AppearanceSystem _appearance = default!;
+ [Dependency] private readonly GameTicker _ticker = default!;
+ [Dependency] private readonly MaterialStorageSystem _materialStorage = default!;
+ [Dependency] private readonly PopupSystem _popup = default!;
+ [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
+ [Dependency] private readonly SharedBodySystem _body = default!; //bobby
+ [Dependency] private readonly SpillableSystem _spillable = default!;
+ [Dependency] private readonly StackSystem _stack = default!;
+
+ ///
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnStartup);
+ SubscribeLocalEvent(OnRefreshParts);
+ SubscribeLocalEvent(OnUpgradeExamine);
+ SubscribeLocalEvent(OnPowerChanged);
+ SubscribeLocalEvent(OnInteractUsing,
+ before: new []{typeof(WiresSystem), typeof(SolutionTransferSystem)});
+ SubscribeLocalEvent(OnSuicide);
+ SubscribeLocalEvent(OnActivePowerChanged);
+ }
+ private void OnStartup(EntityUid uid, MaterialReclaimerComponent component, ComponentStartup args)
+ {
+ component.OutputSolution = _solutionContainer.EnsureSolution(uid, component.SolutionContainerId);
+ }
+
+ private void OnUpgradeExamine(EntityUid uid, MaterialReclaimerComponent component, UpgradeExamineEvent args)
+ {
+ args.AddPercentageUpgrade(Loc.GetString("material-reclaimer-upgrade-process-rate"), component.MaterialProcessRate / component.BaseMaterialProcessRate);
+ }
+
+ private void OnRefreshParts(EntityUid uid, MaterialReclaimerComponent component, RefreshPartsEvent args)
+ {
+ var rating = args.PartRatings[component.MachinePartProcessRate] - 1;
+ component.MaterialProcessRate = component.BaseMaterialProcessRate * MathF.Pow(component.PartRatingProcessRateMultiplier, rating);
+ Dirty(component);
+ }
+
+ private void OnPowerChanged(EntityUid uid, MaterialReclaimerComponent component, ref PowerChangedEvent args)
+ {
+ AmbientSound.SetAmbience(uid, args.Powered);
+ component.Powered = args.Powered;
+ Dirty(component);
+ }
+
+ private void OnInteractUsing(EntityUid uid, MaterialReclaimerComponent component, InteractUsingEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ // if we're trying to get a solution out of the reclaimer, don't destroy it
+ if (component.OutputSolution.Contents.Any())
+ {
+ if (TryComp(args.Used, out var managerComponent) &&
+ managerComponent.Solutions.Any(s => s.Value.AvailableVolume > 0))
+ {
+ if (TryComp(args.Used, out var drink) &&
+ !drink.Opened)
+ return;
+
+ if (TryComp(args.Used, out var transfer) &&
+ transfer.CanReceive)
+ return;
+ }
+ }
+
+ args.Handled = TryStartProcessItem(uid, args.Used, component, args.User);
+ }
+
+ private void OnSuicide(EntityUid uid, MaterialReclaimerComponent component, SuicideEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ args.SetHandled(SuicideKind.Bloodloss);
+ var victim = args.Victim;
+ if (TryComp(victim, out ActorComponent? actor) &&
+ actor.PlayerSession.ContentData()?.Mind is { } mind)
+ {
+ _ticker.OnGhostAttempt(mind, false);
+ if (mind.OwnedEntity is { Valid: true } entity)
+ {
+ _popup.PopupEntity(Loc.GetString("recycler-component-suicide-message"), entity);
+ }
+ }
+
+ _popup.PopupEntity(Loc.GetString("recycler-component-suicide-message-others", ("victim", Identity.Entity(victim, EntityManager))),
+ victim,
+ Filter.PvsExcept(victim, entityManager: EntityManager), true);
+
+ _body.GibBody(victim, true);
+ _appearance.SetData(uid, RecyclerVisuals.Bloody, true);
+ }
+
+ private void OnActivePowerChanged(EntityUid uid, ActiveMaterialReclaimerComponent component, ref PowerChangedEvent args)
+ {
+ if (!args.Powered)
+ TryFinishProcessItem(uid, null, component);
+ }
+
+ ///
+ public override bool TryFinishProcessItem(EntityUid uid, MaterialReclaimerComponent? component = null, ActiveMaterialReclaimerComponent? active = null)
+ {
+ if (!Resolve(uid, ref component, ref active, false))
+ return false;
+
+ if (!base.TryFinishProcessItem(uid, component, active))
+ return false;
+
+ if (active.ReclaimingContainer.ContainedEntities.FirstOrNull() is not { } item)
+ return false;
+
+ active.ReclaimingContainer.Remove(item);
+ Dirty(component);
+
+ // scales the output if the process was interrupted.
+ var completion = 1f - Math.Clamp((float) Math.Round((active.EndTime - Timing.CurTime) / active.Duration),
+ 0f, 1f);
+ Reclaim(uid, item, completion, component);
+
+ return true;
+ }
+
+ ///
+ public override void Reclaim(EntityUid uid,
+ EntityUid item,
+ float completion = 1f,
+ MaterialReclaimerComponent? component = null)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ var xform = Transform(uid);
+
+ SpawnMaterialsFromComposition(uid, item, completion * component.Efficiency, xform: xform);
+ SpawnChemicalsFromComposition(uid, item, completion, component, xform);
+
+ if (CanGib(uid, item, component))
+ {
+ _body.GibBody(item, true);
+ _appearance.SetData(uid, RecyclerVisuals.Bloody, true);
+ }
+
+ QueueDel(item);
+ }
+
+ private void SpawnMaterialsFromComposition(EntityUid reclaimer,
+ EntityUid item,
+ float efficiency,
+ MaterialStorageComponent? storage = null,
+ TransformComponent? xform = null,
+ PhysicalCompositionComponent? composition = null)
+ {
+ if (!Resolve(reclaimer, ref storage, ref xform, false))
+ return;
+
+ if (!Resolve(item, ref composition, false))
+ return;
+
+ foreach (var (material, amount) in composition.MaterialComposition)
+ {
+ var outputAmount = (int) (amount * efficiency);
+ _materialStorage.TryChangeMaterialAmount(reclaimer, material, outputAmount, storage);
+ }
+
+ foreach (var (storedMaterial, storedAmount) in storage.Storage)
+ {
+ var stacks = _materialStorage.SpawnMultipleFromMaterial(storedAmount, storedMaterial,
+ xform.Coordinates,
+ out var materialOverflow);
+ var amountConsumed = storedAmount - materialOverflow;
+ _materialStorage.TryChangeMaterialAmount(reclaimer, storedMaterial, -amountConsumed, storage);
+ foreach (var stack in stacks)
+ {
+ _stack.TryMergeToContacts(stack);
+ }
+ }
+ }
+
+ private void SpawnChemicalsFromComposition(EntityUid reclaimer,
+ EntityUid item,
+ float efficiency,
+ MaterialReclaimerComponent? reclaimerComponent = null,
+ TransformComponent? xform = null,
+ PhysicalCompositionComponent? composition = null)
+ {
+ if (!Resolve(reclaimer, ref reclaimerComponent, ref xform))
+ return;
+
+ var overflow = new Solution();
+ var totalChemicals = new Dictionary();
+
+ if (Resolve(item, ref composition, false))
+ {
+ foreach (var (key, value) in composition.ChemicalComposition)
+ {
+ totalChemicals[key] = totalChemicals.GetValueOrDefault(key) + value;
+ }
+ }
+
+ // if the item we inserted has reagents, add it in.
+ if (TryComp(item, out var solutionContainer))
+ {
+ foreach (var solution in solutionContainer.Solutions.Values)
+ {
+ foreach (var quantity in solution.Contents)
+ {
+ totalChemicals[quantity.ReagentId] =
+ totalChemicals.GetValueOrDefault(quantity.ReagentId) + quantity.Quantity;
+ }
+ }
+ }
+
+ foreach (var (reagent, amount) in totalChemicals)
+ {
+ var outputAmount = amount * efficiency * reclaimerComponent.Efficiency;
+ _solutionContainer.TryAddReagent(reclaimer, reclaimerComponent.OutputSolution, reagent, outputAmount,
+ out var accepted);
+ var overflowAmount = outputAmount - accepted;
+ if (overflowAmount > 0)
+ {
+ overflow.AddReagent(reagent, overflowAmount);
+ }
+ }
+
+ if (overflow.Volume > 0)
+ {
+ _spillable.SpillAt(reclaimer, overflow, reclaimerComponent.PuddleId, transformComponent: xform);
+ }
+ }
+}
diff --git a/Content.Server/Materials/MaterialStorageSystem.cs b/Content.Server/Materials/MaterialStorageSystem.cs
index 4e4aaeec58..e79a47d067 100644
--- a/Content.Server/Materials/MaterialStorageSystem.cs
+++ b/Content.Server/Materials/MaterialStorageSystem.cs
@@ -48,9 +48,9 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
return false;
if (!base.TryInsertMaterialEntity(user, toInsert, receiver, component))
return false;
- _audio.PlayPvs(component.InsertingSound, component.Owner);
- _popup.PopupEntity(Loc.GetString("machine-insert-item", ("user", user), ("machine", component.Owner),
- ("item", toInsert)), component.Owner);
+ _audio.PlayPvs(component.InsertingSound, receiver);
+ _popup.PopupEntity(Loc.GetString("machine-insert-item", ("user", user), ("machine", receiver),
+ ("item", toInsert)), receiver);
QueueDel(toInsert);
// Logging
@@ -67,16 +67,27 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
/// 1 biomass = 1 biomass in its stack,
/// but 100 plasma = 1 sheet of plasma, etc.
///
- [PublicAPI]
public List SpawnMultipleFromMaterial(int amount, string material, EntityCoordinates coordinates)
{
+ return SpawnMultipleFromMaterial(amount, material, coordinates, out _);
+ }
+
+ ///
+ /// Spawn an amount of a material in stack entities.
+ /// Note the 'amount' is material dependent.
+ /// 1 biomass = 1 biomass in its stack,
+ /// but 100 plasma = 1 sheet of plasma, etc.
+ ///
+ public List SpawnMultipleFromMaterial(int amount, string material, EntityCoordinates coordinates, out int overflowMaterial)
+ {
+ overflowMaterial = 0;
if (!_prototypeManager.TryIndex(material, out var stackType))
{
Logger.Error("Failed to index material prototype " + material);
return new List();
}
- return SpawnMultipleFromMaterial(amount, stackType, coordinates);
+ return SpawnMultipleFromMaterial(amount, stackType, coordinates, out overflowMaterial);
}
///
@@ -85,8 +96,22 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
/// 1 biomass = 1 biomass in its stack,
/// but 100 plasma = 1 sheet of plasma, etc.
///
+ [PublicAPI]
public List SpawnMultipleFromMaterial(int amount, MaterialPrototype materialProto, EntityCoordinates coordinates)
{
+ return SpawnMultipleFromMaterial(amount, materialProto, coordinates, out _);
+ }
+
+ ///
+ /// Spawn an amount of a material in stack entities.
+ /// Note the 'amount' is material dependent.
+ /// 1 biomass = 1 biomass in its stack,
+ /// but 100 plasma = 1 sheet of plasma, etc.
+ ///
+ public List SpawnMultipleFromMaterial(int amount, MaterialPrototype materialProto, EntityCoordinates coordinates, out int overflowMaterial)
+ {
+ overflowMaterial = 0;
+
if (amount <= 0)
return new List();
@@ -96,6 +121,7 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
var materialPerStack = material.Materials[materialProto.ID];
var amountToSpawn = amount / materialPerStack;
+ overflowMaterial = amount - amountToSpawn * materialPerStack;
return _stackSystem.SpawnMultiple(materialProto.StackEntity, amountToSpawn, coordinates);
}
}
diff --git a/Content.Server/Physics/Controllers/ConveyorController.cs b/Content.Server/Physics/Controllers/ConveyorController.cs
index 1d18eb70f4..31779ed1a7 100644
--- a/Content.Server/Physics/Controllers/ConveyorController.cs
+++ b/Content.Server/Physics/Controllers/ConveyorController.cs
@@ -1,8 +1,7 @@
using Content.Server.MachineLinking.Events;
using Content.Server.MachineLinking.System;
+using Content.Server.Materials;
using Content.Server.Power.Components;
-using Content.Server.Recycling;
-using Content.Server.Recycling.Components;
using Content.Shared.Conveyor;
using Content.Shared.Maps;
using Content.Shared.Physics;
@@ -18,7 +17,7 @@ namespace Content.Server.Physics.Controllers;
public sealed class ConveyorController : SharedConveyorController
{
[Dependency] private readonly FixtureSystem _fixtures = default!;
- [Dependency] private readonly RecyclerSystem _recycler = default!;
+ [Dependency] private readonly MaterialReclaimerSystem _materialReclaimer = default!;
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
@@ -105,13 +104,7 @@ public sealed class ConveyorController : SharedConveyorController
if (TryComp(uid, out var physics))
_broadphase.RegenerateContacts(physics);
- if (TryComp(uid, out var recycler))
- {
- if (component.State != ConveyorState.Off)
- _recycler.EnableRecycler(recycler);
- else
- _recycler.DisableRecycler(recycler);
- }
+ _materialReclaimer.SetReclaimerEnabled(uid, component.State != ConveyorState.Off);
UpdateAppearance(uid, component);
Dirty(component);
diff --git a/Content.Server/Recycling/Components/RecyclableComponent.cs b/Content.Server/Recycling/Components/RecyclableComponent.cs
deleted file mode 100644
index baa3794423..0000000000
--- a/Content.Server/Recycling/Components/RecyclableComponent.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-
-namespace Content.Server.Recycling.Components
-{
- [RegisterComponent, Access(typeof(RecyclerSystem))]
- public sealed class RecyclableComponent : Component
- {
- ///
- /// The prototype that will be spawned on recycle.
- ///
- [DataField("prototype", customTypeSerializer:typeof(PrototypeIdSerializer))] public string? Prototype;
-
- ///
- /// The amount of things that will be spawned on recycle.
- ///
- [DataField("amount")] public int Amount = 1;
-
- ///
- /// Whether this is "safe" to recycle or not.
- /// If this is false, the recycler's safety must be disabled to recycle it.
- ///
- [DataField("safe")]
- public bool Safe { get; set; } = true;
- }
-}
diff --git a/Content.Server/Recycling/Components/RecyclerComponent.cs b/Content.Server/Recycling/Components/RecyclerComponent.cs
deleted file mode 100644
index 017c9881c1..0000000000
--- a/Content.Server/Recycling/Components/RecyclerComponent.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Content.Shared.Recycling;
-using Robust.Shared.Audio;
-
-namespace Content.Server.Recycling.Components
-{
- // TODO: Add sound and safe beep
- [RegisterComponent]
- [Access(typeof(RecyclerSystem))]
- public sealed class RecyclerComponent : Component
- {
- [Dependency] private readonly IEntityManager _entMan = default!;
-
- [DataField("enabled")]
- public bool Enabled;
-
- ///
- /// The percentage of material that will be recovered
- ///
- [ViewVariables(VVAccess.ReadWrite)]
- [DataField("efficiency")]
- internal float Efficiency = 0.25f;
-
- ///
- /// Default sound to play when recycling
- ///
- [ViewVariables(VVAccess.ReadWrite)] [DataField("sound")]
- public SoundSpecifier? Sound = new SoundPathSpecifier("/Audio/Effects/saw.ogg");
-
- // Ratelimit sounds to avoid spam
- public TimeSpan LastSound;
-
- public int ItemsProcessed;
- }
-}
diff --git a/Content.Server/Recycling/RecyclerSystem.cs b/Content.Server/Recycling/RecyclerSystem.cs
deleted file mode 100644
index de7c558b4c..0000000000
--- a/Content.Server/Recycling/RecyclerSystem.cs
+++ /dev/null
@@ -1,199 +0,0 @@
-using Content.Server.Audio;
-using Content.Server.Body.Systems;
-using Content.Server.GameTicking;
-using Content.Server.Players;
-using Content.Server.Popups;
-using Content.Server.Power.Components;
-using Content.Server.Power.EntitySystems;
-using Content.Server.Recycling.Components;
-using Content.Shared.Audio;
-using Content.Shared.Body.Components;
-using Content.Shared.Emag.Components;
-using Content.Shared.Emag.Systems;
-using Content.Shared.Examine;
-using Content.Shared.IdentityManagement;
-using Content.Shared.Interaction.Events;
-using Content.Shared.Recycling;
-using Content.Shared.Tag;
-using Robust.Server.GameObjects;
-using Robust.Shared.Audio;
-using Robust.Shared.Physics.Events;
-using Robust.Shared.Player;
-using Robust.Shared.Timing;
-
-namespace Content.Server.Recycling
-{
- public sealed class RecyclerSystem : EntitySystem
- {
- [Dependency] private readonly IGameTiming _timing = default!;
- [Dependency] private readonly AmbientSoundSystem _ambience = default!;
- [Dependency] private readonly BodySystem _bodySystem = default!;
- [Dependency] private readonly GameTicker _ticker = default!;
- [Dependency] private readonly PopupSystem _popup = default!;
- [Dependency] private readonly TagSystem _tags = default!;
- [Dependency] private readonly AudioSystem _soundSystem = default!;
- [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
-
- private const string RecyclerColliderName = "brrt";
-
- private const float RecyclerSoundCooldown = 0.8f;
-
- public override void Initialize()
- {
- SubscribeLocalEvent(OnExamined);
- SubscribeLocalEvent(OnCollide);
- SubscribeLocalEvent(OnEmagged);
- SubscribeLocalEvent(OnSuicide);
- SubscribeLocalEvent(OnPowerChanged);
- }
-
- private void OnExamined(EntityUid uid, RecyclerComponent component, ExaminedEvent args)
- {
- args.PushMarkup(Loc.GetString("recycler-count-items", ("items", component.ItemsProcessed)));
- }
-
- private void OnSuicide(EntityUid uid, RecyclerComponent component, SuicideEvent args)
- {
- if (args.Handled) return;
- args.SetHandled(SuicideKind.Bloodloss);
- var victim = args.Victim;
- if (TryComp(victim, out ActorComponent? actor) &&
- actor.PlayerSession.ContentData()?.Mind is { } mind)
- {
- _ticker.OnGhostAttempt(mind, false);
- if (mind.OwnedEntity is { Valid: true } entity)
- {
- _popup.PopupEntity(Loc.GetString("recycler-component-suicide-message"), entity);
- }
- }
-
- _popup.PopupEntity(Loc.GetString("recycler-component-suicide-message-others", ("victim", Identity.Entity(victim, EntityManager))),
- victim,
- Filter.PvsExcept(victim, entityManager: EntityManager), true);
-
- if (TryComp(victim, out var body))
- {
- _bodySystem.GibBody(victim, true, body);
- }
-
- Bloodstain(component);
- }
-
- public void EnableRecycler(RecyclerComponent component)
- {
- if (component.Enabled) return;
-
- component.Enabled = true;
-
- if (TryComp(component.Owner, out ApcPowerReceiverComponent? apcPower))
- {
- _ambience.SetAmbience(component.Owner, apcPower.Powered);
- }
- else
- {
- _ambience.SetAmbience(component.Owner, true);
- }
-
- }
-
- public void DisableRecycler(RecyclerComponent component)
- {
- if (!component.Enabled) return;
-
- component.Enabled = false;
- _ambience.SetAmbience(component.Owner, false);
- }
-
- private void OnPowerChanged(EntityUid uid, RecyclerComponent component, ref PowerChangedEvent args)
- {
- if (component.Enabled)
- {
- _ambience.SetAmbience(uid, args.Powered);
- }
- }
-
- private void OnCollide(EntityUid uid, RecyclerComponent component, ref StartCollideEvent args)
- {
- if (component.Enabled && args.OurFixture.ID != RecyclerColliderName)
- return;
-
- if (TryComp(uid, out ApcPowerReceiverComponent? apcPower))
- {
- if (!apcPower.Powered)
- return;
- }
-
- Recycle(component, args.OtherFixture.Body.Owner);
- }
-
- private void Recycle(RecyclerComponent component, EntityUid entity)
- {
- RecyclableComponent? recyclable = null;
-
- // Can only recycle things that are tagged trash or recyclable... And also check the safety of the thing to recycle.
- if (!_tags.HasAnyTag(entity, "Trash", "Recyclable") &&
- (!TryComp(entity, out recyclable) || !recyclable.Safe && !HasComp(component.Owner)))
- {
- return;
- }
-
- // TODO: Prevent collision with recycled items
-
- // Mobs are a special case!
- if (CanGib(component, entity))
- {
- _bodySystem.GibBody(entity, true, Comp(entity));
- Bloodstain(component);
- return;
- }
-
- if (recyclable == null)
- QueueDel(entity);
- else
- Recycle(recyclable, component.Efficiency);
-
- if (component.Sound != null && (_timing.CurTime - component.LastSound).TotalSeconds > RecyclerSoundCooldown)
- {
- _soundSystem.PlayPvs(component.Sound, component.Owner, AudioHelpers.WithVariation(0.01f).WithVolume(-3));
- component.LastSound = _timing.CurTime;
- }
-
- component.ItemsProcessed++;
- }
-
- private bool CanGib(RecyclerComponent component, EntityUid entity)
- {
- return HasComp(entity) && HasComp(component.Owner) &&
- this.IsPowered(component.Owner, EntityManager);
- }
-
- public void Bloodstain(RecyclerComponent component)
- {
- if (EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearance))
- {
- _appearanceSystem.SetData(component.Owner, RecyclerVisuals.Bloody, true, appearance);
- }
- }
-
- private void Recycle(RecyclableComponent component, float efficiency = 1f)
- {
- if (!string.IsNullOrEmpty(component.Prototype))
- {
- var xform = Transform(component.Owner);
-
- for (var i = 0; i < Math.Max(component.Amount * efficiency, 1); i++)
- {
- Spawn(component.Prototype, xform.Coordinates);
- }
- }
-
- QueueDel(component.Owner);
- }
-
- private void OnEmagged(EntityUid uid, RecyclerComponent component, ref GotEmaggedEvent args)
- {
- // no fancy conditions
- args.Handled = true;
- }
- }
-}
diff --git a/Content.Shared/Lathe/LatheComponent.cs b/Content.Shared/Lathe/LatheComponent.cs
index 752eec5aba..4cfd94c80f 100644
--- a/Content.Shared/Lathe/LatheComponent.cs
+++ b/Content.Shared/Lathe/LatheComponent.cs
@@ -85,7 +85,7 @@ namespace Content.Shared.Lathe
[DataField("partRatingMaterialUseMultiplier")]
public float PartRatingMaterialUseMultiplier = DefaultPartRatingMaterialUseMultiplier;
- public const float DefaultPartRatingMaterialUseMultiplier = 0.75f;
+ public const float DefaultPartRatingMaterialUseMultiplier = 0.85f;
#endregion
}
diff --git a/Content.Shared/Materials/ActiveMaterialReclaimerComponent.cs b/Content.Shared/Materials/ActiveMaterialReclaimerComponent.cs
new file mode 100644
index 0000000000..b62be502e3
--- /dev/null
+++ b/Content.Shared/Materials/ActiveMaterialReclaimerComponent.cs
@@ -0,0 +1,32 @@
+using Robust.Shared.Containers;
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Shared.Materials;
+
+///
+/// Tracker component for the process of reclaiming entities
+///
+///
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedMaterialReclaimerSystem))]
+public sealed class ActiveMaterialReclaimerComponent : Component
+{
+ ///
+ /// Container used to store the item currently being reclaimed
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public Container ReclaimingContainer = default!;
+
+ ///
+ /// When the reclaiming process ends.
+ ///
+ [DataField("endTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
+ public TimeSpan EndTime;
+
+ ///
+ /// The length of the reclaiming process.
+ /// Used for calculations.
+ ///
+ [DataField("duration"), ViewVariables(VVAccess.ReadWrite)]
+ public TimeSpan Duration;
+}
diff --git a/Content.Shared/Materials/CollideMaterialReclaimerComponent.cs b/Content.Shared/Materials/CollideMaterialReclaimerComponent.cs
new file mode 100644
index 0000000000..4d9b072ad2
--- /dev/null
+++ b/Content.Shared/Materials/CollideMaterialReclaimerComponent.cs
@@ -0,0 +1,16 @@
+namespace Content.Shared.Materials;
+
+///
+/// Valid items that collide with an entity with this component
+/// will begin to be reclaimed.
+///
+///
+[RegisterComponent]
+public sealed class CollideMaterialReclaimerComponent : Component
+{
+ ///
+ /// The fixture that starts reclaiming on collision.
+ ///
+ [DataField("fixtureId")]
+ public string FixtureId = "brrt";
+}
diff --git a/Content.Shared/Materials/MaterialReclaimerComponent.cs b/Content.Shared/Materials/MaterialReclaimerComponent.cs
new file mode 100644
index 0000000000..aaaa656f65
--- /dev/null
+++ b/Content.Shared/Materials/MaterialReclaimerComponent.cs
@@ -0,0 +1,177 @@
+using Content.Shared.Chemistry.Components;
+using Content.Shared.Construction.Prototypes;
+using Content.Shared.Whitelist;
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+
+namespace Content.Shared.Materials;
+
+///
+/// This is a machine that handles converting entities
+/// into the raw materials and chemicals that make them up.
+///
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedMaterialReclaimerSystem))]
+public sealed class MaterialReclaimerComponent : Component
+{
+ ///
+ /// Whether or not the machine has power. We put it here
+ /// so we can network and predict it.
+ ///
+ [DataField("powered"), ViewVariables(VVAccess.ReadWrite)]
+ public bool Powered;
+
+ ///
+ /// An "enable" toggle for things like interfacing with machine linking
+ ///
+ [DataField("enabled"), ViewVariables(VVAccess.ReadWrite)]
+ public bool Enabled = true;
+
+ ///
+ /// How efficiently the materials are reclaimed.
+ /// In practice, a multiplier per material when calculating the output of the reclaimer.
+ ///
+ [DataField("efficiency"), ViewVariables(VVAccess.ReadWrite)]
+ public float Efficiency = 1f;
+
+ ///
+ /// Whether or not the process
+ /// speed scales with the amount of materials being processed
+ /// or if it's just
+ ///
+ [DataField("scaleProcessSpeed")]
+ public bool ScaleProcessSpeed = true;
+
+ ///
+ /// How quickly it takes to consume X amount of materials per second.
+ /// For example, with a rate of 50, an entity with 100 total material takes 2 seconds to process.
+ ///
+ [DataField("baseMaterialProcessRate"), ViewVariables(VVAccess.ReadWrite)]
+ public float BaseMaterialProcessRate = 100f;
+
+ ///
+ /// How quickly it takes to consume X amount of materials per second.
+ /// For example, with a rate of 50, an entity with 100 total material takes 2 seconds to process.
+ ///
+ [DataField("materialProcessRate"), ViewVariables(VVAccess.ReadWrite)]
+ public float MaterialProcessRate = 100f;
+
+ ///
+ /// Machine part whose rating modifies
+ ///
+ [DataField("machinePartProcessRate", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)]
+ public string MachinePartProcessRate = "Manipulator";
+
+ ///
+ /// How much the machine part quality affects the
+ ///
+ [DataField("partRatingProcessRateMultiplier"), ViewVariables(VVAccess.ReadWrite)]
+ public float PartRatingProcessRateMultiplier = 1.5f;
+
+ ///
+ /// The minimum amount fo time it can take to process an entity.
+ /// this value supercedes the calculated one using
+ ///
+ [DataField("minimumProcessDuration"), ViewVariables(VVAccess.ReadWrite)]
+ public TimeSpan MinimumProcessDuration = TimeSpan.FromSeconds(0.5f);
+
+ ///
+ /// The id of our output solution
+ ///
+ [DataField("solutionContainerId"), ViewVariables(VVAccess.ReadWrite)]
+ public string SolutionContainerId = "output";
+
+ ///
+ /// The prototype for the puddle
+ ///
+ [DataField("puddleId", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)]
+ public string PuddleId = "PuddleSmear";
+
+ ///
+ /// The solution itself.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ public Solution OutputSolution = default!;
+
+ ///
+ /// a whitelist for what entities can be inserted into this reclaimer
+ ///
+ [DataField("whitelist")]
+ public EntityWhitelist? Whitelist;
+
+ ///
+ /// a blacklist for what entities cannot be inserted into this reclaimer
+ ///
+ [DataField("blacklist")]
+ public EntityWhitelist? Blacklist;
+
+ ///
+ /// The sound played when something is being processed.
+ ///
+ [DataField("sound")]
+ public SoundSpecifier? Sound;
+
+ ///
+ /// whether or not we cut off the sound early when the reclaiming ends.
+ ///
+ [DataField("cutOffSound")]
+ public bool CutOffSound = true;
+
+ ///
+ /// When the next sound will be allowed to be played. Used to prevent spam.
+ ///
+ [DataField("nextSound", customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan NextSound;
+
+ ///
+ /// Minimum time inbetween each
+ ///
+ [DataField("soundCooldown")]
+ public TimeSpan SoundCooldown = TimeSpan.FromSeconds(0.8f);
+
+ public IPlayingAudioStream? Stream;
+
+ ///
+ /// A counter of how many items have been processed
+ ///
+ ///
+ /// I saw this on the recycler and i'm porting it because it's cute af
+ ///
+ [DataField("itemsProcessed")]
+ public int ItemsProcessed;
+}
+
+[Serializable, NetSerializable]
+public sealed class MaterialReclaimerComponentState : ComponentState
+{
+ public bool Powered;
+
+ public bool Enabled;
+
+ public float MaterialProcessRate;
+
+ public int ItemsProcessed;
+
+ public MaterialReclaimerComponentState(bool powered, bool enabled, float materialProcessRate, int itemsProcessed)
+ {
+ Powered = powered;
+ Enabled = enabled;
+ MaterialProcessRate = materialProcessRate;
+ ItemsProcessed = itemsProcessed;
+ }
+}
+
+[NetSerializable, Serializable]
+public enum RecyclerVisuals
+{
+ Bloody
+}
+
+public enum RecyclerVisualLayers : byte
+{
+ Main,
+ Bloody
+}
diff --git a/Content.Shared/Materials/MaterialStorageComponent.cs b/Content.Shared/Materials/MaterialStorageComponent.cs
index 491c4d3cb7..71b4056042 100644
--- a/Content.Shared/Materials/MaterialStorageComponent.cs
+++ b/Content.Shared/Materials/MaterialStorageComponent.cs
@@ -15,6 +15,12 @@ public sealed class MaterialStorageComponent : Component
[DataField("storage", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))]
public Dictionary Storage { get; set; } = new();
+ ///
+ /// Whether or not interacting with the materialstorage inserts the material in hand.
+ ///
+ [DataField("insertOnInteract")]
+ public bool InsertOnInteract = true;
+
///
/// How much material the storage can store in total.
///
diff --git a/Content.Shared/Materials/PhysicalCompositionComponent.cs b/Content.Shared/Materials/PhysicalCompositionComponent.cs
new file mode 100644
index 0000000000..2d23a8ccf6
--- /dev/null
+++ b/Content.Shared/Materials/PhysicalCompositionComponent.cs
@@ -0,0 +1,30 @@
+using Content.Shared.Chemistry.Reagent;
+using Content.Shared.FixedPoint;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
+
+namespace Content.Shared.Materials;
+
+///
+/// This is used for assigning an innate material/chemical composition to an entity.
+/// These aren't materials per se, but rather the materials which "make up" an entity.
+/// This also isn't something that should exist simultaneously with .
+///
+///
+/// The reason for duel material/chemical is for the eventual
+/// combination of the two systems.
+///
+[RegisterComponent]
+public sealed class PhysicalCompositionComponent : Component
+{
+ ///
+ /// The materials that "make up" this entity
+ ///
+ [DataField("materialComposition", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))]
+ public Dictionary MaterialComposition = new();
+
+ ///
+ /// The chemicals that "make up" this entity
+ ///
+ [DataField("chemicalComposition", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))]
+ public Dictionary ChemicalComposition = new();
+}
diff --git a/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs b/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs
new file mode 100644
index 0000000000..18a744e80d
--- /dev/null
+++ b/Content.Shared/Materials/SharedMaterialReclaimerSystem.cs
@@ -0,0 +1,249 @@
+using System.Linq;
+using Content.Shared.Administration.Logs;
+using Content.Shared.Audio;
+using Content.Shared.Body.Components;
+using Content.Shared.Database;
+using Content.Shared.Emag.Components;
+using Content.Shared.Emag.Systems;
+using Content.Shared.Examine;
+using Content.Shared.Mobs.Components;
+using Content.Shared.Stacks;
+using Robust.Shared.Containers;
+using Robust.Shared.GameStates;
+using Robust.Shared.Physics.Events;
+using Robust.Shared.Timing;
+
+namespace Content.Shared.Materials;
+
+///
+/// Handles interactions and logic related to ,
+/// , and .
+///
+public abstract class SharedMaterialReclaimerSystem : EntitySystem
+{
+ [Dependency] private readonly ISharedAdminLogManager _adminLog = default!;
+ [Dependency] protected readonly IGameTiming Timing = default!;
+ [Dependency] protected readonly SharedAmbientSoundSystem AmbientSound = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly SharedContainerSystem _container = default!;
+
+ public const string ActiveReclaimerContainerId = "active-material-reclaimer-container";
+
+ ///
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnGetState);
+ SubscribeLocalEvent(OnHandleState);
+ SubscribeLocalEvent(OnUnpaused);
+ SubscribeLocalEvent(OnExamined);
+ SubscribeLocalEvent(OnEmagged);
+ SubscribeLocalEvent(OnCollide);
+ SubscribeLocalEvent(OnActiveStartup);
+ SubscribeLocalEvent(OnActiveUnpaused);
+ }
+
+ private void OnGetState(EntityUid uid, MaterialReclaimerComponent component, ref ComponentGetState args)
+ {
+ args.State = new MaterialReclaimerComponentState(component.Powered,
+ component.Enabled,
+ component.MaterialProcessRate,
+ component.ItemsProcessed);
+ }
+
+ private void OnHandleState(EntityUid uid, MaterialReclaimerComponent component, ref ComponentHandleState args)
+ {
+ if (args.Current is not MaterialReclaimerComponentState state)
+ return;
+ component.Powered = state.Powered;
+ component.Enabled = state.Enabled;
+ component.MaterialProcessRate = state.MaterialProcessRate;
+ component.ItemsProcessed = state.ItemsProcessed;
+ }
+
+ private void OnUnpaused(EntityUid uid, MaterialReclaimerComponent component, ref EntityUnpausedEvent args)
+ {
+ component.NextSound += args.PausedTime;
+ }
+
+ private void OnExamined(EntityUid uid, MaterialReclaimerComponent component, ExaminedEvent args)
+ {
+ args.PushMarkup(Loc.GetString("recycler-count-items", ("items", component.ItemsProcessed)));
+ }
+
+ private void OnEmagged(EntityUid uid, MaterialReclaimerComponent component, ref GotEmaggedEvent args)
+ {
+ args.Handled = true;
+ }
+
+ private void OnCollide(EntityUid uid, CollideMaterialReclaimerComponent component, ref StartCollideEvent args)
+ {
+ if (args.OurFixture.ID != component.FixtureId)
+ return;
+ if (!TryComp(uid, out var reclaimer))
+ return;
+ TryStartProcessItem(uid, args.OtherFixture.Body.Owner, reclaimer);
+ }
+
+ private void OnActiveStartup(EntityUid uid, ActiveMaterialReclaimerComponent component, ComponentStartup args)
+ {
+ component.ReclaimingContainer = _container.EnsureContainer(uid, ActiveReclaimerContainerId);
+ }
+
+ private void OnActiveUnpaused(EntityUid uid, ActiveMaterialReclaimerComponent component, ref EntityUnpausedEvent args)
+ {
+ component.EndTime += args.PausedTime;
+ }
+
+ ///
+ /// Tries to start processing an item via a .
+ ///
+ public bool TryStartProcessItem(EntityUid uid, EntityUid item, MaterialReclaimerComponent? component = null, EntityUid? user = null)
+ {
+ if (!Resolve(uid, ref component))
+ return false;
+
+ if (!CanStart(uid, component))
+ return false;
+
+ if (component.Whitelist != null && !component.Whitelist.IsValid(item) ||
+ HasComp(item) && !CanGib(uid, item, component)) // whitelist? We be gibbing, boy!
+ return false;
+
+ if (component.Blacklist != null && component.Blacklist.IsValid(item))
+ return false;
+
+ if (user != null)
+ {
+ _adminLog.Add(LogType.Action, LogImpact.High,
+ $"{ToPrettyString(user.Value):player} destroyed {ToPrettyString(item)} in the material reclaimer, {ToPrettyString(uid)}");
+ }
+
+ if (Timing.CurTime > component.NextSound)
+ component.Stream = _audio.PlayPvs(component.Sound, uid);
+ component.NextSound = Timing.CurTime + component.SoundCooldown;
+
+ var duration = GetReclaimingDuration(uid, item, component);
+ // if it's instant, don't bother with all the active comp stuff.
+ if (duration == TimeSpan.Zero)
+ {
+ Reclaim(uid, item, 1, component);
+ return true;
+ }
+
+ var active = EnsureComp(uid);
+ active.Duration = duration;
+ active.EndTime = Timing.CurTime + duration;
+ active.ReclaimingContainer.Insert(item);
+ return true;
+ }
+
+ ///
+ /// Finishes processing an item, freeing up the the reclaimer.
+ ///
+ ///
+ /// This doesn't reclaim the entity itself, but rather ends the formal
+ /// process started with .
+ /// The actual reclaiming happens in
+ ///
+ public virtual bool TryFinishProcessItem(EntityUid uid, MaterialReclaimerComponent? component = null, ActiveMaterialReclaimerComponent? active = null)
+ {
+ if (!Resolve(uid, ref component, ref active, false))
+ return false;
+
+ RemCompDeferred(uid, active);
+ return true;
+ }
+
+ ///
+ /// Spawns the materials and chemicals associated
+ /// with an entity. Also deletes the item.
+ ///
+ public virtual void Reclaim(EntityUid uid,
+ EntityUid item,
+ float completion = 1f,
+ MaterialReclaimerComponent? component = null)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ component.ItemsProcessed++;
+ if (component.CutOffSound)
+ component.Stream?.Stop();
+
+ Dirty(component);
+ }
+
+ ///
+ /// Sets the Enabled field on the reclaimer.
+ ///
+ public void SetReclaimerEnabled(EntityUid uid, bool enabled, MaterialReclaimerComponent? component = null)
+ {
+ if (!Resolve(uid, ref component, false))
+ return;
+ component.Enabled = enabled;
+ AmbientSound.SetAmbience(uid, enabled && component.Powered);
+ Dirty(component);
+ }
+
+ ///
+ /// Whether or not the specified reclaimer can currently
+ /// begin reclaiming another entity.
+ ///
+ public bool CanStart(EntityUid uid, MaterialReclaimerComponent component)
+ {
+ if (HasComp(uid))
+ return false;
+
+ return component.Powered && component.Enabled;
+ }
+
+ ///
+ /// Whether or not the reclaimer satisfies the conditions
+ /// allowing it to gib/reclaim a living creature.
+ ///
+ public bool CanGib(EntityUid uid, EntityUid victim, MaterialReclaimerComponent component)
+ {
+ return component.Powered &&
+ component.Enabled &&
+ HasComp(victim) &&
+ HasComp(uid);
+ }
+
+ ///
+ /// Gets the duration of processing a specified entity.
+ /// Processing is calculated from the sum of the materials within the entity.
+ /// It does not regard the chemicals within it.
+ ///
+ public TimeSpan GetReclaimingDuration(EntityUid reclaimer,
+ EntityUid item,
+ MaterialReclaimerComponent? reclaimerComponent = null,
+ PhysicalCompositionComponent? compositionComponent = null)
+ {
+ if (!Resolve(reclaimer, ref reclaimerComponent))
+ return TimeSpan.Zero;
+
+ if (!reclaimerComponent.ScaleProcessSpeed ||
+ !Resolve(item, ref compositionComponent, false))
+ return reclaimerComponent.MinimumProcessDuration;
+
+ var materialSum = compositionComponent.MaterialComposition.Values.Sum();
+ materialSum *= CompOrNull(item)?.Count ?? 1;
+ var duration = TimeSpan.FromSeconds(materialSum / reclaimerComponent.MaterialProcessRate);
+ if (duration < reclaimerComponent.MinimumProcessDuration)
+ duration = reclaimerComponent.MinimumProcessDuration;
+ return duration;
+ }
+
+ ///
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var active, out var reclaimer))
+ {
+ if (Timing.CurTime < active.EndTime)
+ continue;
+ TryFinishProcessItem(uid, reclaimer, active);
+ }
+ }
+}
diff --git a/Content.Shared/Materials/SharedMaterialStorageSystem.cs b/Content.Shared/Materials/SharedMaterialStorageSystem.cs
index 2ade6b5705..7daea6977b 100644
--- a/Content.Shared/Materials/SharedMaterialStorageSystem.cs
+++ b/Content.Shared/Materials/SharedMaterialStorageSystem.cs
@@ -252,7 +252,7 @@ public abstract class SharedMaterialStorageSystem : EntitySystem
private void OnInteractUsing(EntityUid uid, MaterialStorageComponent component, InteractUsingEvent args)
{
- if (args.Handled)
+ if (args.Handled || !component.InsertOnInteract)
return;
args.Handled = TryInsertMaterialEntity(args.User, args.Used, uid, component);
}
diff --git a/Content.Shared/Recycling/SharedRecyclerComponent.cs b/Content.Shared/Recycling/SharedRecyclerComponent.cs
deleted file mode 100644
index 33cbc5165c..0000000000
--- a/Content.Shared/Recycling/SharedRecyclerComponent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Recycling
-{
- [NetSerializable, Serializable]
- public enum RecyclerVisuals
- {
- Bloody
- }
-}
diff --git a/Resources/Audio/Ambience/Objects/attributions.yml b/Resources/Audio/Ambience/Objects/attributions.yml
index 8322c91a48..c084f551c7 100644
--- a/Resources/Audio/Ambience/Objects/attributions.yml
+++ b/Resources/Audio/Ambience/Objects/attributions.yml
@@ -1,4 +1,9 @@
- files: ["anomaly_generator.ogg"]
license: "CC0-1.0"
copyright: "Created by steaq, converted Mono and .ogg by EmoGarbage"
- source: "https://freesound.org/people/steaq/sounds/509249/"
\ No newline at end of file
+ source: "https://freesound.org/people/steaq/sounds/509249/"
+
+- files: ["crushing.ogg"]
+ license: "CC-BY-4.0"
+ copyright: "Created by juskiddink, converted Mono and .ogg by EmoGarbage"
+ source: "https://freesound.org/people/juskiddink/sounds/66956/"
\ No newline at end of file
diff --git a/Resources/Audio/Ambience/Objects/crushing.ogg b/Resources/Audio/Ambience/Objects/crushing.ogg
new file mode 100644
index 0000000000..401ae15f6f
Binary files /dev/null and b/Resources/Audio/Ambience/Objects/crushing.ogg differ
diff --git a/Resources/Locale/en-US/materials/materials.ftl b/Resources/Locale/en-US/materials/materials.ftl
index f3cb457d73..336b7f1206 100644
--- a/Resources/Locale/en-US/materials/materials.ftl
+++ b/Resources/Locale/en-US/materials/materials.ftl
@@ -18,3 +18,6 @@ materials-plasma = plasma
materials-plastic = plastic
materials-wood = wood
materials-uranium = uranium
+
+# Material Reclaimer
+material-reclaimer-upgrade-process-rate = process rate
\ No newline at end of file
diff --git a/Resources/Prototypes/Body/Parts/silicon.yml b/Resources/Prototypes/Body/Parts/silicon.yml
index 90e682282f..266c1dd5a6 100644
--- a/Resources/Prototypes/Body/Parts/silicon.yml
+++ b/Resources/Prototypes/Body/Parts/silicon.yml
@@ -16,6 +16,9 @@
- type: Tag
tags:
- Trash
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 25
- type: entity
id: LeftArmBorg
@@ -36,7 +39,6 @@
tags:
- Trash
- BorgArm
- - type: Recyclable
- type: entity
id: RightArmBorg
@@ -57,4 +59,3 @@
tags:
- Trash
- BorgArm
- - type: Recyclable
diff --git a/Resources/Prototypes/Catalog/Research/technologies.yml b/Resources/Prototypes/Catalog/Research/technologies.yml
index 5c605abffc..f10f43bd7a 100644
--- a/Resources/Prototypes/Catalog/Research/technologies.yml
+++ b/Resources/Prototypes/Catalog/Research/technologies.yml
@@ -364,6 +364,7 @@
- SheetPlastic
- SheetRGlass
- SheetGlass1
+ - MaterialReclaimerMachineCircuitboard
# Electromagnetic Theory Technology Tree
diff --git a/Resources/Prototypes/Entities/Clothing/Belt/base_clothingbelt.yml b/Resources/Prototypes/Entities/Clothing/Belt/base_clothingbelt.yml
index d23807a1fa..0c400828d8 100644
--- a/Resources/Prototypes/Entities/Clothing/Belt/base_clothingbelt.yml
+++ b/Resources/Prototypes/Entities/Clothing/Belt/base_clothingbelt.yml
@@ -10,6 +10,11 @@
- type: Clothing
slots: [belt]
quickEquip: false
+ - type: PhysicalComposition
+ materialComposition:
+ Cloth: 50
+ - type: StaticPrice
+ price: 25
- type: entity
abstract: true
diff --git a/Resources/Prototypes/Entities/Clothing/Head/misc.yml b/Resources/Prototypes/Entities/Clothing/Head/misc.yml
index 1f1a8b4146..b010f1a978 100644
--- a/Resources/Prototypes/Entities/Clothing/Head/misc.yml
+++ b/Resources/Prototypes/Entities/Clothing/Head/misc.yml
@@ -125,6 +125,9 @@
sprite: Clothing/Head/Misc/cone.rsi
- type: Clothing
sprite: Clothing/Head/Misc/cone.rsi
+ - type: PhysicalComposition #you can't just pass up some free plastic!
+ materialComposition:
+ Plastic: 100
- type: entity
parent: ClothingHeadBase
diff --git a/Resources/Prototypes/Entities/Clothing/Head/welding.yml b/Resources/Prototypes/Entities/Clothing/Head/welding.yml
index f410104784..94254e625f 100644
--- a/Resources/Prototypes/Entities/Clothing/Head/welding.yml
+++ b/Resources/Prototypes/Entities/Clothing/Head/welding.yml
@@ -8,6 +8,12 @@
- type: FlashImmunity
- type: IdentityBlocker
- type: EyeProtection
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 500
+ Glass: 100
+ - type: StaticPrice
+ price: 50
- type: entity
parent: WeldingMaskBase
diff --git a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml
index 3f5d9f8755..1298ac5322 100644
--- a/Resources/Prototypes/Entities/Clothing/Masks/masks.yml
+++ b/Resources/Prototypes/Entities/Clothing/Masks/masks.yml
@@ -137,7 +137,10 @@
- type: Tag
tags:
- PetWearable
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 50
+ Plastic: 100
- type: entity
parent: ClothingMaskBase
diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml
index c3946c6606..08fd95b278 100644
--- a/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml
+++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml
@@ -259,6 +259,10 @@
sprintModifier: 0.75
- type: Item
size: 100
+ - type: Tag
+ tags:
+ - WhitelistChameleon
+ - HighRiskItem
- type: ExplosionResistance
damageCoefficient: 0.1
- type: ToggleableClothing
diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml
index f8398f93d0..6fc0525604 100644
--- a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml
+++ b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml
@@ -58,6 +58,10 @@
sprintModifier: 1
enabled: false
- type: NoSlip
+ - type: Tag
+ tags:
+ - WhitelistChameleon
+ - HighRiskItem
- type: StaticPrice
price: 750
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
index bc42856392..5bd5deb20b 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
@@ -824,7 +824,6 @@
tags:
- Trash
- CannotSuicide
- - type: Recyclable
- type: Respirator
damage:
types:
@@ -1997,7 +1996,6 @@
tags:
- Trash
- CannotSuicide
- - type: Recyclable
- type: Respirator
damage:
types:
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
index e708eb9d9b..5dcc5ec98a 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
@@ -38,8 +38,6 @@
noRot: true
drawdepth: Mobs
netsync: false
- - type: Recyclable
- safe: false
- type: Faction
factions:
- SimpleNeutral
diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
index e5e7efcf2c..71ed356e28 100644
--- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
+++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
@@ -139,8 +139,6 @@
- type: Polymorphable
- type: Pullable
- type: Buckle
- - type: Recyclable
- safe: false
- type: StandingState
- type: Alerts
- type: NameIdentifier
diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
index 8c7181b00c..7a12adb345 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
@@ -56,8 +56,6 @@
- type: Pullable
- type: Examiner
- type: Puller
- - type: Recyclable
- safe: false
- type: StandingState
- type: Alerts
- type: Tag
diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml
index d49205a2a3..fea68b0c2a 100644
--- a/Resources/Prototypes/Entities/Mobs/Species/base.yml
+++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml
@@ -280,8 +280,6 @@
spawned:
- id: FoodMeat
amount: 5
- # - type: Recyclable Turns out turning off recycler safeties without considering the instagib is a bad idea
- # safe: false
- type: Speech
speechSounds: Alto
- type: Vocal
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml
index 6e2d74a855..1e355ec798 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml
@@ -72,6 +72,9 @@
damage:
types:
Blunt: 5
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 25
# Transformable container - normal glass
- type: entity
@@ -2164,7 +2167,6 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: entity
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
index 4a40578fd4..b03d917559 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
@@ -51,10 +51,12 @@
types:
Blunt: 0
- type: ItemCooldown
- - type: Recyclable
- type: SpaceGarbage
- type: TrashOnEmpty
solution: drink
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 50 #reduce, reuse, recycle
- type: entity
parent: DrinkCanBaseFull
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml
index 1d15533407..c91593bfc2 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml
@@ -66,6 +66,9 @@
- type: SolutionContainerVisuals
maxFillLevels: 3
fillBaseName: icon-
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 25
- type: entity
parent: DrinkBaseMug
@@ -130,6 +133,9 @@
components:
- type: Sprite
sprite: Objects/Consumable/Drinks/mug_metal.rsi
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 25
- type: entity
parent: DrinkBaseMug
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml
index d2a5a52f3c..ae2daac052 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml
@@ -7,6 +7,9 @@
- type: Drink
- type: Sprite
sprite: Objects/Consumable/Drinks/shinyflask.rsi
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 50
- type: entity
parent: DrinkBase
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_special.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_special.yml
index 2fbc947041..684681074e 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_special.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_special.yml
@@ -29,6 +29,9 @@
interfaces:
- key: enum.TransferAmountUiKey.Key
type: TransferAmountBoundUserInterface
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 50
- type: entity
parent: DrinkGlassBase
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/trash_drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/trash_drinks.yml
index 03b04d7e55..a1a1eef3f3 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/trash_drinks.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/trash_drinks.yml
@@ -68,7 +68,9 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 100
- type: SpaceGarbage
# Containers
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/bowl.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/bowl.yml
index e6392877f3..04693e0596 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/bowl.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/bowl.yml
@@ -69,7 +69,9 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 50
- type: SpaceGarbage
- type: StaticPrice
price: 0
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/plate.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/plate.yml
index 39f2bfa1a8..f5b0ff6880 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/plate.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/plate.yml
@@ -45,7 +45,9 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 100
- type: SpaceGarbage
- type: entity
@@ -61,7 +63,6 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
- type: SpaceGarbage
# Small Plate
@@ -147,5 +148,7 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
- type: SpaceGarbage
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/tin.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/tin.yml
index 84bbb670be..80129c01e0 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/tin.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/tin.yml
@@ -28,6 +28,9 @@
Blunt: 3
- type: Damageable
damageContainer: Inorganic
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
- type: entity
abstract: true
@@ -46,6 +49,9 @@
- type: Tag
tags:
- Trash
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
# Tins
# Need something that you can open these tins with. I suggest a prying or cutting tool.
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/egg.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/egg.yml
index 41eb9ca924..9ecfae3324 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/egg.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/egg.yml
@@ -110,7 +110,6 @@
tags:
- Egg
- Trash
- - type: Recyclable
- type: SpaceGarbage
# Egg
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/food_base.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/food_base.yml
index 31c120b6aa..a9f0609914 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/food_base.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/food_base.yml
@@ -10,7 +10,6 @@
flavors:
- food
- type: Food
- - type: Recyclable
- type: SpaceGarbage
- type: Sprite
netsync: false
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/frozen.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/frozen.yml
index c9e973ff14..12b93c35a8 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/frozen.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/frozen.yml
@@ -275,5 +275,4 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
- type: SpaceGarbage
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml
index 925d5f86ab..8c8c35388d 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml
@@ -225,6 +225,7 @@
- type: Tag
tags:
- Raw
+ - HighRiskItem
- type: Sprite
state: corgi
- type: SolutionContainerManager
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml
index 1c8d38aa78..d20aacdc1f 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml
@@ -213,7 +213,6 @@
Quantity: 4
- type: Extractable
grindableSolutionName: food
- - type: Recyclable
- type: SpaceGarbage
- type: entity
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/snacks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/snacks.yml
index bfa59aaf64..ee0c29fbe9 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/snacks.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/snacks.yml
@@ -387,7 +387,9 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
- type: SpaceGarbage
- type: StaticPrice
price: 0
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/cartons.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/cartons.yml
index d7cc6a01fb..52fa3dd50b 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/cartons.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/cartons.yml
@@ -24,7 +24,9 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Plastic: 50
- type: SpaceGarbage
- type: entity
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/cigarette.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/cigarette.yml
index 65e4772bff..777d396869 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/cigarette.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/cigarette.yml
@@ -12,7 +12,6 @@
tags:
- Cigarette
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: Clothing
sprite: Objects/Consumable/Smokeables/Cigarettes/cigarette.rsi
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/joints.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/joints.yml
index 0e4a78bca0..42aa84d43d 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/joints.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/joints.yml
@@ -12,7 +12,6 @@
tags:
- Cigarette
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: Clothing
sprite: Objects/Consumable/Smokeables/Cannabis/joint.rsi
@@ -45,7 +44,6 @@
tags:
- Cigarette
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: Clothing
sprite: Objects/Consumable/Smokeables/Cannabis/blunt.rsi
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/packs.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/packs.yml
index c508333057..0368c599ac 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/packs.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/packs.yml
@@ -8,7 +8,9 @@
tags:
- CigPack
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 50
- type: SpaceGarbage
- type: Storage
capacity: 6
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/rolling_paper.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/rolling_paper.yml
index e62db9e40f..c4b53f45b5 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/rolling_paper.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/Cigarettes/rolling_paper.yml
@@ -59,7 +59,6 @@
tags:
- RollingPaper
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: entity
@@ -90,7 +89,6 @@
tags:
- CigFilter
- Trash
- - type: Recyclable
- type: entity
id: CigaretteFilter1
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml
index ef58235903..c534b73094 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Smokeables/base_smokeables.yml
@@ -13,7 +13,6 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: StaticPrice
price: 5
@@ -50,14 +49,14 @@
bowl_slot: !type:ContainerSlot
- type: ItemSlots
- type: SmokingPipe
- bowl_slot:
+ bowl_slot:
name: Bowl
whitelist:
tags:
- Smokable
- insertSound:
+ insertSound:
path: /Audio/Weapons/Guns/Empty/empty.ogg
- ejectSound:
+ ejectSound:
path: /Audio/Weapons/Guns/Empty/empty.ogg
- type: SolutionContainerManager
solutions:
diff --git a/Resources/Prototypes/Entities/Objects/Decoration/present.yml b/Resources/Prototypes/Entities/Objects/Decoration/present.yml
index 3a7d059e9f..c5a308591c 100644
--- a/Resources/Prototypes/Entities/Objects/Decoration/present.yml
+++ b/Resources/Prototypes/Entities/Objects/Decoration/present.yml
@@ -376,5 +376,4 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
- type: SpaceGarbage
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/base_machineboard.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/base_machineboard.yml
index 0ff99e2902..f11e2021c6 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/base_machineboard.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/base_machineboard.yml
@@ -14,3 +14,9 @@
- DroneUsable
- type: StaticPrice
price: 100
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 400
+ chemicalComposition:
+ Silicon: 20
+
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
index adc52ac563..4ace8ea4f0 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml
@@ -466,6 +466,11 @@
materialRequirements:
CableMV: 5
CableHV: 5
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 200
+ chemicalComposition:
+ Silicon: 20
- type: entity
parent: BaseMachineCircuitboard
@@ -515,6 +520,11 @@
Capacitor: 1
materialRequirements:
CableHV: 5
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 200
+ chemicalComposition:
+ Silicon: 20
- type: entity
id: ThrusterMachineCircuitboard
@@ -555,6 +565,11 @@
Capacitor: 2
materialRequirements:
CableHV: 10
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 200
+ chemicalComposition:
+ Silicon: 20
- type: entity
id: ReagentGrinderMachineCircuitboard
@@ -611,6 +626,21 @@
DefaultPrototype: CryostasisBeaker
ExamineName: Cryostasis Beaker
+- type: entity
+ id: MaterialReclaimerMachineCircuitboard
+ parent: BaseMachineCircuitboard
+ name: material reclaimer machine board
+ components:
+ - type: Sprite
+ state: supply
+ - type: MachineBoard
+ prototype: MaterialReclaimer
+ requirements:
+ Manipulator: 2
+ materialRequirements:
+ Steel: 5
+ Plastic: 5
+
- type: entity
id: OreProcessorMachineCircuitboard
parent: BaseMachineCircuitboard
@@ -726,7 +756,7 @@
materialRequirements:
Steel: 10
Plasma: 5
-
+
- type: entity
id: BoozeDispenserMachineCircuitboard
parent: BaseMachineCircuitboard
@@ -766,7 +796,7 @@
- type: entity
id: TelecomServerCircuitboard
parent: BaseMachineCircuitboard
- name: telecommunication server machine board
+ name: telecommunication server machine board
description: A machine printed circuit board for an telecommunication server.
components:
- type: MachineBoard
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
index 25e3ef4181..bfe7cfc64e 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
@@ -13,6 +13,11 @@
- DroneUsable
- type: StaticPrice
price: 100
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 400
+ chemicalComposition:
+ Silicon: 20
- type: entity
parent: BaseComputerCircuitboard
@@ -68,6 +73,10 @@
prototype: ComputerCargoOrders
- type: StaticPrice
price: 750
+ - type: Tag
+ tags:
+ - DroneUsable
+ - HighRiskItem
- type: entity
parent: BaseComputerCircuitboard
@@ -178,6 +187,10 @@
prototype: ComputerId
- type: StaticPrice
price: 750
+ - type: Tag
+ tags:
+ - DroneUsable
+ - HighRiskItem
- type: entity
parent: BaseComputerCircuitboard
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Electronics/base_electronics.yml b/Resources/Prototypes/Entities/Objects/Devices/Electronics/base_electronics.yml
index e4f789f1f3..ec24e4be15 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Electronics/base_electronics.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Electronics/base_electronics.yml
@@ -14,3 +14,8 @@
- DroneUsable
- type: StaticPrice
price: 100
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 200
+ chemicalComposition:
+ Silicon: 20
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Electronics/power_electronics.yml b/Resources/Prototypes/Entities/Objects/Devices/Electronics/power_electronics.yml
index 7adc3a1095..5b48ede4c1 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Electronics/power_electronics.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Electronics/power_electronics.yml
@@ -10,6 +10,11 @@
sprite: Objects/Misc/module.rsi
state: charger_APC
netsync: false
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 50
+ chemicalComposition:
+ Silicon: 20
# Wallmount Substation
- type: entity
diff --git a/Resources/Prototypes/Entities/Objects/Devices/hand_teleporter.yml b/Resources/Prototypes/Entities/Objects/Devices/hand_teleporter.yml
index 55839ada54..0acd4fbf19 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/hand_teleporter.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/hand_teleporter.yml
@@ -9,3 +9,6 @@
layers:
- state: icon
- type: HandTeleporter
+ - type: Tag
+ tags:
+ - HighRiskItem
diff --git a/Resources/Prototypes/Entities/Objects/Fun/crayons.yml b/Resources/Prototypes/Entities/Objects/Fun/crayons.yml
index 0dc6cb3045..d0856c64f4 100644
--- a/Resources/Prototypes/Entities/Objects/Fun/crayons.yml
+++ b/Resources/Prototypes/Entities/Objects/Fun/crayons.yml
@@ -10,7 +10,6 @@
- Write
- Crayon
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: UserInterface
interfaces:
diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml
index 848993121c..ca7504c063 100644
--- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml
+++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml
@@ -26,6 +26,11 @@
damage:
types:
Blunt: 0
+ - type: PhysicalComposition
+ materialComposition:
+ Cloth: 100
+ - type: StaticPrice
+ price: 5
- type: entity
parent: BasePlushie
@@ -243,7 +248,6 @@
- type: Sprite
state: narplush
-
- type: entity
parent: BasePlushie
id: PlushieCarp
@@ -356,55 +360,66 @@
- type: entity
parent: BaseItem
+ id: BaseFigurine
+ name: figurine
+ description: A small miniature.
+ abstract: true
+ components:
+ - type: Sprite
+ sprite: Objects/Fun/toys.rsi
+ netsync: false
+ - type: PhysicalComposition
+ materialComposition:
+ Plastic: 100
+ - type: StaticPrice
+ price: 10
+
+- type: entity
+ parent: BaseFigurine
id: ToyAi
name: AI toy
description: A scaled-down toy AI core.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: AI
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyNuke
name: nuke toy
description: A plastic model of a Nuclear Fission Explosive. No uranium included... probably.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: nuketoy
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyAssistant # TODO rename but needs map changes
name: passenger toy
description: Grey tide world wide!
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: doll
- type: Item
sprite: Objects/Fun/toys.rsi
heldPrefix: doll
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyGriffin
name: griffin toy
description: An action figure modeled after 'The Griffin', criminal mastermind.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: griffinprize
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyHonk
name: H.O.N.K. toy
description: Mini-Mecha action figure! 'Mecha No. 6/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: honkprize
- type: entity
@@ -423,125 +438,111 @@
path: /Audio/Items/Toys/ian.ogg
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyMarauder
name: marauder toy
description: Mini-Mecha action figure! 'Mecha No. 7/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: marauderprize
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyMauler
name: mauler toy
description: Mini-Mecha action figure! 'Mecha No. 9/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: maulerprize
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyGygax
name: gygax toy
description: Mini-Mecha action figure! 'Mecha No. 4/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: gygaxtoy
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyOdysseus
name: odysseus toy
description: Mini-Mecha action figure! 'Mecha No. 10/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: odysseusprize
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyOwlman
name: owl toy
description: An action figure modeled after 'The Owl', defender of justice.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: owlprize
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyDeathRipley
name: deathripley toy
description: Mini-Mecha action figure! 'Mecha No. 3/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: deathripleytoy
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyPhazon
name: phazon toy
description: Mini-Mecha action figure! 'Mecha No. 11/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: phazonprize
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyFireRipley
name: fire ripley
description: Mini-Mecha action figure! 'Mecha No. 2/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: fireripleytoy
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyReticence
name: reticence toy
description: Mini-Mecha action figure! 'Mecha No. 12/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: reticenceprize
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyRipley
name: ripley toy
description: Mini-Mecha action figure! 'Mecha No. 1/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: ripleytoy
-
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToySeraph
name: seraph toy
description: Mini-Mecha action figure! 'Mecha No. 8/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: seraphprize
-
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToyDurand
name: durand toy
description: Mini-Mecha action figure! 'Mecha No. 5/12' is written on the back.
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: durandprize
@@ -549,13 +550,12 @@
### Help i'm sorting these and my previous self let this message here to taunt me aaaaa
- type: entity
- parent: BaseItem
+ parent: BaseFigurine
id: ToySkeleton
name: skeleton toy
description: Spooked ya!
components:
- type: Sprite
- sprite: Objects/Fun/toys.rsi
state: skeletonprize
## Toyweapons
@@ -843,8 +843,6 @@
available:
- enum.DamageStateVisualLayers.Base:
base: Sixteen
- - type: StaticPrice
- price: 3
- type: entity
parent: BaseItem
diff --git a/Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml b/Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml
index 0a0c876e99..e49d6a3207 100644
--- a/Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml
+++ b/Resources/Prototypes/Entities/Objects/Materials/Sheets/glass.yml
@@ -51,8 +51,6 @@
- type: Material
materials:
Glass: 100
- - type: StackPrice
- price: 5
- type: Stack
stackType: Glass
- type: Sprite
diff --git a/Resources/Prototypes/Entities/Objects/Materials/shards.yml b/Resources/Prototypes/Entities/Objects/Materials/shards.yml
index 2ae5298d57..a0711122da 100644
--- a/Resources/Prototypes/Entities/Objects/Materials/shards.yml
+++ b/Resources/Prototypes/Entities/Objects/Materials/shards.yml
@@ -51,7 +51,6 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: Damageable
damageContainer: Inorganic
diff --git a/Resources/Prototypes/Entities/Objects/Misc/box.yml b/Resources/Prototypes/Entities/Objects/Misc/box.yml
index 5f3e1e6cd9..d893b56cce 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/box.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/box.yml
@@ -20,3 +20,8 @@
node: boxcardboard
containers:
- entity_storage
+ - type: PhysicalComposition
+ materialComposition:
+ Cardboard: 100
+ - type: StaticPrice
+ price: 10
diff --git a/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml b/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml
index 8d7462cc96..e7f2088b64 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/broken_bottle.yml
@@ -23,6 +23,8 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 50
- type: SpaceGarbage
diff --git a/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml b/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml
index b0fe40562e..30a0065056 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml
@@ -18,6 +18,9 @@
- type: WarpPoint
follow: true
location: nuke disk
+ - type: Tag
+ tags:
+ - HighRiskItem
- type: entity
name: nuclear authentication disk
diff --git a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml
index 6499ceeab1..b21f47cb60 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/handcuffs.yml
@@ -90,10 +90,12 @@
components:
- type: Item
size: 2
- - type: Recyclable
- type: Tag
tags:
- Trash
+ - type: PhysicalComposition
+ materialComposition:
+ Plastic: 25
- type: entity
name: broken zipties
@@ -114,4 +116,4 @@
- type: Sprite
sprite: Objects/Misc/cablecuffs.rsi
state: cuff-broken
- color: forestgreen
\ No newline at end of file
+ color: forestgreen
diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
index 50da83763b..b1ba64a8f8 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
@@ -107,6 +107,10 @@
heldPrefix: gold
- type: PresetIdCard
job: Captain
+ - type: Tag
+ tags:
+ - WhitelistChameleon
+ - HighRiskItem
- type: entity
parent: IDCardStandard
@@ -548,7 +552,7 @@
- state: idzookeeper
- type: PresetIdCard
job: Zookeeper
-
+
- type: entity
parent: IDCardStandard
id: DetectiveIDCard
@@ -572,7 +576,7 @@
- state: idcentcom
- type: Item
heldPrefix: gold
-
+
- type: entity
parent: IDCardStandard
diff --git a/Resources/Prototypes/Entities/Objects/Misc/paper.yml b/Resources/Prototypes/Entities/Objects/Misc/paper.yml
index 4dbe14d202..d35fb1eafb 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/paper.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/paper.yml
@@ -31,7 +31,6 @@
- Trash
- type: Appearance
- type: PaperVisuals
- - type: Recyclable
- type: entity
name: office paper
@@ -182,7 +181,9 @@
sprite: Objects/Misc/bureaucracy.rsi
heldPrefix: pen
size: 2
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 25
- type: entity
name: Cybersun pen
diff --git a/Resources/Prototypes/Entities/Objects/Misc/utensils.yml b/Resources/Prototypes/Entities/Objects/Misc/utensils.yml
index ee6d680485..e2891c48bf 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/utensils.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/utensils.yml
@@ -10,7 +10,6 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: entity
diff --git a/Resources/Prototypes/Entities/Objects/Power/lights.yml b/Resources/Prototypes/Entities/Objects/Power/lights.yml
index a0aa6b4330..ccc3cdb146 100644
--- a/Resources/Prototypes/Entities/Objects/Power/lights.yml
+++ b/Resources/Prototypes/Entities/Objects/Power/lights.yml
@@ -60,7 +60,9 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 25
- type: SpaceGarbage
- type: entity
diff --git a/Resources/Prototypes/Entities/Objects/Shields/shields.yml b/Resources/Prototypes/Entities/Objects/Shields/shields.yml
index 29ddee84c6..d1668feae5 100644
--- a/Resources/Prototypes/Entities/Objects/Shields/shields.yml
+++ b/Resources/Prototypes/Entities/Objects/Shields/shields.yml
@@ -43,11 +43,11 @@
- !type:SpawnEntitiesBehavior
spawn:
SheetSteel:
- min: 5
- max: 5
+ min: 2
+ max: 2
SheetGlass:
- min: 5
- max: 5
+ min: 2
+ max: 2
- type: StaticPrice
price: 50
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
index 27361d6b1b..b08a665274 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
@@ -22,6 +22,9 @@
delay: 0.5
- type: StaticPrice
price: 750
+ - type: Tag
+ tags:
+ - HighRiskItem
- type: entity
name: gorlex hypospray
@@ -78,7 +81,9 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Plastic: 50
- type: SpaceGarbage
- type: StaticPrice
price: 75 # These are limited supply items.
diff --git a/Resources/Prototypes/Entities/Objects/Specific/atmos.yml b/Resources/Prototypes/Entities/Objects/Specific/atmos.yml
index 21ce9f46d4..1bb1ae59ca 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/atmos.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/atmos.yml
@@ -32,3 +32,7 @@
- DroneUsable
- type: StaticPrice
price: 80
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 400
+ Glass: 100
diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml
index 3c255483d4..73c6a3a08f 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml
@@ -9,7 +9,9 @@
tags:
- Bottle
- Trash
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Glass: 25
- type: SpaceGarbage
- type: Sprite
sprite: Objects/Specific/Chemistry/bottle.rsi
diff --git a/Resources/Prototypes/Entities/Objects/Tools/bucket.yml b/Resources/Prototypes/Entities/Objects/Tools/bucket.yml
index a61b6efb4e..532e838817 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/bucket.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/bucket.yml
@@ -58,3 +58,6 @@
- type: Tag
tags:
- Bucket
+ - type: PhysicalComposition
+ materialComposition:
+ Plastic: 50
diff --git a/Resources/Prototypes/Entities/Objects/Tools/flare.yml b/Resources/Prototypes/Entities/Objects/Tools/flare.yml
index 71261cc8a9..e67c8f74a4 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/flare.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/flare.yml
@@ -8,7 +8,6 @@
tags:
- Flare
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: ExpendableLight
spentName: expendable-light-spent-flare-name
diff --git a/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml b/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml
index 21b5ebde94..4c8dcda6c6 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/gas_tanks.yml
@@ -35,6 +35,11 @@
damage:
types:
Blunt: 10
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 400
+ - type: StaticPrice
+ price: 20
- type: entity
parent: GasTankBase
@@ -109,6 +114,9 @@
damage:
types:
Blunt: 5
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
- type: entity
parent: EmergencyOxygenTank
diff --git a/Resources/Prototypes/Entities/Objects/Tools/glowstick.yml b/Resources/Prototypes/Entities/Objects/Tools/glowstick.yml
index 9b58d9105e..41919ddce6 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/glowstick.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/glowstick.yml
@@ -4,7 +4,6 @@
id: GlowstickBase
description: Useful for raves and emergencies.
components:
- - type: Recyclable
- type: SpaceGarbage
- type: ExpendableLight
spentName: expendable-light-spent-green-glowstick-name
diff --git a/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml b/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml
index 388cef6019..cd8da06a32 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/jetpacks.yml
@@ -147,6 +147,9 @@
- type: Item
sprite: Objects/Tanks/Jetpacks/captain.rsi
size: 30
+ - type: Tag
+ tags:
+ - HighRiskItem
# Filled captain
- type: entity
@@ -248,7 +251,7 @@
sprite: Objects/Tanks/Jetpacks/void.rsi
slots:
- Back
- - suitStorage
+ - suitStorage
# Filled void
- type: entity
diff --git a/Resources/Prototypes/Entities/Objects/Tools/matches.yml b/Resources/Prototypes/Entities/Objects/Tools/matches.yml
index 9350cf4da6..3700a1bfb1 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/matches.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/matches.yml
@@ -18,7 +18,6 @@
tags:
- Matchstick
- Trash
- - type: Recyclable
- type: SpaceGarbage
- type: Sprite
netsync: false
@@ -94,5 +93,4 @@
- type: Tag
tags:
- Trash
- - type: Recyclable
- type: SpaceGarbage
diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml
index ac419a7016..9708b7f538 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml
@@ -35,6 +35,9 @@
- type: Item
sprite: Objects/Tools/wirecutters.rsi
- type: LatticeCutting
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
- type: StaticPrice
price: 40
@@ -74,6 +77,9 @@
available:
- enum.DamageStateVisualLayers.Base:
screwdriver: Rainbow
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
- type: StaticPrice
price: 40
@@ -106,6 +112,9 @@
- Anchoring
useSound:
path: /Audio/Items/ratchet.ogg
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
- type: StaticPrice
price: 40
@@ -139,6 +148,9 @@
useSound:
path: /Audio/Items/crowbar.ogg
- type: TilePrying
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
- type: StaticPrice
price: 40
@@ -200,6 +212,10 @@
- type: Tag
tags:
- DroneUsable
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
+ Plastic: 100
- type: StaticPrice
price: 60
@@ -242,6 +258,10 @@
path: /Audio/Items/drill_use.ogg
changeSound:
path: /Audio/Items/change_drill.ogg
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 300
+ Plastic: 100
- type: StaticPrice
price: 100
@@ -264,6 +284,10 @@
quickEquip: false
slots:
- Belt
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 600
+ Plastic: 100
- type: StaticPrice
price: 100
@@ -288,6 +312,10 @@
- type: Item
sprite: Objects/Tools/rcd.rsi
heldPrefix: ammo
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
+ Plastic: 100
- type: StaticPrice
price: 60
@@ -310,6 +338,12 @@
Blunt: 10
- type: Item
sprite: Objects/Tools/shovel.rsi
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 100
+ Wood: 50
+ - type: StaticPrice
+ price: 25
- type: entity
name: omnitool
diff --git a/Resources/Prototypes/Entities/Objects/Tools/welders.yml b/Resources/Prototypes/Entities/Objects/Tools/welders.yml
index fbf43fefa3..0834b192b0 100644
--- a/Resources/Prototypes/Entities/Objects/Tools/welders.yml
+++ b/Resources/Prototypes/Entities/Objects/Tools/welders.yml
@@ -60,6 +60,9 @@
color: orange
- type: Appearance
- type: RequiresEyeProtection
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 200
- type: StaticPrice
price: 40
- type: IgnitionSource
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/base_cartridge.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/base_cartridge.yml
index c021eebed6..230be6a76b 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/base_cartridge.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/base_cartridge.yml
@@ -11,5 +11,4 @@
- Cartridge
- type: Item
size: 1
- - type: Recyclable
- type: SpaceGarbage
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/toy.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/toy.yml
index 39542eccc2..34a39c1583 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/toy.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/toy.yml
@@ -7,9 +7,9 @@
- type: Tag
tags:
- BulletFoam
+ - Trash
- type: Ammo
- type: Sprite
sprite: Objects/Fun/toys.rsi
layers:
- state: foamdart
- - type: Recyclable
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
index 2b2f7ed0b0..ba1e9cfa46 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
@@ -390,6 +390,9 @@
steps: 5
zeroVisible: true
- type: Appearance
+ - type: Tag
+ tags:
+ - HighRiskItem
- type: StaticPrice
price: 750
diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
index f7599c12c9..6bce0ecbf8 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
@@ -306,6 +306,7 @@
- DawInstrumentMachineCircuitboard
- CloningConsoleComputerCircuitboard
- StasisBedMachineCircuitboard
+ - MaterialReclaimerMachineCircuitboard
- OreProcessorMachineCircuitboard
- RipleyCentralElectronics
- RipleyPeripheralsElectronics
diff --git a/Resources/Prototypes/Entities/Structures/Machines/material_reclaimer.yml b/Resources/Prototypes/Entities/Structures/Machines/material_reclaimer.yml
new file mode 100644
index 0000000000..26d4adf09d
--- /dev/null
+++ b/Resources/Prototypes/Entities/Structures/Machines/material_reclaimer.yml
@@ -0,0 +1,101 @@
+- type: entity
+ parent: [ BaseMachinePowered, ConstructibleMachine ]
+ id: MaterialReclaimer
+ name: material reclaimer
+ description: Cannot reclaim immaterial things, like motivation.
+ components:
+ - type: Sprite
+ sprite: Structures/Machines/material_reclaimer.rsi
+ snapCardinals: true
+ netsync: false
+ layers:
+ - state: icon
+ map: ["enum.LatheVisualLayers.IsRunning"]
+ - state: gear-active
+ map: ["enum.DamageStateVisualLayers.Base"]
+ - state: unlit
+ shader: unshaded
+ map: ["enum.PowerDeviceVisualLayers.Powered"]
+ - state: fill-6
+ map: ["enum.SolutionContainerLayers.Fill"]
+ visible: false
+ - state: panel
+ map: ["enum.WiresVisualLayers.MaintenancePanel"]
+ - type: Appearance
+ - type: SolutionContainerVisuals
+ maxFillLevels: 6
+ fillBaseName: fill-
+ - type: WiresVisuals
+ - type: GenericVisualizer
+ visuals:
+ enum.PowerDeviceVisuals.Powered:
+ enum.DamageStateVisualLayers.Base:
+ True: { state: gear-active}
+ False: { state: gear-idle }
+ enum.PowerDeviceVisualLayers.Powered:
+ True: { visible: true }
+ False: { visible: false }
+ - type: LitOnPowered
+ - type: PointLight
+ radius: 1.5
+ energy: 1.6
+ enabled: false
+ color: "#da824d"
+ mask: /Textures/Effects/LightMasks/cone.png
+ autoRot: true
+ offset: "0, 0.4"
+ castShadows: false
+ - type: PowerSwitch
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 100
+ behaviors:
+ - !type:ChangeConstructionNodeBehavior
+ node: machineFrame
+ - !type:DoActsBehavior
+ acts: ["Destruction"]
+ - type: Machine
+ board: MaterialReclaimerMachineCircuitboard
+ - type: Wires
+ BoardName: "reclaimer"
+ LayoutId: Reclaimer
+ - type: MaterialReclaimer
+ whitelist:
+ components:
+ - PhysicalComposition
+ - SpaceGarbage
+ tags:
+ - Trash
+ - Recyclable
+ blacklist:
+ components:
+ - Material
+ - PDA
+ - IdCard
+ tags:
+ - HighRiskItem
+ sound:
+ path: /Audio/Ambience/Objects/crushing.ogg
+ params:
+ volume: 5
+ maxdistance: 5
+ loop: true
+ - type: MaterialStorage
+ insertOnInteract: false
+ - type: ContainerContainer
+ containers:
+ active-material-reclaimer-container: !type:Container
+ machine_board: !type:Container
+ machine_parts: !type:Container
+ - type: SolutionContainerManager
+ solutions:
+ output:
+ maxVol: 100
+ - type: DrainableSolution
+ solution: output
+ - type: ExaminableSolution
+ solution: output
+ - type: StaticPrice
+ price: 500
diff --git a/Resources/Prototypes/Entities/Structures/Machines/recycler.yml b/Resources/Prototypes/Entities/Structures/Machines/recycler.yml
index 6faa94dd3f..49b6e563dd 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/recycler.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/recycler.yml
@@ -11,12 +11,11 @@
sound:
# TODO: https://freesound.org/people/derjuli/sounds/448133/ CC-NC-
path: /Audio/Ambience/Objects/circular_saw.ogg
- - type: Physics
- type: Fixtures
fixtures:
- shape:
!type:PhysShapeAabb
- bounds: "-0.2,-0.2,0.2,0.2"
+ bounds: "-0.15,-0.15,0.15,0.15"
id: brrt
hard: false
layer:
@@ -58,11 +57,58 @@
layers:
- state: grinder-o0
map: ["enum.RecyclerVisualLayers.Main"]
+ - state: grinder-o0bld
+ map: ["enum.RecyclerVisualLayers.Bloody"]
+ visible: false
- type: Appearance
+ - type: GenericVisualizer
visuals:
- - type: RecyclerVisualizer
- state_on: grinder-o1
- state_off: grinder-o0
- - type: Recycler
+ enum.RecyclerVisuals.Bloody:
+ enum.RecyclerVisualLayers.Main:
+ True: { visible: false }
+ False: { visible: true }
+ enum.RecyclerVisualLayers.Bloody:
+ True: { visible: true }
+ False: { visible: false }
+ enum.ConveyorVisuals.State:
+ enum.RecyclerVisualLayers.Main:
+ Forward: { state: grinder-o1 }
+ Reverse: { state: grinder-o1 }
+ Off: { state: grinder-o0 }
+ enum.RecyclerVisualLayers.Bloody:
+ Forward: { state: grinder-o1bld }
+ Reverse: { state: grinder-o1bld }
+ Off: { state: grinder-o0bld }
+ - type: CollideMaterialReclaimer
+ - type: MaterialReclaimer
+ enabled: false
+ efficiency: 0.25
+ scaleProcessSpeed: false #instant!
+ minimumProcessDuration: 0
+ whitelist:
+ components:
+ - PhysicalComposition
+ - SpaceGarbage
+ tags:
+ - Trash
+ - Recyclable
+ blacklist:
+ components:
+ - Material
+ - PDA
+ - IdCard
+ - HumanoidAppearance
+ tags:
+ - HighRiskItem
+ sound:
+ path: /Audio/Effects/saw.ogg
+ params:
+ volume: -3
+ cutOffSound: false
+ - type: SolutionContainerManager
+ solutions:
+ output:
+ maxVol: 0 #exists only for the overflow stuff on material reclaimer
+ - type: MaterialStorage
- type: Conveyor
- type: Rotatable
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml b/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml
index 345eea9897..2e89c2f622 100644
--- a/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml
+++ b/Resources/Prototypes/Entities/Structures/Storage/Canisters/gas_canisters.yml
@@ -608,7 +608,9 @@
- MachineMask
layer:
- MachineLayer
- - type: Recyclable
+ - type: PhysicalComposition
+ materialComposition:
+ Steel: 500
- type: StaticPrice
price: 60
diff --git a/Resources/Prototypes/Entities/Structures/Windows/window.yml b/Resources/Prototypes/Entities/Structures/Windows/window.yml
index 2234f3de72..e68dbb8f62 100644
--- a/Resources/Prototypes/Entities/Structures/Windows/window.yml
+++ b/Resources/Prototypes/Entities/Structures/Windows/window.yml
@@ -169,7 +169,7 @@
graph: WindowDirectional
node: windowDirectional
- type: StaticPrice
- price: 5
+ price: 10
- type: entity
id: WindowTintedDirectional
@@ -193,8 +193,6 @@
state: tinted_window
- type: Occluder
boundingBox: "-0.5,-0.5,0.5,-0.3"
- - type: StaticPrice
- price: 5
- type: entity
id: WindowFrostedDirectional
@@ -213,5 +211,3 @@
- type: Icon
sprite: Structures/Windows/directional.rsi
state: frosted_window
- - type: StaticPrice
- price: 5
diff --git a/Resources/Prototypes/Reagents/Materials/materials.yml b/Resources/Prototypes/Reagents/Materials/materials.yml
index faaa2523ec..15af26eb47 100644
--- a/Resources/Prototypes/Reagents/Materials/materials.yml
+++ b/Resources/Prototypes/Reagents/Materials/materials.yml
@@ -12,7 +12,7 @@
name: materials-cardboard
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cardboard }
color: "#70736c"
- price: 0.05
+ price: 0.005
- type: material
id: Cloth
diff --git a/Resources/Prototypes/Recipes/Lathes/electronics.yml b/Resources/Prototypes/Recipes/Lathes/electronics.yml
index c5aea71800..468c0e5a56 100644
--- a/Resources/Prototypes/Recipes/Lathes/electronics.yml
+++ b/Resources/Prototypes/Recipes/Lathes/electronics.yml
@@ -292,6 +292,14 @@
Glass: 900
Gold: 100
+- type: latheRecipe
+ id: MaterialReclaimerMachineCircuitboard
+ result: MaterialReclaimerMachineCircuitboard
+ completetime: 4
+ materials:
+ Steel: 100
+ Glass: 900
+
- type: latheRecipe
id: OreProcessorMachineCircuitboard
result: OreProcessorMachineCircuitboard
diff --git a/Resources/Prototypes/Recipes/Lathes/janitorial.yml b/Resources/Prototypes/Recipes/Lathes/janitorial.yml
index 4c537c30e5..1515ccdaad 100644
--- a/Resources/Prototypes/Recipes/Lathes/janitorial.yml
+++ b/Resources/Prototypes/Recipes/Lathes/janitorial.yml
@@ -18,7 +18,7 @@
result: Bucket
completetime: 2
materials:
- Steel: 100
+ Plastic: 100
- type: latheRecipe
id: WetFloorSign
diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml
index bfb69b2448..f7870ccdc6 100644
--- a/Resources/Prototypes/tags.yml
+++ b/Resources/Prototypes/tags.yml
@@ -302,6 +302,9 @@
- type: Tag
id: HidesHair # for headwear.
+- type: Tag
+ id: HighRiskItem
+
- type: Tag
id: Hoe
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-1.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-1.png
new file mode 100644
index 0000000000..32efd405d8
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-1.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-2.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-2.png
new file mode 100644
index 0000000000..71883d8117
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-2.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-3.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-3.png
new file mode 100644
index 0000000000..747e6a3fd5
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-3.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-4.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-4.png
new file mode 100644
index 0000000000..e734cce94b
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-4.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-5.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-5.png
new file mode 100644
index 0000000000..1ed097f5e2
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-5.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-6.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-6.png
new file mode 100644
index 0000000000..ab269efd65
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/fill-6.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/gear-active.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/gear-active.png
new file mode 100644
index 0000000000..a228b142f4
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/gear-active.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/gear-idle.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/gear-idle.png
new file mode 100644
index 0000000000..96a795aaf3
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/gear-idle.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/icon.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/icon.png
new file mode 100644
index 0000000000..7ba2ef785e
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/icon.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/meta.json b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/meta.json
new file mode 100644
index 0000000000..3e27312a6c
--- /dev/null
+++ b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/meta.json
@@ -0,0 +1,57 @@
+{
+ "version": 1,
+ "license": "CC0-1.0",
+ "copyright": "Created by EmoGarbage404 (github) for Space Station 14",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "fill-1"
+ },
+ {
+ "name": "fill-2"
+ },
+ {
+ "name": "fill-3"
+ },
+ {
+ "name": "fill-4"
+ },
+ {
+ "name": "fill-5"
+ },
+ {
+ "name": "fill-6"
+ },
+ {
+ "name": "gear-active",
+ "delays": [
+ [
+ 0.25,
+ 0.25,
+ 0.25
+ ]
+ ]
+ },
+ {
+ "name": "gear-idle"
+ },
+ {
+ "name": "icon"
+ },
+ {
+ "name": "panel"
+ },
+ {
+ "name": "unlit",
+ "delays": [
+ [
+ 0.1,
+ 1.0
+ ]
+ ]
+ }
+ ]
+}
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/panel.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/panel.png
new file mode 100644
index 0000000000..b3de5c1be1
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/panel.png differ
diff --git a/Resources/Textures/Structures/Machines/material_reclaimer.rsi/unlit.png b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/unlit.png
new file mode 100644
index 0000000000..9c9511af3e
Binary files /dev/null and b/Resources/Textures/Structures/Machines/material_reclaimer.rsi/unlit.png differ