move hot plate item placement stuff into its own system (#18923)

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-08-20 01:37:19 +01:00
committed by GitHub
parent f25813a098
commit 00bae110e1
9 changed files with 160 additions and 124 deletions

View File

@@ -1,5 +1,3 @@
using Content.Shared.Whitelist;
namespace Content.Server.Chemistry.Components; namespace Content.Server.Chemistry.Components;
[RegisterComponent] [RegisterComponent]
@@ -28,23 +26,4 @@ public sealed class SolutionHeaterComponent : Component
/// </summary> /// </summary>
[DataField("partRatingHeatMultiplier")] [DataField("partRatingHeatMultiplier")]
public float PartRatingHeatMultiplier = 1.5f; public float PartRatingHeatMultiplier = 1.5f;
/// <summary>
/// The entities that are placed on the heater.
/// <summary>
[DataField("placedEntities")]
public HashSet<EntityUid> PlacedEntities = new();
/// <summary>
/// The max amount of entities that can be heated at the same time.
/// </summary>
[DataField("maxEntities")]
public uint MaxEntities = 1;
/// <summary>
/// Whitelist for entities that can be placed on the heater.
/// </summary>
[DataField("whitelist")]
[ViewVariables(VVAccess.ReadWrite)]
public EntityWhitelist? Whitelist;
} }

View File

