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
This commit is contained in:
9
Content.Client/Materials/MaterialReclaimerSystem.cs
Normal file
9
Content.Client/Materials/MaterialReclaimerSystem.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Content.Shared.Materials;
|
||||||
|
|
||||||
|
namespace Content.Client.Materials;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public sealed class MaterialReclaimerSystem : SharedMaterialReclaimerSystem
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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<IEntityManager>();
|
|
||||||
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<IEntityManager>();
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,10 +14,12 @@ using Robust.Shared.GameObjects;
|
|||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.Construction.Components;
|
using Content.Shared.Construction.Components;
|
||||||
|
using Content.Shared.FixedPoint;
|
||||||
|
using Content.Shared.Materials;
|
||||||
|
|
||||||
namespace Content.IntegrationTests.Tests;
|
namespace Content.IntegrationTests.Tests;
|
||||||
|
|
||||||
@@ -31,10 +33,7 @@ public sealed class MaterialArbitrageTest
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task NoMaterialArbitrage()
|
public async Task NoMaterialArbitrage()
|
||||||
{
|
{
|
||||||
// TODO check lathe resource prices?
|
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings {NoClient = true});
|
||||||
// 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});
|
|
||||||
var server = pairTracker.Pair.Server;
|
var server = pairTracker.Pair.Server;
|
||||||
|
|
||||||
var testMap = await PoolManager.CreateTestMap(pairTracker);
|
var testMap = await PoolManager.CreateTestMap(pairTracker);
|
||||||
@@ -51,8 +50,9 @@ public sealed class MaterialArbitrageTest
|
|||||||
var compFact = server.ResolveDependency<IComponentFactory>();
|
var compFact = server.ResolveDependency<IComponentFactory>();
|
||||||
|
|
||||||
var constructionName = compFact.GetComponentName(typeof(ConstructionComponent));
|
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 destructibleName = compFact.GetComponentName(typeof(DestructibleComponent));
|
||||||
var stackName = compFact.GetComponentName(typeof(StackComponent));
|
|
||||||
|
|
||||||
// construct inverted lathe recipe dictionary
|
// construct inverted lathe recipe dictionary
|
||||||
Dictionary<string, LatheRecipePrototype> latheRecipes = new();
|
Dictionary<string, LatheRecipePrototype> latheRecipes = new();
|
||||||
@@ -84,6 +84,9 @@ public sealed class MaterialArbitrageTest
|
|||||||
{
|
{
|
||||||
var materials = new Dictionary<string, int>();
|
var materials = new Dictionary<string, int>();
|
||||||
var graph = protoManager.Index<ConstructionGraphPrototype>(comp.Graph);
|
var graph = protoManager.Index<ConstructionGraphPrototype>(comp.Graph);
|
||||||
|
if (graph.Start == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!graph.TryPath(graph.Start, comp.Node, out var path) || path.Length == 0)
|
if (!graph.TryPath(graph.Start, comp.Node, out var path) || path.Length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -93,10 +96,25 @@ public sealed class MaterialArbitrageTest
|
|||||||
var edge = cur.GetEdge(node.Name);
|
var edge = cur.GetEdge(node.Name);
|
||||||
cur = node;
|
cur = node;
|
||||||
|
|
||||||
|
if (edge == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
foreach (var step in edge.Steps)
|
foreach (var step in edge.Steps)
|
||||||
{
|
{
|
||||||
if (step is MaterialConstructionGraphStep materialStep)
|
if (step is not MaterialConstructionGraphStep materialStep)
|
||||||
materials[materialStep.MaterialPrototypeId] = materialStep.Amount + materials.GetValueOrDefault(materialStep.MaterialPrototypeId);
|
continue;
|
||||||
|
|
||||||
|
var stackProto = protoManager.Index<StackPrototype>(materialStep.MaterialPrototypeId);
|
||||||
|
var spawnProto = protoManager.Index<EntityPrototype>(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);
|
constructionMaterials.Add(id, materials);
|
||||||
@@ -136,11 +154,16 @@ public sealed class MaterialArbitrageTest
|
|||||||
spawnedEnts[key] = spawnedEnts.GetValueOrDefault(key) + value.Max;
|
spawnedEnts[key] = spawnedEnts.GetValueOrDefault(key) + value.Max;
|
||||||
|
|
||||||
var spawnProto = protoManager.Index<EntityPrototype>(key);
|
var spawnProto = protoManager.Index<EntityPrototype>(key);
|
||||||
if (!spawnProto.Components.TryGetValue(stackName, out var reg))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var stack = (StackComponent) reg.Component;
|
// get the amount of each material included in the entity
|
||||||
spawnedMats[stack.StackTypeId] = value.Max + spawnedMats.GetValueOrDefault(stack.StackTypeId);
|
if (!spawnProto.Components.TryGetValue(materialName, out var matreg))
|
||||||
|
continue;
|
||||||
|
var mat = (MaterialComponent) matreg.Component;
|
||||||
|
|
||||||
|
foreach (var (matId, amount) in mat.Materials)
|
||||||
|
{
|
||||||
|
spawnedMats[matId] = value.Max * amount + spawnedMats.GetValueOrDefault(matId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,18 +234,21 @@ public sealed class MaterialArbitrageTest
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var spawnProto = protoManager.Index<EntityPrototype>(spawnCompletion.Prototype);
|
var spawnProto = protoManager.Index<EntityPrototype>(spawnCompletion.Prototype);
|
||||||
if (!spawnProto.Components.TryGetValue(stackName, out var reg))
|
|
||||||
|
if (!spawnProto.Components.TryGetValue(materialName, out var matreg))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var stack = (StackComponent) reg.Component;
|
var mat = (MaterialComponent) matreg.Component;
|
||||||
|
foreach (var (matId, amount) in mat.Materials)
|
||||||
materials[stack.StackTypeId] = spawnCompletion.Amount + materials.GetValueOrDefault(stack.StackTypeId);
|
{
|
||||||
|
materials[matId] = spawnCompletion.Amount * amount + materials.GetValueOrDefault(matId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deconstructionMaterials.Add(id, materials);
|
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.
|
// This is pretty braindead. In principle construction graphs can have loops and whatnot.
|
||||||
|
|
||||||
Assert.Multiple(async () =>
|
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<string, PhysicalCompositionComponent> physicalCompositions = new();
|
||||||
|
foreach (var proto in protoManager.EnumeratePrototypes<EntityPrototype>())
|
||||||
|
{
|
||||||
|
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 server.WaitPost(() => mapManager.DeleteMap(testMap.MapId));
|
||||||
await pairTracker.CleanReturnAsync();
|
await pairTracker.CleanReturnAsync();
|
||||||
|
|
||||||
@@ -293,8 +371,20 @@ public sealed class MaterialArbitrageTest
|
|||||||
double price = 0;
|
double price = 0;
|
||||||
foreach (var (id, num) in mats)
|
foreach (var (id, num) in mats)
|
||||||
{
|
{
|
||||||
var matProto = protoManager.Index<StackPrototype>(id).Spawn;
|
var matProto = protoManager.Index<MaterialPrototype>(id);
|
||||||
price += num * await GetPrice(matProto);
|
price += num * matProto.Price;
|
||||||
|
}
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async Task<double> GetChemicalCompositionPrice(Dictionary<string, FixedPoint2> mats)
|
||||||
|
{
|
||||||
|
double price = 0;
|
||||||
|
foreach (var (id, num) in mats)
|
||||||
|
{
|
||||||
|
var reagentProto = protoManager.Index<ReagentPrototype>(id);
|
||||||
|
price += num.Double() * reagentProto.PricePerUnit;
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ public sealed class PricingSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
double price = 0;
|
double price = 0;
|
||||||
|
|
||||||
if (TryComp<MaterialComponent>(uid, out var material) && !HasComp<StackPriceComponent>(uid))
|
if (TryComp<MaterialComponent>(uid, out var material))
|
||||||
{
|
{
|
||||||
var matPrice = GetMaterialPrice(material);
|
var matPrice = GetMaterialPrice(material);
|
||||||
if (TryComp<StackComponent>(uid, out var stack))
|
if (TryComp<StackComponent>(uid, out var stack))
|
||||||
@@ -229,8 +229,7 @@ public sealed class PricingSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
double price = 0;
|
double price = 0;
|
||||||
|
|
||||||
if (prototype.Components.TryGetValue(_factory.GetComponentName(typeof(MaterialComponent)), out var materials) &&
|
if (prototype.Components.TryGetValue(_factory.GetComponentName(typeof(MaterialComponent)), out var materials))
|
||||||
!prototype.Components.ContainsKey(_factory.GetComponentName(typeof(StackPriceComponent))))
|
|
||||||
{
|
{
|
||||||
var materialsComp = (MaterialComponent) materials.Component;
|
var materialsComp = (MaterialComponent) materials.Component;
|
||||||
var matPrice = GetMaterialPrice(materialsComp);
|
var matPrice = GetMaterialPrice(materialsComp);
|
||||||
@@ -276,7 +275,8 @@ public sealed class PricingSystem : EntitySystem
|
|||||||
var price = 0.0;
|
var price = 0.0;
|
||||||
|
|
||||||
if (TryComp<StackPriceComponent>(uid, out var stackPrice) &&
|
if (TryComp<StackPriceComponent>(uid, out var stackPrice) &&
|
||||||
TryComp<StackComponent>(uid, out var stack))
|
TryComp<StackComponent>(uid, out var stack) &&
|
||||||
|
!HasComp<MaterialComponent>(uid)) // don't double count material prices
|
||||||
{
|
{
|
||||||
price += stack.Count * stackPrice.Price;
|
price += stack.Count * stackPrice.Price;
|
||||||
}
|
}
|
||||||
@@ -289,7 +289,8 @@ public sealed class PricingSystem : EntitySystem
|
|||||||
var price = 0.0;
|
var price = 0.0;
|
||||||
|
|
||||||
if (prototype.Components.TryGetValue(_factory.GetComponentName(typeof(StackPriceComponent)), out var stackpriceProto) &&
|
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 stackPrice = (StackPriceComponent) stackpriceProto.Component;
|
||||||
var stack = (StackComponent) stackProto.Component;
|
var stack = (StackComponent) stackProto.Component;
|
||||||
|
|||||||
261
Content.Server/Materials/MaterialReclaimerSystem.cs
Normal file
261
Content.Server/Materials/MaterialReclaimerSystem.cs
Normal file
@@ -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;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
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!;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, ComponentStartup>(OnStartup);
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, RefreshPartsEvent>(OnRefreshParts);
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, UpgradeExamineEvent>(OnUpgradeExamine);
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, PowerChangedEvent>(OnPowerChanged);
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, InteractUsingEvent>(OnInteractUsing,
|
||||||
|
before: new []{typeof(WiresSystem), typeof(SolutionTransferSystem)});
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, SuicideEvent>(OnSuicide);
|
||||||
|
SubscribeLocalEvent<ActiveMaterialReclaimerComponent, PowerChangedEvent>(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<SolutionContainerManagerComponent>(args.Used, out var managerComponent) &&
|
||||||
|
managerComponent.Solutions.Any(s => s.Value.AvailableVolume > 0))
|
||||||
|
{
|
||||||
|
if (TryComp<DrinkComponent>(args.Used, out var drink) &&
|
||||||
|
!drink.Opened)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp<SolutionTransferComponent>(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
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<string, FixedPoint2>();
|
||||||
|
|
||||||
|
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<SolutionContainerManagerComponent>(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,9 +48,9 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
|
|||||||
return false;
|
return false;
|
||||||
if (!base.TryInsertMaterialEntity(user, toInsert, receiver, component))
|
if (!base.TryInsertMaterialEntity(user, toInsert, receiver, component))
|
||||||
return false;
|
return false;
|
||||||
_audio.PlayPvs(component.InsertingSound, component.Owner);
|
_audio.PlayPvs(component.InsertingSound, receiver);
|
||||||
_popup.PopupEntity(Loc.GetString("machine-insert-item", ("user", user), ("machine", component.Owner),
|
_popup.PopupEntity(Loc.GetString("machine-insert-item", ("user", user), ("machine", receiver),
|
||||||
("item", toInsert)), component.Owner);
|
("item", toInsert)), receiver);
|
||||||
QueueDel(toInsert);
|
QueueDel(toInsert);
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
@@ -67,16 +67,9 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
|
|||||||
/// 1 biomass = 1 biomass in its stack,
|
/// 1 biomass = 1 biomass in its stack,
|
||||||
/// but 100 plasma = 1 sheet of plasma, etc.
|
/// but 100 plasma = 1 sheet of plasma, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
|
||||||
public List<EntityUid> SpawnMultipleFromMaterial(int amount, string material, EntityCoordinates coordinates)
|
public List<EntityUid> SpawnMultipleFromMaterial(int amount, string material, EntityCoordinates coordinates)
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.TryIndex<MaterialPrototype>(material, out var stackType))
|
return SpawnMultipleFromMaterial(amount, material, coordinates, out _);
|
||||||
{
|
|
||||||
Logger.Error("Failed to index material prototype " + material);
|
|
||||||
return new List<EntityUid>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return SpawnMultipleFromMaterial(amount, stackType, coordinates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -85,8 +78,40 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
|
|||||||
/// 1 biomass = 1 biomass in its stack,
|
/// 1 biomass = 1 biomass in its stack,
|
||||||
/// but 100 plasma = 1 sheet of plasma, etc.
|
/// but 100 plasma = 1 sheet of plasma, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
public List<EntityUid> SpawnMultipleFromMaterial(int amount, string material, EntityCoordinates coordinates, out int overflowMaterial)
|
||||||
|
{
|
||||||
|
overflowMaterial = 0;
|
||||||
|
if (!_prototypeManager.TryIndex<MaterialPrototype>(material, out var stackType))
|
||||||
|
{
|
||||||
|
Logger.Error("Failed to index material prototype " + material);
|
||||||
|
return new List<EntityUid>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SpawnMultipleFromMaterial(amount, stackType, coordinates, out overflowMaterial);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
public List<EntityUid> SpawnMultipleFromMaterial(int amount, MaterialPrototype materialProto, EntityCoordinates coordinates)
|
public List<EntityUid> SpawnMultipleFromMaterial(int amount, MaterialPrototype materialProto, EntityCoordinates coordinates)
|
||||||
{
|
{
|
||||||
|
return SpawnMultipleFromMaterial(amount, materialProto, coordinates, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
public List<EntityUid> SpawnMultipleFromMaterial(int amount, MaterialPrototype materialProto, EntityCoordinates coordinates, out int overflowMaterial)
|
||||||
|
{
|
||||||
|
overflowMaterial = 0;
|
||||||
|
|
||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
return new List<EntityUid>();
|
return new List<EntityUid>();
|
||||||
|
|
||||||
@@ -96,6 +121,7 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
|
|||||||
|
|
||||||
var materialPerStack = material.Materials[materialProto.ID];
|
var materialPerStack = material.Materials[materialProto.ID];
|
||||||
var amountToSpawn = amount / materialPerStack;
|
var amountToSpawn = amount / materialPerStack;
|
||||||
|
overflowMaterial = amount - amountToSpawn * materialPerStack;
|
||||||
return _stackSystem.SpawnMultiple(materialProto.StackEntity, amountToSpawn, coordinates);
|
return _stackSystem.SpawnMultiple(materialProto.StackEntity, amountToSpawn, coordinates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
using Content.Server.MachineLinking.Events;
|
using Content.Server.MachineLinking.Events;
|
||||||
using Content.Server.MachineLinking.System;
|
using Content.Server.MachineLinking.System;
|
||||||
|
using Content.Server.Materials;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Recycling;
|
|
||||||
using Content.Server.Recycling.Components;
|
|
||||||
using Content.Shared.Conveyor;
|
using Content.Shared.Conveyor;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
@@ -18,7 +17,7 @@ namespace Content.Server.Physics.Controllers;
|
|||||||
public sealed class ConveyorController : SharedConveyorController
|
public sealed class ConveyorController : SharedConveyorController
|
||||||
{
|
{
|
||||||
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
[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 SignalLinkerSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
|
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
@@ -105,13 +104,7 @@ public sealed class ConveyorController : SharedConveyorController
|
|||||||
if (TryComp<PhysicsComponent>(uid, out var physics))
|
if (TryComp<PhysicsComponent>(uid, out var physics))
|
||||||
_broadphase.RegenerateContacts(physics);
|
_broadphase.RegenerateContacts(physics);
|
||||||
|
|
||||||
if (TryComp<RecyclerComponent>(uid, out var recycler))
|
_materialReclaimer.SetReclaimerEnabled(uid, component.State != ConveyorState.Off);
|
||||||
{
|
|
||||||
if (component.State != ConveyorState.Off)
|
|
||||||
_recycler.EnableRecycler(recycler);
|
|
||||||
else
|
|
||||||
_recycler.DisableRecycler(recycler);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateAppearance(uid, component);
|
UpdateAppearance(uid, component);
|
||||||
Dirty(component);
|
Dirty(component);
|
||||||
|
|||||||
@@ -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
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The prototype that will be spawned on recycle.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("prototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))] public string? Prototype;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The amount of things that will be spawned on recycle.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("amount")] public int Amount = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether this is "safe" to recycle or not.
|
|
||||||
/// If this is false, the recycler's safety must be disabled to recycle it.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("safe")]
|
|
||||||
public bool Safe { get; set; } = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The percentage of material that will be recovered
|
|
||||||
/// </summary>
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
[DataField("efficiency")]
|
|
||||||
internal float Efficiency = 0.25f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default sound to play when recycling
|
|
||||||
/// </summary>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<RecyclerComponent, ExaminedEvent>(OnExamined);
|
|
||||||
SubscribeLocalEvent<RecyclerComponent, StartCollideEvent>(OnCollide);
|
|
||||||
SubscribeLocalEvent<RecyclerComponent, GotEmaggedEvent>(OnEmagged);
|
|
||||||
SubscribeLocalEvent<RecyclerComponent, SuicideEvent>(OnSuicide);
|
|
||||||
SubscribeLocalEvent<RecyclerComponent, PowerChangedEvent>(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<BodyComponent?>(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<EmaggedComponent>(component.Owner)))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Prevent collision with recycled items
|
|
||||||
|
|
||||||
// Mobs are a special case!
|
|
||||||
if (CanGib(component, entity))
|
|
||||||
{
|
|
||||||
_bodySystem.GibBody(entity, true, Comp<BodyComponent>(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<BodyComponent>(entity) && HasComp<EmaggedComponent>(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -85,7 +85,7 @@ namespace Content.Shared.Lathe
|
|||||||
[DataField("partRatingMaterialUseMultiplier")]
|
[DataField("partRatingMaterialUseMultiplier")]
|
||||||
public float PartRatingMaterialUseMultiplier = DefaultPartRatingMaterialUseMultiplier;
|
public float PartRatingMaterialUseMultiplier = DefaultPartRatingMaterialUseMultiplier;
|
||||||
|
|
||||||
public const float DefaultPartRatingMaterialUseMultiplier = 0.75f;
|
public const float DefaultPartRatingMaterialUseMultiplier = 0.85f;
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
32
Content.Shared/Materials/ActiveMaterialReclaimerComponent.cs
Normal file
32
Content.Shared/Materials/ActiveMaterialReclaimerComponent.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
|
namespace Content.Shared.Materials;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tracker component for the process of reclaiming entities
|
||||||
|
/// <seealso cref="MaterialReclaimerComponent"/>
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedMaterialReclaimerSystem))]
|
||||||
|
public sealed class ActiveMaterialReclaimerComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Container used to store the item currently being reclaimed
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public Container ReclaimingContainer = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When the reclaiming process ends.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("endTime", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan EndTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The length of the reclaiming process.
|
||||||
|
/// Used for calculations.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("duration"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan Duration;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace Content.Shared.Materials;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Valid items that collide with an entity with this component
|
||||||
|
/// will begin to be reclaimed.
|
||||||
|
/// <seealso cref="MaterialReclaimerComponent"/>
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class CollideMaterialReclaimerComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The fixture that starts reclaiming on collision.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("fixtureId")]
|
||||||
|
public string FixtureId = "brrt";
|
||||||
|
}
|
||||||
177
Content.Shared/Materials/MaterialReclaimerComponent.cs
Normal file
177
Content.Shared/Materials/MaterialReclaimerComponent.cs
Normal file
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a machine that handles converting entities
|
||||||
|
/// into the raw materials and chemicals that make them up.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedMaterialReclaimerSystem))]
|
||||||
|
public sealed class MaterialReclaimerComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not the machine has power. We put it here
|
||||||
|
/// so we can network and predict it.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("powered"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool Powered;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An "enable" toggle for things like interfacing with machine linking
|
||||||
|
/// </summary>
|
||||||
|
[DataField("enabled"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool Enabled = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How efficiently the materials are reclaimed.
|
||||||
|
/// In practice, a multiplier per material when calculating the output of the reclaimer.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("efficiency"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float Efficiency = 1f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not the process
|
||||||
|
/// speed scales with the amount of materials being processed
|
||||||
|
/// or if it's just <see cref="MinimumProcessDuration"/>
|
||||||
|
/// </summary>
|
||||||
|
[DataField("scaleProcessSpeed")]
|
||||||
|
public bool ScaleProcessSpeed = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("baseMaterialProcessRate"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float BaseMaterialProcessRate = 100f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("materialProcessRate"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float MaterialProcessRate = 100f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Machine part whose rating modifies <see cref="MaterialProcessRate"/>
|
||||||
|
/// </summary>
|
||||||
|
[DataField("machinePartProcessRate", customTypeSerializer: typeof(PrototypeIdSerializer<MachinePartPrototype>)), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string MachinePartProcessRate = "Manipulator";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much the machine part quality affects the <see cref="MaterialProcessRate"/>
|
||||||
|
/// </summary>
|
||||||
|
[DataField("partRatingProcessRateMultiplier"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float PartRatingProcessRateMultiplier = 1.5f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum amount fo time it can take to process an entity.
|
||||||
|
/// this value supercedes the calculated one using <see cref="MaterialProcessRate"/>
|
||||||
|
/// </summary>
|
||||||
|
[DataField("minimumProcessDuration"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan MinimumProcessDuration = TimeSpan.FromSeconds(0.5f);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The id of our output solution
|
||||||
|
/// </summary>
|
||||||
|
[DataField("solutionContainerId"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string SolutionContainerId = "output";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The prototype for the puddle
|
||||||
|
/// </summary>
|
||||||
|
[DataField("puddleId", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>)), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string PuddleId = "PuddleSmear";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The solution itself.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public Solution OutputSolution = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a whitelist for what entities can be inserted into this reclaimer
|
||||||
|
/// </summary>
|
||||||
|
[DataField("whitelist")]
|
||||||
|
public EntityWhitelist? Whitelist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// a blacklist for what entities cannot be inserted into this reclaimer
|
||||||
|
/// </summary>
|
||||||
|
[DataField("blacklist")]
|
||||||
|
public EntityWhitelist? Blacklist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sound played when something is being processed.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("sound")]
|
||||||
|
public SoundSpecifier? Sound;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// whether or not we cut off the sound early when the reclaiming ends.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("cutOffSound")]
|
||||||
|
public bool CutOffSound = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When the next sound will be allowed to be played. Used to prevent spam.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("nextSound", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||||
|
public TimeSpan NextSound;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minimum time inbetween each <see cref="Sound"/>
|
||||||
|
/// </summary>
|
||||||
|
[DataField("soundCooldown")]
|
||||||
|
public TimeSpan SoundCooldown = TimeSpan.FromSeconds(0.8f);
|
||||||
|
|
||||||
|
public IPlayingAudioStream? Stream;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A counter of how many items have been processed
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// I saw this on the recycler and i'm porting it because it's cute af
|
||||||
|
/// </remarks>
|
||||||
|
[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
|
||||||
|
}
|
||||||
@@ -15,6 +15,12 @@ public sealed class MaterialStorageComponent : Component
|
|||||||
[DataField("storage", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MaterialPrototype>))]
|
[DataField("storage", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MaterialPrototype>))]
|
||||||
public Dictionary<string, int> Storage { get; set; } = new();
|
public Dictionary<string, int> Storage { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not interacting with the materialstorage inserts the material in hand.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("insertOnInteract")]
|
||||||
|
public bool InsertOnInteract = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How much material the storage can store in total.
|
/// How much material the storage can store in total.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
30
Content.Shared/Materials/PhysicalCompositionComponent.cs
Normal file
30
Content.Shared/Materials/PhysicalCompositionComponent.cs
Normal file
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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 <see cref="MaterialComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The reason for duel material/chemical is for the eventual
|
||||||
|
/// combination of the two systems.
|
||||||
|
/// </remarks>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class PhysicalCompositionComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The materials that "make up" this entity
|
||||||
|
/// </summary>
|
||||||
|
[DataField("materialComposition", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MaterialPrototype>))]
|
||||||
|
public Dictionary<string, int> MaterialComposition = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The chemicals that "make up" this entity
|
||||||
|
/// </summary>
|
||||||
|
[DataField("chemicalComposition", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<FixedPoint2, ReagentPrototype>))]
|
||||||
|
public Dictionary<string, FixedPoint2> ChemicalComposition = new();
|
||||||
|
}
|
||||||
249
Content.Shared/Materials/SharedMaterialReclaimerSystem.cs
Normal file
249
Content.Shared/Materials/SharedMaterialReclaimerSystem.cs
Normal file
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles interactions and logic related to <see cref="MaterialReclaimerComponent"/>,
|
||||||
|
/// <see cref="CollideMaterialReclaimerComponent"/>, and <see cref="ActiveMaterialReclaimerComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
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";
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, ComponentGetState>(OnGetState);
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, ComponentHandleState>(OnHandleState);
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, EntityUnpausedEvent>(OnUnpaused);
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, ExaminedEvent>(OnExamined);
|
||||||
|
SubscribeLocalEvent<MaterialReclaimerComponent, GotEmaggedEvent>(OnEmagged);
|
||||||
|
SubscribeLocalEvent<CollideMaterialReclaimerComponent, StartCollideEvent>(OnCollide);
|
||||||
|
SubscribeLocalEvent<ActiveMaterialReclaimerComponent, ComponentStartup>(OnActiveStartup);
|
||||||
|
SubscribeLocalEvent<ActiveMaterialReclaimerComponent, EntityUnpausedEvent>(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<MaterialReclaimerComponent>(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<Container>(uid, ActiveReclaimerContainerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnActiveUnpaused(EntityUid uid, ActiveMaterialReclaimerComponent component, ref EntityUnpausedEvent args)
|
||||||
|
{
|
||||||
|
component.EndTime += args.PausedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to start processing an item via a <see cref="MaterialReclaimerComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
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<MobStateComponent>(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<ActiveMaterialReclaimerComponent>(uid);
|
||||||
|
active.Duration = duration;
|
||||||
|
active.EndTime = Timing.CurTime + duration;
|
||||||
|
active.ReclaimingContainer.Insert(item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finishes processing an item, freeing up the the reclaimer.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This doesn't reclaim the entity itself, but rather ends the formal
|
||||||
|
/// process started with <see cref="ActiveMaterialReclaimerComponent"/>.
|
||||||
|
/// The actual reclaiming happens in <see cref="Reclaim"/>
|
||||||
|
/// </remarks>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spawns the materials and chemicals associated
|
||||||
|
/// with an entity. Also deletes the item.
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the Enabled field on the reclaimer.
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not the specified reclaimer can currently
|
||||||
|
/// begin reclaiming another entity.
|
||||||
|
/// </summary>
|
||||||
|
public bool CanStart(EntityUid uid, MaterialReclaimerComponent component)
|
||||||
|
{
|
||||||
|
if (HasComp<ActiveMaterialReclaimerComponent>(uid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return component.Powered && component.Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not the reclaimer satisfies the conditions
|
||||||
|
/// allowing it to gib/reclaim a living creature.
|
||||||
|
/// </summary>
|
||||||
|
public bool CanGib(EntityUid uid, EntityUid victim, MaterialReclaimerComponent component)
|
||||||
|
{
|
||||||
|
return component.Powered &&
|
||||||
|
component.Enabled &&
|
||||||
|
HasComp<BodyComponent>(victim) &&
|
||||||
|
HasComp<EmaggedComponent>(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
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<StackComponent>(item)?.Count ?? 1;
|
||||||
|
var duration = TimeSpan.FromSeconds(materialSum / reclaimerComponent.MaterialProcessRate);
|
||||||
|
if (duration < reclaimerComponent.MinimumProcessDuration)
|
||||||
|
duration = reclaimerComponent.MinimumProcessDuration;
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
var query = EntityQueryEnumerator<ActiveMaterialReclaimerComponent, MaterialReclaimerComponent>();
|
||||||
|
while (query.MoveNext(out var uid, out var active, out var reclaimer))
|
||||||
|
{
|
||||||
|
if (Timing.CurTime < active.EndTime)
|
||||||
|
continue;
|
||||||
|
TryFinishProcessItem(uid, reclaimer, active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -252,7 +252,7 @@ public abstract class SharedMaterialStorageSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnInteractUsing(EntityUid uid, MaterialStorageComponent component, InteractUsingEvent args)
|
private void OnInteractUsing(EntityUid uid, MaterialStorageComponent component, InteractUsingEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled)
|
if (args.Handled || !component.InsertOnInteract)
|
||||||
return;
|
return;
|
||||||
args.Handled = TryInsertMaterialEntity(args.User, args.Used, uid, component);
|
args.Handled = TryInsertMaterialEntity(args.User, args.Used, uid, component);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.Recycling
|
|
||||||
{
|
|
||||||
[NetSerializable, Serializable]
|
|
||||||
public enum RecyclerVisuals
|
|
||||||
{
|
|
||||||
Bloody
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
- files: ["anomaly_generator.ogg"]
|
- files: ["anomaly_generator.ogg"]
|
||||||
license: "CC0-1.0"
|
license: "CC0-1.0"
|
||||||
copyright: "Created by steaq, converted Mono and .ogg by EmoGarbage"
|
copyright: "Created by steaq, converted Mono and .ogg by EmoGarbage"
|
||||||
source: "https://freesound.org/people/steaq/sounds/509249/"
|
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/"
|
||||||
BIN
Resources/Audio/Ambience/Objects/crushing.ogg
Normal file
BIN
Resources/Audio/Ambience/Objects/crushing.ogg
Normal file
Binary file not shown.
@@ -18,3 +18,6 @@ materials-plasma = plasma
|
|||||||
materials-plastic = plastic
|
materials-plastic = plastic
|
||||||
materials-wood = wood
|
materials-wood = wood
|
||||||
materials-uranium = uranium
|
materials-uranium = uranium
|
||||||
|
|
||||||
|
# Material Reclaimer
|
||||||
|
material-reclaimer-upgrade-process-rate = process rate
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 25
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: LeftArmBorg
|
id: LeftArmBorg
|
||||||
@@ -36,7 +39,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- BorgArm
|
- BorgArm
|
||||||
- type: Recyclable
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: RightArmBorg
|
id: RightArmBorg
|
||||||
@@ -57,4 +59,3 @@
|
|||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- BorgArm
|
- BorgArm
|
||||||
- type: Recyclable
|
|
||||||
|
|||||||
@@ -364,6 +364,7 @@
|
|||||||
- SheetPlastic
|
- SheetPlastic
|
||||||
- SheetRGlass
|
- SheetRGlass
|
||||||
- SheetGlass1
|
- SheetGlass1
|
||||||
|
- MaterialReclaimerMachineCircuitboard
|
||||||
|
|
||||||
# Electromagnetic Theory Technology Tree
|
# Electromagnetic Theory Technology Tree
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,11 @@
|
|||||||
- type: Clothing
|
- type: Clothing
|
||||||
slots: [belt]
|
slots: [belt]
|
||||||
quickEquip: false
|
quickEquip: false
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Cloth: 50
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 25
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
abstract: true
|
abstract: true
|
||||||
|
|||||||
@@ -125,6 +125,9 @@
|
|||||||
sprite: Clothing/Head/Misc/cone.rsi
|
sprite: Clothing/Head/Misc/cone.rsi
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Head/Misc/cone.rsi
|
sprite: Clothing/Head/Misc/cone.rsi
|
||||||
|
- type: PhysicalComposition #you can't just pass up some free plastic!
|
||||||
|
materialComposition:
|
||||||
|
Plastic: 100
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingHeadBase
|
parent: ClothingHeadBase
|
||||||
|
|||||||
@@ -8,6 +8,12 @@
|
|||||||
- type: FlashImmunity
|
- type: FlashImmunity
|
||||||
- type: IdentityBlocker
|
- type: IdentityBlocker
|
||||||
- type: EyeProtection
|
- type: EyeProtection
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 500
|
||||||
|
Glass: 100
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 50
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: WeldingMaskBase
|
parent: WeldingMaskBase
|
||||||
|
|||||||
@@ -137,7 +137,10 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- PetWearable
|
- PetWearable
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 50
|
||||||
|
Plastic: 100
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingMaskBase
|
parent: ClothingMaskBase
|
||||||
|
|||||||
@@ -259,6 +259,10 @@
|
|||||||
sprintModifier: 0.75
|
sprintModifier: 0.75
|
||||||
- type: Item
|
- type: Item
|
||||||
size: 100
|
size: 100
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- WhitelistChameleon
|
||||||
|
- HighRiskItem
|
||||||
- type: ExplosionResistance
|
- type: ExplosionResistance
|
||||||
damageCoefficient: 0.1
|
damageCoefficient: 0.1
|
||||||
- type: ToggleableClothing
|
- type: ToggleableClothing
|
||||||
|
|||||||
@@ -58,6 +58,10 @@
|
|||||||
sprintModifier: 1
|
sprintModifier: 1
|
||||||
enabled: false
|
enabled: false
|
||||||
- type: NoSlip
|
- type: NoSlip
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- WhitelistChameleon
|
||||||
|
- HighRiskItem
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 750
|
price: 750
|
||||||
|
|
||||||
|
|||||||
@@ -824,7 +824,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- CannotSuicide
|
- CannotSuicide
|
||||||
- type: Recyclable
|
|
||||||
- type: Respirator
|
- type: Respirator
|
||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
@@ -1997,7 +1996,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- CannotSuicide
|
- CannotSuicide
|
||||||
- type: Recyclable
|
|
||||||
- type: Respirator
|
- type: Respirator
|
||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
|
|||||||
@@ -38,8 +38,6 @@
|
|||||||
noRot: true
|
noRot: true
|
||||||
drawdepth: Mobs
|
drawdepth: Mobs
|
||||||
netsync: false
|
netsync: false
|
||||||
- type: Recyclable
|
|
||||||
safe: false
|
|
||||||
- type: Faction
|
- type: Faction
|
||||||
factions:
|
factions:
|
||||||
- SimpleNeutral
|
- SimpleNeutral
|
||||||
|
|||||||
@@ -139,8 +139,6 @@
|
|||||||
- type: Polymorphable
|
- type: Polymorphable
|
||||||
- type: Pullable
|
- type: Pullable
|
||||||
- type: Buckle
|
- type: Buckle
|
||||||
- type: Recyclable
|
|
||||||
safe: false
|
|
||||||
- type: StandingState
|
- type: StandingState
|
||||||
- type: Alerts
|
- type: Alerts
|
||||||
- type: NameIdentifier
|
- type: NameIdentifier
|
||||||
|
|||||||
@@ -56,8 +56,6 @@
|
|||||||
- type: Pullable
|
- type: Pullable
|
||||||
- type: Examiner
|
- type: Examiner
|
||||||
- type: Puller
|
- type: Puller
|
||||||
- type: Recyclable
|
|
||||||
safe: false
|
|
||||||
- type: StandingState
|
- type: StandingState
|
||||||
- type: Alerts
|
- type: Alerts
|
||||||
- type: Tag
|
- type: Tag
|
||||||
|
|||||||
@@ -280,8 +280,6 @@
|
|||||||
spawned:
|
spawned:
|
||||||
- id: FoodMeat
|
- id: FoodMeat
|
||||||
amount: 5
|
amount: 5
|
||||||
# - type: Recyclable Turns out turning off recycler safeties without considering the instagib is a bad idea
|
|
||||||
# safe: false
|
|
||||||
- type: Speech
|
- type: Speech
|
||||||
speechSounds: Alto
|
speechSounds: Alto
|
||||||
- type: Vocal
|
- type: Vocal
|
||||||
|
|||||||
@@ -72,6 +72,9 @@
|
|||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
Blunt: 5
|
Blunt: 5
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 25
|
||||||
|
|
||||||
# Transformable container - normal glass
|
# Transformable container - normal glass
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -2164,7 +2167,6 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -51,10 +51,12 @@
|
|||||||
types:
|
types:
|
||||||
Blunt: 0
|
Blunt: 0
|
||||||
- type: ItemCooldown
|
- type: ItemCooldown
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: TrashOnEmpty
|
- type: TrashOnEmpty
|
||||||
solution: drink
|
solution: drink
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 50 #reduce, reuse, recycle
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: DrinkCanBaseFull
|
parent: DrinkCanBaseFull
|
||||||
|
|||||||
@@ -66,6 +66,9 @@
|
|||||||
- type: SolutionContainerVisuals
|
- type: SolutionContainerVisuals
|
||||||
maxFillLevels: 3
|
maxFillLevels: 3
|
||||||
fillBaseName: icon-
|
fillBaseName: icon-
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 25
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: DrinkBaseMug
|
parent: DrinkBaseMug
|
||||||
@@ -130,6 +133,9 @@
|
|||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Consumable/Drinks/mug_metal.rsi
|
sprite: Objects/Consumable/Drinks/mug_metal.rsi
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 25
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: DrinkBaseMug
|
parent: DrinkBaseMug
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
- type: Drink
|
- type: Drink
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Consumable/Drinks/shinyflask.rsi
|
sprite: Objects/Consumable/Drinks/shinyflask.rsi
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 50
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: DrinkBase
|
parent: DrinkBase
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
interfaces:
|
interfaces:
|
||||||
- key: enum.TransferAmountUiKey.Key
|
- key: enum.TransferAmountUiKey.Key
|
||||||
type: TransferAmountBoundUserInterface
|
type: TransferAmountBoundUserInterface
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 50
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: DrinkGlassBase
|
parent: DrinkGlassBase
|
||||||
|
|||||||
@@ -68,7 +68,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 100
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
# Containers
|
# Containers
|
||||||
|
|||||||
@@ -69,7 +69,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 50
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 0
|
price: 0
|
||||||
|
|||||||
@@ -45,7 +45,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 100
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -61,7 +63,6 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
# Small Plate
|
# Small Plate
|
||||||
@@ -147,5 +148,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|||||||
@@ -28,6 +28,9 @@
|
|||||||
Blunt: 3
|
Blunt: 3
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
abstract: true
|
abstract: true
|
||||||
@@ -46,6 +49,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
# Tins
|
# Tins
|
||||||
|
|
||||||
# Need something that you can open these tins with. I suggest a prying or cutting tool.
|
# Need something that you can open these tins with. I suggest a prying or cutting tool.
|
||||||
|
|||||||
@@ -110,7 +110,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Egg
|
- Egg
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
# Egg
|
# Egg
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
flavors:
|
flavors:
|
||||||
- food
|
- food
|
||||||
- type: Food
|
- type: Food
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: false
|
netsync: false
|
||||||
|
|||||||
@@ -275,5 +275,4 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|||||||
@@ -225,6 +225,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Raw
|
- Raw
|
||||||
|
- HighRiskItem
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
state: corgi
|
state: corgi
|
||||||
- type: SolutionContainerManager
|
- type: SolutionContainerManager
|
||||||
|
|||||||
@@ -213,7 +213,6 @@
|
|||||||
Quantity: 4
|
Quantity: 4
|
||||||
- type: Extractable
|
- type: Extractable
|
||||||
grindableSolutionName: food
|
grindableSolutionName: food
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -387,7 +387,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 0
|
price: 0
|
||||||
|
|||||||
@@ -24,7 +24,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Plastic: 50
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Cigarette
|
- Cigarette
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Objects/Consumable/Smokeables/Cigarettes/cigarette.rsi
|
sprite: Objects/Consumable/Smokeables/Cigarettes/cigarette.rsi
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Cigarette
|
- Cigarette
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Objects/Consumable/Smokeables/Cannabis/joint.rsi
|
sprite: Objects/Consumable/Smokeables/Cannabis/joint.rsi
|
||||||
@@ -45,7 +44,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Cigarette
|
- Cigarette
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Objects/Consumable/Smokeables/Cannabis/blunt.rsi
|
sprite: Objects/Consumable/Smokeables/Cannabis/blunt.rsi
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
tags:
|
tags:
|
||||||
- CigPack
|
- CigPack
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 50
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: Storage
|
- type: Storage
|
||||||
capacity: 6
|
capacity: 6
|
||||||
|
|||||||
@@ -59,7 +59,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- RollingPaper
|
- RollingPaper
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -90,7 +89,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- CigFilter
|
- CigFilter
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: CigaretteFilter1
|
id: CigaretteFilter1
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 5
|
price: 5
|
||||||
@@ -50,14 +49,14 @@
|
|||||||
bowl_slot: !type:ContainerSlot
|
bowl_slot: !type:ContainerSlot
|
||||||
- type: ItemSlots
|
- type: ItemSlots
|
||||||
- type: SmokingPipe
|
- type: SmokingPipe
|
||||||
bowl_slot:
|
bowl_slot:
|
||||||
name: Bowl
|
name: Bowl
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
- Smokable
|
- Smokable
|
||||||
insertSound:
|
insertSound:
|
||||||
path: /Audio/Weapons/Guns/Empty/empty.ogg
|
path: /Audio/Weapons/Guns/Empty/empty.ogg
|
||||||
ejectSound:
|
ejectSound:
|
||||||
path: /Audio/Weapons/Guns/Empty/empty.ogg
|
path: /Audio/Weapons/Guns/Empty/empty.ogg
|
||||||
- type: SolutionContainerManager
|
- type: SolutionContainerManager
|
||||||
solutions:
|
solutions:
|
||||||
|
|||||||
@@ -376,5 +376,4 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|||||||
@@ -14,3 +14,9 @@
|
|||||||
- DroneUsable
|
- DroneUsable
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 100
|
price: 100
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 400
|
||||||
|
chemicalComposition:
|
||||||
|
Silicon: 20
|
||||||
|
|
||||||
|
|||||||
@@ -466,6 +466,11 @@
|
|||||||
materialRequirements:
|
materialRequirements:
|
||||||
CableMV: 5
|
CableMV: 5
|
||||||
CableHV: 5
|
CableHV: 5
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 200
|
||||||
|
chemicalComposition:
|
||||||
|
Silicon: 20
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseMachineCircuitboard
|
parent: BaseMachineCircuitboard
|
||||||
@@ -515,6 +520,11 @@
|
|||||||
Capacitor: 1
|
Capacitor: 1
|
||||||
materialRequirements:
|
materialRequirements:
|
||||||
CableHV: 5
|
CableHV: 5
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 200
|
||||||
|
chemicalComposition:
|
||||||
|
Silicon: 20
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ThrusterMachineCircuitboard
|
id: ThrusterMachineCircuitboard
|
||||||
@@ -555,6 +565,11 @@
|
|||||||
Capacitor: 2
|
Capacitor: 2
|
||||||
materialRequirements:
|
materialRequirements:
|
||||||
CableHV: 10
|
CableHV: 10
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 200
|
||||||
|
chemicalComposition:
|
||||||
|
Silicon: 20
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ReagentGrinderMachineCircuitboard
|
id: ReagentGrinderMachineCircuitboard
|
||||||
@@ -611,6 +626,21 @@
|
|||||||
DefaultPrototype: CryostasisBeaker
|
DefaultPrototype: CryostasisBeaker
|
||||||
ExamineName: Cryostasis Beaker
|
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
|
- type: entity
|
||||||
id: OreProcessorMachineCircuitboard
|
id: OreProcessorMachineCircuitboard
|
||||||
parent: BaseMachineCircuitboard
|
parent: BaseMachineCircuitboard
|
||||||
@@ -726,7 +756,7 @@
|
|||||||
materialRequirements:
|
materialRequirements:
|
||||||
Steel: 10
|
Steel: 10
|
||||||
Plasma: 5
|
Plasma: 5
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: BoozeDispenserMachineCircuitboard
|
id: BoozeDispenserMachineCircuitboard
|
||||||
parent: BaseMachineCircuitboard
|
parent: BaseMachineCircuitboard
|
||||||
@@ -766,7 +796,7 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
id: TelecomServerCircuitboard
|
id: TelecomServerCircuitboard
|
||||||
parent: BaseMachineCircuitboard
|
parent: BaseMachineCircuitboard
|
||||||
name: telecommunication server machine board
|
name: telecommunication server machine board
|
||||||
description: A machine printed circuit board for an telecommunication server.
|
description: A machine printed circuit board for an telecommunication server.
|
||||||
components:
|
components:
|
||||||
- type: MachineBoard
|
- type: MachineBoard
|
||||||
|
|||||||
@@ -13,6 +13,11 @@
|
|||||||
- DroneUsable
|
- DroneUsable
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 100
|
price: 100
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 400
|
||||||
|
chemicalComposition:
|
||||||
|
Silicon: 20
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputerCircuitboard
|
parent: BaseComputerCircuitboard
|
||||||
@@ -68,6 +73,10 @@
|
|||||||
prototype: ComputerCargoOrders
|
prototype: ComputerCargoOrders
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 750
|
price: 750
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- DroneUsable
|
||||||
|
- HighRiskItem
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputerCircuitboard
|
parent: BaseComputerCircuitboard
|
||||||
@@ -178,6 +187,10 @@
|
|||||||
prototype: ComputerId
|
prototype: ComputerId
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 750
|
price: 750
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- DroneUsable
|
||||||
|
- HighRiskItem
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputerCircuitboard
|
parent: BaseComputerCircuitboard
|
||||||
|
|||||||
@@ -14,3 +14,8 @@
|
|||||||
- DroneUsable
|
- DroneUsable
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 100
|
price: 100
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 200
|
||||||
|
chemicalComposition:
|
||||||
|
Silicon: 20
|
||||||
|
|||||||
@@ -10,6 +10,11 @@
|
|||||||
sprite: Objects/Misc/module.rsi
|
sprite: Objects/Misc/module.rsi
|
||||||
state: charger_APC
|
state: charger_APC
|
||||||
netsync: false
|
netsync: false
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 50
|
||||||
|
chemicalComposition:
|
||||||
|
Silicon: 20
|
||||||
|
|
||||||
# Wallmount Substation
|
# Wallmount Substation
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -9,3 +9,6 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: icon
|
- state: icon
|
||||||
- type: HandTeleporter
|
- type: HandTeleporter
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HighRiskItem
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
- Write
|
- Write
|
||||||
- Crayon
|
- Crayon
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
|
|||||||
@@ -26,6 +26,11 @@
|
|||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
Blunt: 0
|
Blunt: 0
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Cloth: 100
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 5
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BasePlushie
|
parent: BasePlushie
|
||||||
@@ -243,7 +248,6 @@
|
|||||||
- type: Sprite
|
- type: Sprite
|
||||||
state: narplush
|
state: narplush
|
||||||
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BasePlushie
|
parent: BasePlushie
|
||||||
id: PlushieCarp
|
id: PlushieCarp
|
||||||
@@ -356,55 +360,66 @@
|
|||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
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
|
id: ToyAi
|
||||||
name: AI toy
|
name: AI toy
|
||||||
description: A scaled-down toy AI core.
|
description: A scaled-down toy AI core.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: AI
|
state: AI
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyNuke
|
id: ToyNuke
|
||||||
name: nuke toy
|
name: nuke toy
|
||||||
description: A plastic model of a Nuclear Fission Explosive. No uranium included... probably.
|
description: A plastic model of a Nuclear Fission Explosive. No uranium included... probably.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: nuketoy
|
state: nuketoy
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyAssistant # TODO rename but needs map changes
|
id: ToyAssistant # TODO rename but needs map changes
|
||||||
name: passenger toy
|
name: passenger toy
|
||||||
description: Grey tide world wide!
|
description: Grey tide world wide!
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: doll
|
state: doll
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Fun/toys.rsi
|
sprite: Objects/Fun/toys.rsi
|
||||||
heldPrefix: doll
|
heldPrefix: doll
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyGriffin
|
id: ToyGriffin
|
||||||
name: griffin toy
|
name: griffin toy
|
||||||
description: An action figure modeled after 'The Griffin', criminal mastermind.
|
description: An action figure modeled after 'The Griffin', criminal mastermind.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: griffinprize
|
state: griffinprize
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyHonk
|
id: ToyHonk
|
||||||
name: H.O.N.K. toy
|
name: H.O.N.K. toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 6/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 6/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: honkprize
|
state: honkprize
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -423,125 +438,111 @@
|
|||||||
path: /Audio/Items/Toys/ian.ogg
|
path: /Audio/Items/Toys/ian.ogg
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyMarauder
|
id: ToyMarauder
|
||||||
name: marauder toy
|
name: marauder toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 7/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 7/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: marauderprize
|
state: marauderprize
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyMauler
|
id: ToyMauler
|
||||||
name: mauler toy
|
name: mauler toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 9/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 9/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: maulerprize
|
state: maulerprize
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyGygax
|
id: ToyGygax
|
||||||
name: gygax toy
|
name: gygax toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 4/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 4/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: gygaxtoy
|
state: gygaxtoy
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyOdysseus
|
id: ToyOdysseus
|
||||||
name: odysseus toy
|
name: odysseus toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 10/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 10/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: odysseusprize
|
state: odysseusprize
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyOwlman
|
id: ToyOwlman
|
||||||
name: owl toy
|
name: owl toy
|
||||||
description: An action figure modeled after 'The Owl', defender of justice.
|
description: An action figure modeled after 'The Owl', defender of justice.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: owlprize
|
state: owlprize
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyDeathRipley
|
id: ToyDeathRipley
|
||||||
name: deathripley toy
|
name: deathripley toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 3/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 3/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: deathripleytoy
|
state: deathripleytoy
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyPhazon
|
id: ToyPhazon
|
||||||
name: phazon toy
|
name: phazon toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 11/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 11/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: phazonprize
|
state: phazonprize
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyFireRipley
|
id: ToyFireRipley
|
||||||
name: fire ripley
|
name: fire ripley
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 2/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 2/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: fireripleytoy
|
state: fireripleytoy
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyReticence
|
id: ToyReticence
|
||||||
name: reticence toy
|
name: reticence toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 12/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 12/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: reticenceprize
|
state: reticenceprize
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyRipley
|
id: ToyRipley
|
||||||
name: ripley toy
|
name: ripley toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 1/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 1/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: ripleytoy
|
state: ripleytoy
|
||||||
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToySeraph
|
id: ToySeraph
|
||||||
name: seraph toy
|
name: seraph toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 8/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 8/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: seraphprize
|
state: seraphprize
|
||||||
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToyDurand
|
id: ToyDurand
|
||||||
name: durand toy
|
name: durand toy
|
||||||
description: Mini-Mecha action figure! 'Mecha No. 5/12' is written on the back.
|
description: Mini-Mecha action figure! 'Mecha No. 5/12' is written on the back.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: durandprize
|
state: durandprize
|
||||||
|
|
||||||
|
|
||||||
@@ -549,13 +550,12 @@
|
|||||||
### Help i'm sorting these and my previous self let this message here to taunt me aaaaa
|
### Help i'm sorting these and my previous self let this message here to taunt me aaaaa
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseFigurine
|
||||||
id: ToySkeleton
|
id: ToySkeleton
|
||||||
name: skeleton toy
|
name: skeleton toy
|
||||||
description: Spooked ya!
|
description: Spooked ya!
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
|
||||||
state: skeletonprize
|
state: skeletonprize
|
||||||
|
|
||||||
## Toyweapons
|
## Toyweapons
|
||||||
@@ -843,8 +843,6 @@
|
|||||||
available:
|
available:
|
||||||
- enum.DamageStateVisualLayers.Base:
|
- enum.DamageStateVisualLayers.Base:
|
||||||
base: Sixteen
|
base: Sixteen
|
||||||
- type: StaticPrice
|
|
||||||
price: 3
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseItem
|
parent: BaseItem
|
||||||
|
|||||||
@@ -51,8 +51,6 @@
|
|||||||
- type: Material
|
- type: Material
|
||||||
materials:
|
materials:
|
||||||
Glass: 100
|
Glass: 100
|
||||||
- type: StackPrice
|
|
||||||
price: 5
|
|
||||||
- type: Stack
|
- type: Stack
|
||||||
stackType: Glass
|
stackType: Glass
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
|
|||||||
@@ -20,3 +20,8 @@
|
|||||||
node: boxcardboard
|
node: boxcardboard
|
||||||
containers:
|
containers:
|
||||||
- entity_storage
|
- entity_storage
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Cardboard: 100
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 10
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 50
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
- type: WarpPoint
|
- type: WarpPoint
|
||||||
follow: true
|
follow: true
|
||||||
location: nuke disk
|
location: nuke disk
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HighRiskItem
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: nuclear authentication disk
|
name: nuclear authentication disk
|
||||||
|
|||||||
@@ -90,10 +90,12 @@
|
|||||||
components:
|
components:
|
||||||
- type: Item
|
- type: Item
|
||||||
size: 2
|
size: 2
|
||||||
- type: Recyclable
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Plastic: 25
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: broken zipties
|
name: broken zipties
|
||||||
@@ -114,4 +116,4 @@
|
|||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Misc/cablecuffs.rsi
|
sprite: Objects/Misc/cablecuffs.rsi
|
||||||
state: cuff-broken
|
state: cuff-broken
|
||||||
color: forestgreen
|
color: forestgreen
|
||||||
|
|||||||
@@ -107,6 +107,10 @@
|
|||||||
heldPrefix: gold
|
heldPrefix: gold
|
||||||
- type: PresetIdCard
|
- type: PresetIdCard
|
||||||
job: Captain
|
job: Captain
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- WhitelistChameleon
|
||||||
|
- HighRiskItem
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: IDCardStandard
|
parent: IDCardStandard
|
||||||
@@ -548,7 +552,7 @@
|
|||||||
- state: idzookeeper
|
- state: idzookeeper
|
||||||
- type: PresetIdCard
|
- type: PresetIdCard
|
||||||
job: Zookeeper
|
job: Zookeeper
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: IDCardStandard
|
parent: IDCardStandard
|
||||||
id: DetectiveIDCard
|
id: DetectiveIDCard
|
||||||
@@ -572,7 +576,7 @@
|
|||||||
- state: idcentcom
|
- state: idcentcom
|
||||||
- type: Item
|
- type: Item
|
||||||
heldPrefix: gold
|
heldPrefix: gold
|
||||||
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: IDCardStandard
|
parent: IDCardStandard
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
- Trash
|
- Trash
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: PaperVisuals
|
- type: PaperVisuals
|
||||||
- type: Recyclable
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: office paper
|
name: office paper
|
||||||
@@ -182,7 +181,9 @@
|
|||||||
sprite: Objects/Misc/bureaucracy.rsi
|
sprite: Objects/Misc/bureaucracy.rsi
|
||||||
heldPrefix: pen
|
heldPrefix: pen
|
||||||
size: 2
|
size: 2
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 25
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: Cybersun pen
|
name: Cybersun pen
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -60,7 +60,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 25
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -43,11 +43,11 @@
|
|||||||
- !type:SpawnEntitiesBehavior
|
- !type:SpawnEntitiesBehavior
|
||||||
spawn:
|
spawn:
|
||||||
SheetSteel:
|
SheetSteel:
|
||||||
min: 5
|
min: 2
|
||||||
max: 5
|
max: 2
|
||||||
SheetGlass:
|
SheetGlass:
|
||||||
min: 5
|
min: 2
|
||||||
max: 5
|
max: 2
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 50
|
price: 50
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
delay: 0.5
|
delay: 0.5
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 750
|
price: 750
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HighRiskItem
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: gorlex hypospray
|
name: gorlex hypospray
|
||||||
@@ -78,7 +81,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Plastic: 50
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 75 # These are limited supply items.
|
price: 75 # These are limited supply items.
|
||||||
|
|||||||
@@ -32,3 +32,7 @@
|
|||||||
- DroneUsable
|
- DroneUsable
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 80
|
price: 80
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 400
|
||||||
|
Glass: 100
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
tags:
|
tags:
|
||||||
- Bottle
|
- Bottle
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Glass: 25
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Specific/Chemistry/bottle.rsi
|
sprite: Objects/Specific/Chemistry/bottle.rsi
|
||||||
|
|||||||
@@ -58,3 +58,6 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Bucket
|
- Bucket
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Plastic: 50
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Flare
|
- Flare
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: ExpendableLight
|
- type: ExpendableLight
|
||||||
spentName: expendable-light-spent-flare-name
|
spentName: expendable-light-spent-flare-name
|
||||||
|
|||||||
@@ -35,6 +35,11 @@
|
|||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
Blunt: 10
|
Blunt: 10
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 400
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 20
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: GasTankBase
|
parent: GasTankBase
|
||||||
@@ -109,6 +114,9 @@
|
|||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
Blunt: 5
|
Blunt: 5
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: EmergencyOxygenTank
|
parent: EmergencyOxygenTank
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
id: GlowstickBase
|
id: GlowstickBase
|
||||||
description: Useful for raves and emergencies.
|
description: Useful for raves and emergencies.
|
||||||
components:
|
components:
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: ExpendableLight
|
- type: ExpendableLight
|
||||||
spentName: expendable-light-spent-green-glowstick-name
|
spentName: expendable-light-spent-green-glowstick-name
|
||||||
|
|||||||
@@ -147,6 +147,9 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tanks/Jetpacks/captain.rsi
|
sprite: Objects/Tanks/Jetpacks/captain.rsi
|
||||||
size: 30
|
size: 30
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HighRiskItem
|
||||||
|
|
||||||
# Filled captain
|
# Filled captain
|
||||||
- type: entity
|
- type: entity
|
||||||
@@ -248,7 +251,7 @@
|
|||||||
sprite: Objects/Tanks/Jetpacks/void.rsi
|
sprite: Objects/Tanks/Jetpacks/void.rsi
|
||||||
slots:
|
slots:
|
||||||
- Back
|
- Back
|
||||||
- suitStorage
|
- suitStorage
|
||||||
|
|
||||||
# Filled void
|
# Filled void
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
tags:
|
tags:
|
||||||
- Matchstick
|
- Matchstick
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: false
|
netsync: false
|
||||||
@@ -94,5 +93,4 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Trash
|
- Trash
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|||||||
@@ -35,6 +35,9 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/wirecutters.rsi
|
sprite: Objects/Tools/wirecutters.rsi
|
||||||
- type: LatticeCutting
|
- type: LatticeCutting
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 40
|
price: 40
|
||||||
|
|
||||||
@@ -74,6 +77,9 @@
|
|||||||
available:
|
available:
|
||||||
- enum.DamageStateVisualLayers.Base:
|
- enum.DamageStateVisualLayers.Base:
|
||||||
screwdriver: Rainbow
|
screwdriver: Rainbow
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 40
|
price: 40
|
||||||
|
|
||||||
@@ -106,6 +112,9 @@
|
|||||||
- Anchoring
|
- Anchoring
|
||||||
useSound:
|
useSound:
|
||||||
path: /Audio/Items/ratchet.ogg
|
path: /Audio/Items/ratchet.ogg
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 40
|
price: 40
|
||||||
|
|
||||||
@@ -139,6 +148,9 @@
|
|||||||
useSound:
|
useSound:
|
||||||
path: /Audio/Items/crowbar.ogg
|
path: /Audio/Items/crowbar.ogg
|
||||||
- type: TilePrying
|
- type: TilePrying
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 40
|
price: 40
|
||||||
|
|
||||||
@@ -200,6 +212,10 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- DroneUsable
|
- DroneUsable
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
|
Plastic: 100
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 60
|
price: 60
|
||||||
|
|
||||||
@@ -242,6 +258,10 @@
|
|||||||
path: /Audio/Items/drill_use.ogg
|
path: /Audio/Items/drill_use.ogg
|
||||||
changeSound:
|
changeSound:
|
||||||
path: /Audio/Items/change_drill.ogg
|
path: /Audio/Items/change_drill.ogg
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 300
|
||||||
|
Plastic: 100
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 100
|
price: 100
|
||||||
|
|
||||||
@@ -264,6 +284,10 @@
|
|||||||
quickEquip: false
|
quickEquip: false
|
||||||
slots:
|
slots:
|
||||||
- Belt
|
- Belt
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 600
|
||||||
|
Plastic: 100
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 100
|
price: 100
|
||||||
|
|
||||||
@@ -288,6 +312,10 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/rcd.rsi
|
sprite: Objects/Tools/rcd.rsi
|
||||||
heldPrefix: ammo
|
heldPrefix: ammo
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
|
Plastic: 100
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 60
|
price: 60
|
||||||
|
|
||||||
@@ -310,6 +338,12 @@
|
|||||||
Blunt: 10
|
Blunt: 10
|
||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/shovel.rsi
|
sprite: Objects/Tools/shovel.rsi
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 100
|
||||||
|
Wood: 50
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 25
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: omnitool
|
name: omnitool
|
||||||
|
|||||||
@@ -60,6 +60,9 @@
|
|||||||
color: orange
|
color: orange
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: RequiresEyeProtection
|
- type: RequiresEyeProtection
|
||||||
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 200
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 40
|
price: 40
|
||||||
- type: IgnitionSource
|
- type: IgnitionSource
|
||||||
|
|||||||
@@ -11,5 +11,4 @@
|
|||||||
- Cartridge
|
- Cartridge
|
||||||
- type: Item
|
- type: Item
|
||||||
size: 1
|
size: 1
|
||||||
- type: Recyclable
|
|
||||||
- type: SpaceGarbage
|
- type: SpaceGarbage
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- BulletFoam
|
- BulletFoam
|
||||||
|
- Trash
|
||||||
- type: Ammo
|
- type: Ammo
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Fun/toys.rsi
|
sprite: Objects/Fun/toys.rsi
|
||||||
layers:
|
layers:
|
||||||
- state: foamdart
|
- state: foamdart
|
||||||
- type: Recyclable
|
|
||||||
@@ -390,6 +390,9 @@
|
|||||||
steps: 5
|
steps: 5
|
||||||
zeroVisible: true
|
zeroVisible: true
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HighRiskItem
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 750
|
price: 750
|
||||||
|
|
||||||
|
|||||||
@@ -306,6 +306,7 @@
|
|||||||
- DawInstrumentMachineCircuitboard
|
- DawInstrumentMachineCircuitboard
|
||||||
- CloningConsoleComputerCircuitboard
|
- CloningConsoleComputerCircuitboard
|
||||||
- StasisBedMachineCircuitboard
|
- StasisBedMachineCircuitboard
|
||||||
|
- MaterialReclaimerMachineCircuitboard
|
||||||
- OreProcessorMachineCircuitboard
|
- OreProcessorMachineCircuitboard
|
||||||
- RipleyCentralElectronics
|
- RipleyCentralElectronics
|
||||||
- RipleyPeripheralsElectronics
|
- RipleyPeripheralsElectronics
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -11,12 +11,11 @@
|
|||||||
sound:
|
sound:
|
||||||
# TODO: https://freesound.org/people/derjuli/sounds/448133/ CC-NC-
|
# TODO: https://freesound.org/people/derjuli/sounds/448133/ CC-NC-
|
||||||
path: /Audio/Ambience/Objects/circular_saw.ogg
|
path: /Audio/Ambience/Objects/circular_saw.ogg
|
||||||
- type: Physics
|
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
fixtures:
|
fixtures:
|
||||||
- shape:
|
- shape:
|
||||||
!type:PhysShapeAabb
|
!type:PhysShapeAabb
|
||||||
bounds: "-0.2,-0.2,0.2,0.2"
|
bounds: "-0.15,-0.15,0.15,0.15"
|
||||||
id: brrt
|
id: brrt
|
||||||
hard: false
|
hard: false
|
||||||
layer:
|
layer:
|
||||||
@@ -58,11 +57,58 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: grinder-o0
|
- state: grinder-o0
|
||||||
map: ["enum.RecyclerVisualLayers.Main"]
|
map: ["enum.RecyclerVisualLayers.Main"]
|
||||||
|
- state: grinder-o0bld
|
||||||
|
map: ["enum.RecyclerVisualLayers.Bloody"]
|
||||||
|
visible: false
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
|
- type: GenericVisualizer
|
||||||
visuals:
|
visuals:
|
||||||
- type: RecyclerVisualizer
|
enum.RecyclerVisuals.Bloody:
|
||||||
state_on: grinder-o1
|
enum.RecyclerVisualLayers.Main:
|
||||||
state_off: grinder-o0
|
True: { visible: false }
|
||||||
- type: Recycler
|
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: Conveyor
|
||||||
- type: Rotatable
|
- type: Rotatable
|
||||||
@@ -608,7 +608,9 @@
|
|||||||
- MachineMask
|
- MachineMask
|
||||||
layer:
|
layer:
|
||||||
- MachineLayer
|
- MachineLayer
|
||||||
- type: Recyclable
|
- type: PhysicalComposition
|
||||||
|
materialComposition:
|
||||||
|
Steel: 500
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 60
|
price: 60
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@
|
|||||||
graph: WindowDirectional
|
graph: WindowDirectional
|
||||||
node: windowDirectional
|
node: windowDirectional
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 5
|
price: 10
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: WindowTintedDirectional
|
id: WindowTintedDirectional
|
||||||
@@ -193,8 +193,6 @@
|
|||||||
state: tinted_window
|
state: tinted_window
|
||||||
- type: Occluder
|
- type: Occluder
|
||||||
boundingBox: "-0.5,-0.5,0.5,-0.3"
|
boundingBox: "-0.5,-0.5,0.5,-0.3"
|
||||||
- type: StaticPrice
|
|
||||||
price: 5
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: WindowFrostedDirectional
|
id: WindowFrostedDirectional
|
||||||
@@ -213,5 +211,3 @@
|
|||||||
- type: Icon
|
- type: Icon
|
||||||
sprite: Structures/Windows/directional.rsi
|
sprite: Structures/Windows/directional.rsi
|
||||||
state: frosted_window
|
state: frosted_window
|
||||||
- type: StaticPrice
|
|
||||||
price: 5
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
name: materials-cardboard
|
name: materials-cardboard
|
||||||
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cardboard }
|
icon: { sprite: /Textures/Objects/Materials/materials.rsi, state: cardboard }
|
||||||
color: "#70736c"
|
color: "#70736c"
|
||||||
price: 0.05
|
price: 0.005
|
||||||
|
|
||||||
- type: material
|
- type: material
|
||||||
id: Cloth
|
id: Cloth
|
||||||
|
|||||||
@@ -292,6 +292,14 @@
|
|||||||
Glass: 900
|
Glass: 900
|
||||||
Gold: 100
|
Gold: 100
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: MaterialReclaimerMachineCircuitboard
|
||||||
|
result: MaterialReclaimerMachineCircuitboard
|
||||||
|
completetime: 4
|
||||||
|
materials:
|
||||||
|
Steel: 100
|
||||||
|
Glass: 900
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: OreProcessorMachineCircuitboard
|
id: OreProcessorMachineCircuitboard
|
||||||
result: OreProcessorMachineCircuitboard
|
result: OreProcessorMachineCircuitboard
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
result: Bucket
|
result: Bucket
|
||||||
completetime: 2
|
completetime: 2
|
||||||
materials:
|
materials:
|
||||||
Steel: 100
|
Plastic: 100
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: WetFloorSign
|
id: WetFloorSign
|
||||||
|
|||||||
@@ -302,6 +302,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: HidesHair # for headwear.
|
id: HidesHair # for headwear.
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: HighRiskItem
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: Hoe
|
id: Hoe
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 112 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user