@@ -1,4 +1,3 @@
using System.Linq;
using Content.Server.Chemistry.Components; using Content.Server.Chemistry.Components;
using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Chemistry.Components.SolutionManager;
using Content.Server.Construction; using Content.Server.Construction;
@@ -6,27 +5,26 @@ using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems; using Content.Server.Power.EntitySystems;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.Placeable; using Content.Shared.Placeable;
using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
namespace Content.Server.Chemistry.EntitySystems; namespace Content.Server.Chemistry.EntitySystems;
public sealed class SolutionHeaterSystem : EntitySystem public sealed class SolutionHeaterSystem : EntitySystem
{ {
[Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly ItemPlacerSystem _itemPlacer = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!;
[Dependency] private readonly PowerReceiverSystem _powerReceiver = default!; [Dependency] private readonly PowerReceiverSystem _powerReceiver = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SolutionContainerSystem _solution = default!; [Dependency] private readonly SolutionContainerSystem _solution = default!;
/// <inheritdoc/> /// <inheritdoc/>
public override void Initialize() public override void Initialize()
{ {
base.Initialize();
SubscribeLocalEvent<SolutionHeaterComponent, PowerChangedEvent>(OnPowerChanged); SubscribeLocalEvent<SolutionHeaterComponent, PowerChangedEvent>(OnPowerChanged);
SubscribeLocalEvent<SolutionHeaterComponent, RefreshPartsEvent>(OnRefreshParts); SubscribeLocalEvent<SolutionHeaterComponent, RefreshPartsEvent>(OnRefreshParts);
SubscribeLocalEvent<SolutionHeaterComponent, UpgradeExamineEvent>(OnUpgradeExamine); SubscribeLocalEvent<SolutionHeaterComponent, UpgradeExamineEvent>(OnUpgradeExamine);
SubscribeLocalEvent<SolutionHeaterComponent, StartCollideEvent>(OnStartCollide); SubscribeLocalEvent<SolutionHeaterComponent, ItemPlacedEvent>(OnItemPlaced);
SubscribeLocalEvent<SolutionHeaterComponent, EndCollideEvent>(OnEndCollide); SubscribeLocalEvent<SolutionHeaterComponent, ItemRemovedEvent>(OnItemRemoved);
} }
private void TurnOn(EntityUid uid) private void TurnOn(EntityUid uid)
@@ -35,9 +33,12 @@ public sealed class SolutionHeaterSystem : EntitySystem
EnsureComp<ActiveSolutionHeaterComponent>(uid); EnsureComp<ActiveSolutionHeaterComponent>(uid);
} }
public bool TryTurnOn(EntityUid uid, SolutionHeaterComponent component) public bool TryTurnOn(EntityUid uid, ItemPlacerComponent? placer = null)
{ {
if (component.PlacedEntities.Count <= 0 || !_powerReceiver.IsPowered(uid)) if (!Resolve(uid, ref placer))
return false;
if (placer.PlacedEntities.Count <= 0 || !_powerReceiver.IsPowered(uid))
return false; return false;
TurnOn(uid); TurnOn(uid);
@@ -52,7 +53,8 @@ public sealed class SolutionHeaterSystem : EntitySystem
private void OnPowerChanged(EntityUid uid, SolutionHeaterComponent component, ref PowerChangedEvent args) private void OnPowerChanged(EntityUid uid, SolutionHeaterComponent component, ref PowerChangedEvent args)
{ {
if (args.Powered && component.PlacedEntities.Count > 0) var placer = Comp<ItemPlacerComponent>(uid);
if (args.Powered && placer.PlacedEntities.Count > 0)
{ {
TurnOn(uid); TurnOn(uid);
} }
@@ -74,43 +76,26 @@ public sealed class SolutionHeaterSystem : EntitySystem
args.AddPercentageUpgrade("solution-heater-upgrade-heat", component.HeatPerSecond / component.BaseHeatPerSecond); args.AddPercentageUpgrade("solution-heater-upgrade-heat", component.HeatPerSecond / component.BaseHeatPerSecond);
} }
private void OnStartCollide(EntityUid uid, SolutionHeaterComponent component, ref StartCollideEvent args) private void OnItemPlaced(EntityUid uid, SolutionHeaterComponent comp, ref ItemPlacedEvent args)
{ {
if (component.Whitelist is not null && !component.Whitelist.IsValid(args.OtherEntity)) TryTurnOn(uid);
return;
// Disallow sleeping so we can detect when entity is removed from the heater.
_physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, false);
component.PlacedEntities.Add(args.OtherEntity);
TryTurnOn(uid, component);
if (component.PlacedEntities.Count >= component.MaxEntities)
_placeableSurface.SetPlaceable(uid, false);
} }
private void OnEndCollide(EntityUid uid, SolutionHeaterComponent component, ref EndCollideEvent args) private void OnItemRemoved(EntityUid uid, SolutionHeaterComponent component, ref ItemRemovedEvent args)
{ {
// Re-allow sleeping. var placer = Comp<ItemPlacerComponent>(uid);
_physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, true); if (placer.PlacedEntities.Count == 0) // Last entity was removed
component.PlacedEntities.Remove(args.OtherEntity);
if (component.PlacedEntities.Count == 0) // Last entity was removed
TurnOff(uid); TurnOff(uid);
_placeableSurface.SetPlaceable(uid, true);
} }
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
base.Update(frameTime); base.Update(frameTime);
var query = EntityQueryEnumerator<ActiveSolutionHeaterComponent, SolutionHeaterComponent>(); var query = EntityQueryEnumerator<ActiveSolutionHeaterComponent, SolutionHeaterComponent, ItemPlacerComponent>();
while (query.MoveNext(out _, out _, out var heater)) while (query.MoveNext(out _, out _, out var heater, out var placer))
{ {
foreach (var heatingEntity in heater.PlacedEntities.Take((int) heater.MaxEntities)) foreach (var heatingEntity in placer.PlacedEntities)
{ {
if (!TryComp<SolutionContainerManagerComponent>(heatingEntity, out var solution)) if (!TryComp<SolutionContainerManagerComponent>(heatingEntity, out var solution))
continue; continue;

View File

@@ -45,12 +45,6 @@ public sealed class ArtifactAnalyzerComponent : Component
[ViewVariables] [ViewVariables]
public EntityUid? Console; public EntityUid? Console;
/// <summary>
/// All of the valid artifacts currently touching the analyzer.
/// </summary>
[ViewVariables]
public HashSet<EntityUid> Contacts = new();
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public bool ReadyToPrint = false; public bool ReadyToPrint = false;

View File

@@ -10,6 +10,7 @@ using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
using Content.Shared.Audio; using Content.Shared.Audio;
using Content.Shared.DeviceLinking; using Content.Shared.DeviceLinking;
using Content.Shared.DeviceLinking.Events; using Content.Shared.DeviceLinking.Events;
using Content.Shared.Placeable;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Research.Components; using Content.Shared.Research.Components;
using Content.Shared.Xenoarchaeology.Equipment; using Content.Shared.Xenoarchaeology.Equipment;
@@ -18,7 +19,6 @@ using JetBrains.Annotations;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Physics.Events;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; using Robust.Shared.Utility;
@@ -45,7 +45,6 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
/// <inheritdoc/> /// <inheritdoc/>
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<ActiveScannedArtifactComponent, MoveEvent>(OnScannedMoved);
SubscribeLocalEvent<ActiveScannedArtifactComponent, ArtifactActivatedEvent>(OnArtifactActivated); SubscribeLocalEvent<ActiveScannedArtifactComponent, ArtifactActivatedEvent>(OnArtifactActivated);
SubscribeLocalEvent<ActiveArtifactAnalyzerComponent, ComponentStartup>(OnAnalyzeStart); SubscribeLocalEvent<ActiveArtifactAnalyzerComponent, ComponentStartup>(OnAnalyzeStart);
@@ -54,8 +53,8 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
SubscribeLocalEvent<ArtifactAnalyzerComponent, UpgradeExamineEvent>(OnUpgradeExamine); SubscribeLocalEvent<ArtifactAnalyzerComponent, UpgradeExamineEvent>(OnUpgradeExamine);
SubscribeLocalEvent<ArtifactAnalyzerComponent, RefreshPartsEvent>(OnRefreshParts); SubscribeLocalEvent<ArtifactAnalyzerComponent, RefreshPartsEvent>(OnRefreshParts);
SubscribeLocalEvent<ArtifactAnalyzerComponent, StartCollideEvent>(OnCollide); SubscribeLocalEvent<ArtifactAnalyzerComponent, ItemPlacedEvent>(OnItemPlaced);
SubscribeLocalEvent<ArtifactAnalyzerComponent, EndCollideEvent>(OnEndCollide); SubscribeLocalEvent<ArtifactAnalyzerComponent, ItemRemovedEvent>(OnItemRemoved);
SubscribeLocalEvent<ArtifactAnalyzerComponent, MapInitEvent>(OnMapInit); SubscribeLocalEvent<ArtifactAnalyzerComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<AnalysisConsoleComponent, NewLinkEvent>(OnNewLink); SubscribeLocalEvent<AnalysisConsoleComponent, NewLinkEvent>(OnNewLink);
@@ -107,22 +106,18 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
} }
/// <summary> /// <summary>
/// Goes through the current contacts on /// Goes through the current entities on
/// the analyzer and returns a valid artifact /// the analyzer and returns a valid artifact
/// </summary> /// </summary>
/// <param name="uid"></param> /// <param name="uid"></param>
/// <param name="component"></param> /// <param name="placer"></param>
/// <returns></returns> /// <returns></returns>
private EntityUid? GetArtifactForAnalysis(EntityUid? uid, ArtifactAnalyzerComponent? component = null) private EntityUid? GetArtifactForAnalysis(EntityUid? uid, ItemPlacerComponent? placer = null)
{ {
if (uid == null) if (uid == null || !Resolve(uid.Value, ref placer))
return null; return null;
if (!Resolve(uid.Value, ref component)) return placer.PlacedEntities.FirstOrNull();
return null;
var validEnts = component.Contacts.Where(HasComp<ArtifactComponent>).ToHashSet();
return validEnts.FirstOrNull();
} }
/// <summary> /// <summary>
@@ -205,11 +200,12 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
artifact = analyzer.LastAnalyzedArtifact; artifact = analyzer.LastAnalyzedArtifact;
msg = GetArtifactScanMessage(analyzer); msg = GetArtifactScanMessage(analyzer);
totalTime = analyzer.AnalysisDuration * analyzer.AnalysisDurationMulitplier; totalTime = analyzer.AnalysisDuration * analyzer.AnalysisDurationMulitplier;
canScan = analyzer.Contacts.Any(); if (TryComp<ItemPlacerComponent>(component.AnalyzerEntity, out var placer))
canScan = placer.PlacedEntities.Any();
canPrint = analyzer.ReadyToPrint; canPrint = analyzer.ReadyToPrint;
// the artifact that's actually on the scanner right now. // the artifact that's actually on the scanner right now.
if (GetArtifactForAnalysis(component.AnalyzerEntity, analyzer) is { } current) if (GetArtifactForAnalysis(component.AnalyzerEntity, placer) is { } current)
points = _artifact.GetResearchPointValue(current); points = _artifact.GetResearchPointValue(current);
} }
var analyzerConnected = component.AnalyzerEntity != null; var analyzerConnected = component.AnalyzerEntity != null;
@@ -381,20 +377,6 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
CancelScan(uid); CancelScan(uid);
} }
/// <summary>
/// Checks to make sure that the currently scanned artifact isn't moved off of the scanner
/// </summary>
private void OnScannedMoved(EntityUid uid, ActiveScannedArtifactComponent component, ref MoveEvent args)
{
if (!TryComp<ArtifactAnalyzerComponent>(component.Scanner, out var analyzer))
return;
if (analyzer.Contacts.Contains(uid))
return;
CancelScan(uid, component, analyzer);
}
/// <summary> /// <summary>
/// Stops the current scan /// Stops the current scan
/// </summary> /// </summary>
@@ -448,27 +430,16 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
args.AddPercentageUpgrade("analyzer-artifact-component-upgrade-analysis", component.AnalysisDurationMulitplier); args.AddPercentageUpgrade("analyzer-artifact-component-upgrade-analysis", component.AnalysisDurationMulitplier);
} }
private void OnCollide(EntityUid uid, ArtifactAnalyzerComponent component, ref StartCollideEvent args) private void OnItemPlaced(EntityUid uid, ArtifactAnalyzerComponent component, ref ItemPlacedEvent args)
{ {
var otherEnt = args.OtherEntity; if (component.Console != null && Exists(component.Console))
if (!HasComp<ArtifactComponent>(otherEnt))
return;
component.Contacts.Add(otherEnt);
if (component.Console != null)
UpdateUserInterface(component.Console.Value); UpdateUserInterface(component.Console.Value);
} }
private void OnEndCollide(EntityUid uid, ArtifactAnalyzerComponent component, ref EndCollideEvent args) private void OnItemRemoved(EntityUid uid, ArtifactAnalyzerComponent component, ref ItemRemovedEvent args)
{ {
var otherEnt = args.OtherEntity; // cancel the scan if the artifact moves off the analyzer
CancelScan(args.OtherEntity);
if (!HasComp<ArtifactComponent>(otherEnt))
return;
component.Contacts.Remove(otherEnt);
if (component.Console != null && Exists(component.Console)) if (component.Console != null && Exists(component.Console))
UpdateUserInterface(component.Console.Value); UpdateUserInterface(component.Console.Value);
} }

View File

@@ -5,7 +5,7 @@ using Content.Server.Xenoarchaeology.Equipment.Components;
using Content.Server.Xenoarchaeology.XenoArtifacts; using Content.Server.Xenoarchaeology.XenoArtifacts;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Robust.Shared.Physics.Events; using Content.Shared.Placeable;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Timing; using Robust.Shared.Timing;
@@ -13,8 +13,8 @@ namespace Content.Server.Xenoarchaeology.Equipment.Systems;
public sealed class TraversalDistorterSystem : EntitySystem public sealed class TraversalDistorterSystem : EntitySystem
{ {
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly PopupSystem _popup = default!;
/// <inheritdoc/> /// <inheritdoc/>
public override void Initialize() public override void Initialize()
@@ -26,8 +26,8 @@ public sealed class TraversalDistorterSystem : EntitySystem
SubscribeLocalEvent<TraversalDistorterComponent, RefreshPartsEvent>(OnRefreshParts); SubscribeLocalEvent<TraversalDistorterComponent, RefreshPartsEvent>(OnRefreshParts);
SubscribeLocalEvent<TraversalDistorterComponent, UpgradeExamineEvent>(OnUpgradeExamine); SubscribeLocalEvent<TraversalDistorterComponent, UpgradeExamineEvent>(OnUpgradeExamine);
SubscribeLocalEvent<TraversalDistorterComponent, StartCollideEvent>(OnCollide); SubscribeLocalEvent<TraversalDistorterComponent, ItemPlacedEvent>(OnItemPlaced);
SubscribeLocalEvent<TraversalDistorterComponent, EndCollideEvent>(OnEndCollide); SubscribeLocalEvent<TraversalDistorterComponent, ItemRemovedEvent>(OnItemRemoved);
} }
private void OnInit(EntityUid uid, TraversalDistorterComponent component, MapInitEvent args) private void OnInit(EntityUid uid, TraversalDistorterComponent component, MapInitEvent args)
@@ -88,24 +88,15 @@ public sealed class TraversalDistorterSystem : EntitySystem
args.AddPercentageUpgrade("traversal-distorter-upgrade-bias", component.BiasChance / component.BaseBiasChance); args.AddPercentageUpgrade("traversal-distorter-upgrade-bias", component.BiasChance / component.BaseBiasChance);
} }
private void OnCollide(EntityUid uid, TraversalDistorterComponent component, ref StartCollideEvent args) private void OnItemPlaced(EntityUid uid, TraversalDistorterComponent component, ref ItemPlacedEvent args)
{ {
var otherEnt = args.OtherEntity; var bias = EnsureComp<BiasedArtifactComponent>(args.OtherEntity);
if (!HasComp<ArtifactComponent>(otherEnt))
return;
var bias = EnsureComp<BiasedArtifactComponent>(otherEnt);
bias.Provider = uid; bias.Provider = uid;
} }
private void OnEndCollide(EntityUid uid, TraversalDistorterComponent component, ref EndCollideEvent args) private void OnItemRemoved(EntityUid uid, TraversalDistorterComponent component, ref ItemRemovedEvent args)
{ {
var otherEnt = args.OtherEntity; var otherEnt = args.OtherEntity;
if (!HasComp<ArtifactComponent>(otherEnt))
return;
if (TryComp<BiasedArtifactComponent>(otherEnt, out var bias) && bias.Provider == uid) if (TryComp<BiasedArtifactComponent>(otherEnt, out var bias) && bias.Provider == uid)
RemComp(otherEnt, bias); RemComp(otherEnt, bias);
} }

View File

@@ -0,0 +1,31 @@
using Content.Shared.Whitelist;
using Robust.Shared.GameStates;
namespace Content.Shared.Placeable;
/// <summary>
/// Detects items placed on it that match a whitelist.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(ItemPlacerSystem))]
public sealed partial class ItemPlacerComponent : Component
{
/// <summary>
/// The entities that are currently on top of the placer.
/// Guaranteed to have less than <see cref="MaxEntities"/> enitites if it is set.
/// <summary>
[DataField("placedEntities"), AutoNetworkedField]
public HashSet<EntityUid> PlacedEntities = new();
/// <summary>
/// Whitelist for entities that can be placed.
/// </summary>
[DataField("whitelist"), ViewVariables(VVAccess.ReadWrite)]
public EntityWhitelist? Whitelist;
/// <summary>
/// The max amount of entities that can be placed at the same time.
/// If 0, there is no limit.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("maxEntities"), AutoNetworkedField]
public uint MaxEntities = 1;
}

View File

@@ -0,0 +1,72 @@
using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
using System.Linq;
namespace Content.Shared.Placeable;
/// <summary>
/// Tracks placed entities
/// Subscribe to <see cref="ItemPlacedEvent"/> or <see cref="ItemRemovedEvent"/> to do things when items or placed or removed.
/// </summary>
public sealed class ItemPlacerSystem : EntitySystem
{
[Dependency] private readonly PlaceableSurfaceSystem _placeableSurface = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ItemPlacerComponent, StartCollideEvent>(OnStartCollide);
SubscribeLocalEvent<ItemPlacerComponent, EndCollideEvent>(OnEndCollide);
}
private void OnStartCollide(EntityUid uid, ItemPlacerComponent comp, ref StartCollideEvent args)
{
if (comp.Whitelist != null && !comp.Whitelist.IsValid(args.OtherEntity))
return;
// Disallow sleeping so we can detect when entity is removed from the heater.
_physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, false);
var count = comp.PlacedEntities.Count;
if (comp.MaxEntities == 0 || count < comp.MaxEntities)
{
comp.PlacedEntities.Add(args.OtherEntity);
var ev = new ItemPlacedEvent(args.OtherEntity);
RaiseLocalEvent(uid, ref ev);
}
if (comp.MaxEntities > 0 && count >= (comp.MaxEntities - 1))
{
// Don't let any more items be placed if it's reached its limit.
_placeableSurface.SetPlaceable(uid, false);
}
}
private void OnEndCollide(EntityUid uid, ItemPlacerComponent comp, ref EndCollideEvent args)
{
// Re-allow sleeping.
_physics.SetSleepingAllowed(args.OtherEntity, args.OtherBody, true);
comp.PlacedEntities.Remove(args.OtherEntity);
var ev = new ItemRemovedEvent(args.OtherEntity);
RaiseLocalEvent(uid, ref ev);
_placeableSurface.SetPlaceable(uid, true);
}
}
/// <summary>
/// Raised on the <see cref="ItemPlacer"/> when an item is placed and it is under the item limit.
/// </summary>
[ByRefEvent]
public record struct ItemPlacedEvent(EntityUid OtherEntity);
/// <summary>
/// Raised on the <see cref="ItemPlacer"/> when an item is removed from it.
/// </summary>
[ByRefEvent]
public record struct ItemRemovedEvent(EntityUid OtherEntity);

View File

@@ -46,6 +46,10 @@
powerDrawMultiplier: 0.80 powerDrawMultiplier: 0.80
scaling: Exponential scaling: Exponential
- type: ArtifactAnalyzer - type: ArtifactAnalyzer
- type: ItemPlacer
whitelist:
components:
- Artifact
- type: DeviceNetwork - type: DeviceNetwork
deviceNetId: Wired deviceNetId: Wired
receiveFrequencyId: BasicDevice receiveFrequencyId: BasicDevice
@@ -109,6 +113,14 @@
powerDrawMultiplier: 0.80 powerDrawMultiplier: 0.80
scaling: Exponential scaling: Exponential
- type: TraversalDistorter - type: TraversalDistorter
- type: ItemPlacer
# don't limit the number of artifacts that can be biased
maxEntities: 0
whitelist:
components:
- Artifact
- type: PlaceableSurface
placeCentered: true
- type: Machine - type: Machine
board: TraversalDistorterMachineCircuitboard board: TraversalDistorterMachineCircuitboard
- type: Appearance - type: Appearance

View File

@@ -38,6 +38,7 @@
components: components:
- FitsInDispenser - FitsInDispenser
- type: SolutionHeater - type: SolutionHeater
- type: ItemPlacer
whitelist: whitelist:
components: components:
- FitsInDispenser - FitsInDispenser