diff --git a/Content.Client/_Sunrise/Pacificator/PacificatorBoundUserInterface.cs b/Content.Client/_Sunrise/Pacificator/PacificatorBoundUserInterface.cs
new file mode 100644
index 0000000000..38bd6dad43
--- /dev/null
+++ b/Content.Client/_Sunrise/Pacificator/PacificatorBoundUserInterface.cs
@@ -0,0 +1,54 @@
+using Content.Shared._Sunrise.Pacificator;
+using JetBrains.Annotations;
+
+namespace Content.Client._Sunrise.Pacificator
+{
+ [UsedImplicitly]
+ public sealed class PacificatorBoundUserInterface : BoundUserInterface
+ {
+ [ViewVariables]
+ private PacificatorWindow? _window;
+
+ public PacificatorBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
+ {
+ }
+
+ protected override void Open()
+ {
+ base.Open();
+
+ _window = new PacificatorWindow(this);
+
+ /*
+ _window.Switch.OnPressed += _ =>
+ {
+ SendMessage(new SharedPacificatorComponent.SwitchGeneratorMessage(!IsOn));
+ };
+ */
+
+ _window.OpenCentered();
+ _window.OnClose += Close;
+ }
+
+ protected override void UpdateState(BoundUserInterfaceState state)
+ {
+ base.UpdateState(state);
+
+ var castState = (GeneratorState) state;
+ _window?.UpdateState(castState);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (!disposing) return;
+
+ _window?.Dispose();
+ }
+
+ public void SetPowerSwitch(bool on)
+ {
+ SendMessage(new SwitchGeneratorMessage(on));
+ }
+ }
+}
diff --git a/Content.Client/_Sunrise/Pacificator/PacificatorWindow.xaml b/Content.Client/_Sunrise/Pacificator/PacificatorWindow.xaml
new file mode 100644
index 0000000000..e6ba9a0023
--- /dev/null
+++ b/Content.Client/_Sunrise/Pacificator/PacificatorWindow.xaml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/_Sunrise/Pacificator/PacificatorWindow.xaml.cs b/Content.Client/_Sunrise/Pacificator/PacificatorWindow.xaml.cs
new file mode 100644
index 0000000000..e253267488
--- /dev/null
+++ b/Content.Client/_Sunrise/Pacificator/PacificatorWindow.xaml.cs
@@ -0,0 +1,73 @@
+using Content.Shared._Sunrise.Pacificator;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow;
+
+namespace Content.Client._Sunrise.Pacificator
+{
+ [GenerateTypedNameReferences]
+ public sealed partial class PacificatorWindow : FancyWindow
+ {
+ private readonly ButtonGroup _buttonGroup = new();
+
+ private readonly PacificatorBoundUserInterface _owner;
+
+ public PacificatorWindow(PacificatorBoundUserInterface owner)
+ {
+ RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
+
+ _owner = owner;
+
+ OnButton.Group = _buttonGroup;
+ OffButton.Group = _buttonGroup;
+
+ OnButton.OnPressed += _ => _owner.SetPowerSwitch(true);
+ OffButton.OnPressed += _ => _owner.SetPowerSwitch(false);
+
+ EntityView.SetEntity(owner.Owner);
+ }
+
+ public void UpdateState(GeneratorState state)
+ {
+ if (state.On)
+ OnButton.Pressed = true;
+ else
+ OffButton.Pressed = true;
+
+ PowerLabel.Text = Loc.GetString(
+ "gravity-generator-window-power-label",
+ ("draw", state.PowerDraw),
+ ("max", state.PowerDrawMax));
+
+ PowerLabel.SetOnlyStyleClass(MathHelper.CloseTo(state.PowerDraw, state.PowerDrawMax) ? "Good" : "Caution");
+
+ ChargeBar.Value = state.Charge;
+ ChargeText.Text = (state.Charge / 255f).ToString("P0");
+ StatusLabel.Text = Loc.GetString(state.PowerStatus switch
+ {
+ PacificatorPowerStatus.Off => "gravity-generator-window-status-off",
+ PacificatorPowerStatus.Discharging => "gravity-generator-window-status-discharging",
+ PacificatorPowerStatus.Charging => "gravity-generator-window-status-charging",
+ PacificatorPowerStatus.FullyCharged => "gravity-generator-window-status-fully-charged",
+ _ => throw new ArgumentOutOfRangeException()
+ });
+
+ StatusLabel.SetOnlyStyleClass(state.PowerStatus switch
+ {
+ PacificatorPowerStatus.Off => "Danger",
+ PacificatorPowerStatus.Discharging => "Caution",
+ PacificatorPowerStatus.Charging => "Caution",
+ PacificatorPowerStatus.FullyCharged => "Good",
+ _ => throw new ArgumentOutOfRangeException()
+ });
+
+ EtaLabel.Text = state.EtaSeconds >= 0
+ ? Loc.GetString("gravity-generator-window-eta-value", ("left", TimeSpan.FromSeconds(state.EtaSeconds)))
+ : Loc.GetString("gravity-generator-window-eta-none");
+
+ EtaLabel.SetOnlyStyleClass(state.EtaSeconds >= 0 ? "Caution" : "Disabled");
+ }
+ }
+}
diff --git a/Content.Server/_Sunrise/Pacificator/PacificatorComponent.cs b/Content.Server/_Sunrise/Pacificator/PacificatorComponent.cs
new file mode 100644
index 0000000000..e08aa9058f
--- /dev/null
+++ b/Content.Server/_Sunrise/Pacificator/PacificatorComponent.cs
@@ -0,0 +1,56 @@
+using Content.Shared.Humanoid;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Server._Sunrise.Pacificator;
+
+///
+///
+///
+[RegisterComponent]
+[Access(typeof(PacificatorSystems))]
+public sealed partial class PacificatorComponent : Component
+{
+ // 1% charge per second.
+ [ViewVariables(VVAccess.ReadWrite)] [DataField("chargeRate")]
+ public float ChargeRate { get; set; } = 0.01f;
+ // The gravity generator has two power values.
+ // Idle power is assumed to be the power needed to run the control systems and interface.
+ [DataField("idlePower")] public float IdlePowerUse { get; set; }
+ // Active power is the power needed to keep the gravity field stable.
+ [DataField("activePower")] public float ActivePowerUse { get; set; }
+ [DataField("lightRadiusMin")] public float LightRadiusMin { get; set; }
+ [DataField("lightRadiusMax")] public float LightRadiusMax { get; set; }
+
+ ///
+ /// Is the power switch on?
+ ///
+ [DataField("switchedOn")]
+ public bool SwitchedOn { get; set; } = true;
+
+ ///
+ /// Is the gravity generator intact?
+ ///
+ [DataField("intact")]
+ public bool Intact { get; set; } = true;
+
+ [DataField("maxCharge")]
+ public float MaxCharge { get; set; } = 1;
+
+ // 0 -> 1
+ [ViewVariables(VVAccess.ReadWrite)] [DataField("charge")] public float Charge { get; set; } = 1;
+
+ [ViewVariables]
+ public bool Active { get; set; } = false;
+
+ [ViewVariables] public bool NeedUIUpdate { get; set; }
+
+ [ViewVariables(VVAccess.ReadWrite), DataField("nextTick", customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan NextTick = TimeSpan.Zero;
+
+ public TimeSpan RefreshCooldown = TimeSpan.FromSeconds(5);
+
+ [DataField]
+ public float Range = 32f;
+
+ public HashSet> PacifiedEntities = [];
+}
diff --git a/Content.Server/_Sunrise/Pacificator/PacificatorSystems.cs b/Content.Server/_Sunrise/Pacificator/PacificatorSystems.cs
new file mode 100644
index 0000000000..7af5207c97
--- /dev/null
+++ b/Content.Server/_Sunrise/Pacificator/PacificatorSystems.cs
@@ -0,0 +1,320 @@
+using Content.Server.Administration.Logs;
+using Content.Server.Audio;
+using Content.Server.Power.Components;
+using Content.Shared._Sunrise.Pacificator;
+using Content.Shared.CombatMode.Pacification;
+using Content.Shared.Database;
+using Content.Shared.Humanoid;
+using Content.Shared.Interaction;
+using Robust.Server.GameObjects;
+using Robust.Shared.Timing;
+
+namespace Content.Server._Sunrise.Pacificator;
+
+public sealed class PacificatorSystems : EntitySystem
+{
+ [Dependency] private readonly EntityLookupSystem _lookup = default!;
+ [Dependency] private readonly IAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly AmbientSoundSystem _ambientSoundSystem = default!;
+ [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly SharedPointLightSystem _lights = default!;
+ [Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnCompInit);
+ SubscribeLocalEvent(OnComponentShutdown);
+ SubscribeLocalEvent(OnInteractHand);
+ SubscribeLocalEvent(
+ OnSwitchGenerator);
+ }
+
+ private void OnInteractHand(EntityUid uid, Pacificator.PacificatorComponent component, InteractHandEvent args)
+ {
+ ApcPowerReceiverComponent? powerReceiver = default!;
+ if (!Resolve(uid, ref powerReceiver))
+ return;
+
+ // Do not allow opening UI if broken or unpowered.
+ if (!component.Intact || powerReceiver.PowerReceived < component.IdlePowerUse)
+ return;
+
+ _uiSystem.TryOpenUi(uid, PacificatorUiKey.Key, args.User);
+ component.NeedUIUpdate = true;
+ }
+
+ private void OnComponentShutdown(EntityUid uid, Pacificator.PacificatorComponent component, ComponentShutdown args)
+ {
+ foreach (var pacifiedEntity in component.PacifiedEntities)
+ {
+ RemComp(pacifiedEntity);
+ component.PacifiedEntities.Remove(pacifiedEntity);
+ }
+ }
+
+ private void OnCompInit(Entity ent, ref ComponentInit args)
+ {
+ ApcPowerReceiverComponent? powerReceiver = null;
+ if (!Resolve(ent, ref powerReceiver, false))
+ return;
+
+ UpdatePowerState(ent, powerReceiver);
+ UpdateState((ent, ent.Comp, powerReceiver));
+ }
+
+ public void UpdateState(Entity ent)
+ {
+ var (uid, grav, powerReceiver) = ent;
+ var appearance = EntityManager.GetComponentOrNull(uid);
+ _appearance.SetData(uid, PacificatorVisuals.Charge, grav.Charge, appearance);
+
+ if (_lights.TryGetLight(uid, out var pointLight))
+ {
+ _lights.SetEnabled(uid, grav.Charge > 0, pointLight);
+ _lights.SetRadius(uid, MathHelper.Lerp(grav.LightRadiusMin, grav.LightRadiusMax, grav.Charge), pointLight);
+ }
+
+ if (!grav.Intact)
+ {
+ MakeBroken((uid, grav), appearance);
+ }
+ else if (powerReceiver.PowerReceived < grav.IdlePowerUse)
+ {
+ MakeUnpowered((uid, grav), appearance);
+ }
+ else if (!grav.SwitchedOn)
+ {
+ MakeOff((uid, grav), appearance);
+ }
+ else
+ {
+ MakeOn((uid, grav), appearance);
+ }
+ }
+
+ private void MakeBroken(Entity ent, AppearanceComponent? appearance)
+ {
+ _ambientSoundSystem.SetAmbience(ent, false);
+
+ _appearance.SetData(ent, PacificatorVisuals.State, PacificatorStatus.Broken);
+ }
+
+ private void MakeUnpowered(Entity ent, AppearanceComponent? appearance)
+ {
+ _ambientSoundSystem.SetAmbience(ent, false);
+
+ _appearance.SetData(ent, PacificatorVisuals.State, PacificatorStatus.Unpowered, appearance);
+ }
+
+ private void MakeOff(Entity ent, AppearanceComponent? appearance)
+ {
+ _ambientSoundSystem.SetAmbience(ent, false);
+
+ _appearance.SetData(ent, PacificatorVisuals.State, PacificatorStatus.Off, appearance);
+ }
+
+ private void MakeOn(Entity ent, AppearanceComponent? appearance)
+ {
+ _ambientSoundSystem.SetAmbience(ent, true);
+
+ _appearance.SetData(ent, PacificatorVisuals.State, PacificatorStatus.On, appearance);
+ }
+
+ private void OnSwitchGenerator(
+ EntityUid uid,
+ Pacificator.PacificatorComponent component,
+ SwitchGeneratorMessage args)
+ {
+ SetSwitchedOn(uid, args.Actor, component, args.On);
+ }
+
+ private void SetSwitchedOn(EntityUid uid, EntityUid actor, Pacificator.PacificatorComponent component, bool on,
+ ApcPowerReceiverComponent? powerReceiver = null)
+ {
+ if (!Resolve(uid, ref powerReceiver))
+ return;
+
+ _adminLogger.Add(LogType.Action, on ? LogImpact.Medium : LogImpact.High, $"{actor:player} set ${ToPrettyString(uid):target} to {(on ? "on" : "off")}");
+
+ component.SwitchedOn = on;
+ UpdatePowerState(component, powerReceiver);
+ component.NeedUIUpdate = true;
+ }
+
+ private static void UpdatePowerState(
+ Pacificator.PacificatorComponent component,
+ ApcPowerReceiverComponent powerReceiver)
+ {
+ powerReceiver.Load = component.SwitchedOn ? component.ActivePowerUse : component.IdlePowerUse;
+ }
+
+ private void UpdateUI(Entity ent, float chargeRate)
+ {
+ var (_, component, powerReceiver) = ent;
+ if (!_uiSystem.IsUiOpen(ent.Owner, PacificatorUiKey.Key))
+ return;
+
+ var chargeTarget = chargeRate < 0 ? 0 : component.MaxCharge;
+ short chargeEta;
+ var atTarget = false;
+ if (MathHelper.CloseTo(component.Charge, chargeTarget))
+ {
+ chargeEta = short.MinValue; // N/A
+ atTarget = true;
+ }
+ else
+ {
+ var diff = chargeTarget - component.Charge;
+ chargeEta = (short) Math.Abs(diff / chargeRate);
+ }
+
+ var status = chargeRate switch
+ {
+ > 0 when atTarget => PacificatorPowerStatus.FullyCharged,
+ < 0 when atTarget => PacificatorPowerStatus.Off,
+ > 0 => PacificatorPowerStatus.Charging,
+ < 0 => PacificatorPowerStatus.Discharging,
+ _ => throw new ArgumentOutOfRangeException()
+ };
+
+ var state = new GeneratorState(
+ component.SwitchedOn,
+ (byte) (component.Charge * 255),
+ status,
+ (short) Math.Round(powerReceiver.PowerReceived),
+ (short) Math.Round(powerReceiver.Load),
+ chargeEta
+ );
+
+ _uiSystem.SetUiState(
+ ent.Owner,
+ PacificatorUiKey.Key,
+ state);
+
+ component.NeedUIUpdate = false;
+ }
+
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var pacificator, out var powerReceiver))
+ {
+ var ent = (uid, pacificator, powerReceiver);
+ if (!pacificator.Intact)
+ continue;
+
+ // Calculate charge rate based on power state and such.
+ // Negative charge rate means discharging.
+ float chargeRate;
+ if (pacificator.SwitchedOn)
+ {
+ if (powerReceiver.Powered)
+ {
+ chargeRate = pacificator.ChargeRate;
+ }
+ else
+ {
+ // Scale discharge rate such that if we're at 25% active power we discharge at 75% rate.
+ var receiving = powerReceiver.PowerReceived;
+ var mainSystemPower = Math.Max(0, receiving - pacificator.IdlePowerUse);
+ var ratio = 1 - mainSystemPower / (pacificator.ActivePowerUse - pacificator.IdlePowerUse);
+ chargeRate = -(ratio * pacificator.ChargeRate);
+ }
+ }
+ else
+ {
+ chargeRate = -pacificator.ChargeRate;
+ }
+
+ var active = pacificator.Active;
+ var lastCharge = pacificator.Charge;
+ pacificator.Charge = Math.Clamp(pacificator.Charge + frameTime * chargeRate, 0, pacificator.MaxCharge);
+ if (chargeRate > 0)
+ {
+ // Charging.
+ if (MathHelper.CloseTo(pacificator.Charge, pacificator.MaxCharge) && !pacificator.Active)
+ {
+ pacificator.Active = true;
+ }
+ }
+ else
+ {
+ // Discharging
+ if (MathHelper.CloseTo(pacificator.Charge, 0) && pacificator.Active)
+ {
+ pacificator.Active = false;
+ }
+ }
+
+ var updateUI = pacificator.NeedUIUpdate;
+ if (!MathHelper.CloseTo(lastCharge, pacificator.Charge))
+ {
+ UpdateState(ent);
+ updateUI = true;
+ }
+
+ if (updateUI)
+ UpdateUI(ent, chargeRate);
+
+ if (active != pacificator.Active)
+ {
+ if (!pacificator.Active)
+ {
+ foreach (var pacifiedEntity in pacificator.PacifiedEntities)
+ {
+ RemComp(pacifiedEntity);
+ pacificator.PacifiedEntities.Remove(pacifiedEntity);
+ }
+ }
+ }
+
+ UpdatePacified((ent.uid, ent.pacificator));
+ }
+ }
+
+ private void UpdatePacified(Entity ent)
+ {
+ if (ent.Comp.NextTick > _timing.CurTime)
+ return;
+
+ ent.Comp.NextTick += ent.Comp.RefreshCooldown;
+
+ if (!ent.Comp.Active)
+ return;
+
+ var coords = Transform(ent.Owner).Coordinates;
+
+ var entities = _lookup.GetEntitiesInRange(coords, ent.Comp.Range);
+
+ foreach (var entityUid in entities)
+ {
+ if (ent.Comp.PacifiedEntities.Contains(entityUid))
+ continue;
+
+ EnsureComp(entityUid);
+ ent.Comp.PacifiedEntities.Add(entityUid);
+ }
+
+ var entitiesToRemove = new HashSet>();
+
+ foreach (var pacifiedEntity in ent.Comp.PacifiedEntities)
+ {
+ if (entities.Contains(pacifiedEntity))
+ continue;
+
+ RemComp(pacifiedEntity);
+ entitiesToRemove.Add(pacifiedEntity);
+ }
+
+ foreach (var entityToRemove in entitiesToRemove)
+ {
+ ent.Comp.PacifiedEntities.Remove(entityToRemove);
+ }
+ }
+}
+
diff --git a/Content.Shared/_Sunrise/Pacificator/SharedPacificatorSystem.cs b/Content.Shared/_Sunrise/Pacificator/SharedPacificatorSystem.cs
new file mode 100644
index 0000000000..81a225c3d5
--- /dev/null
+++ b/Content.Shared/_Sunrise/Pacificator/SharedPacificatorSystem.cs
@@ -0,0 +1,81 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared._Sunrise.Pacificator;
+
+public abstract partial class SharedPacificatorSystem : EntitySystem
+{
+ public override void Initialize()
+ {
+ base.Initialize();
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class SwitchGeneratorMessage : BoundUserInterfaceMessage
+{
+ public bool On;
+
+ public SwitchGeneratorMessage(bool on)
+ {
+ On = on;
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class GeneratorState : BoundUserInterfaceState
+{
+ public bool On;
+ // 0 -> 255
+ public byte Charge;
+ public PacificatorPowerStatus PowerStatus;
+ public short PowerDraw;
+ public short PowerDrawMax;
+ public short EtaSeconds;
+
+ public GeneratorState(
+ bool on,
+ byte charge,
+ PacificatorPowerStatus powerStatus,
+ short powerDraw,
+ short powerDrawMax,
+ short etaSeconds)
+ {
+ On = on;
+ Charge = charge;
+ PowerStatus = powerStatus;
+ PowerDraw = powerDraw;
+ PowerDrawMax = powerDrawMax;
+ EtaSeconds = etaSeconds;
+ }
+}
+
+[Serializable, NetSerializable]
+public enum PacificatorUiKey
+{
+ Key
+}
+
+[Serializable, NetSerializable]
+public enum PacificatorVisuals
+{
+ State,
+ Charge
+}
+
+[Serializable, NetSerializable]
+public enum PacificatorStatus
+{
+ Broken,
+ Unpowered,
+ Off,
+ On
+}
+
+[Serializable, NetSerializable]
+public enum PacificatorPowerStatus : byte
+{
+ Off,
+ Discharging,
+ Charging,
+ FullyCharged
+}
diff --git a/Resources/Locale/ru-RU/gravity/gravity-generator-component.ftl b/Resources/Locale/ru-RU/gravity/gravity-generator-component.ftl
index 22190b51ea..0347050c3c 100644
--- a/Resources/Locale/ru-RU/gravity/gravity-generator-component.ftl
+++ b/Resources/Locale/ru-RU/gravity/gravity-generator-component.ftl
@@ -9,7 +9,7 @@ gravity-generator-window-title = Генератор гравитации
gravity-generator-window-status = Состояние:
gravity-generator-window-power = Питание:
-gravity-generator-window-eta = Оставшееся время:
+gravity-generator-window-eta = ETA:
gravity-generator-window-charge = Заряд:
## UI statuses
diff --git a/Resources/Prototypes/_Sunrise/Pacificator/pacificator.yml b/Resources/Prototypes/_Sunrise/Pacificator/pacificator.yml
new file mode 100644
index 0000000000..c701f2cf6f
--- /dev/null
+++ b/Resources/Prototypes/_Sunrise/Pacificator/pacificator.yml
@@ -0,0 +1,99 @@
+- type: entity
+ id: Pacificator
+ parent: BaseMachinePowered
+ name: генератор пацифизма
+ description: Делает всех разумных существ в радиусе действия пацифистами.
+ placement:
+ mode: AlignTileAny
+ components:
+ - type: Sprite
+ sprite: Structures/Machines/gravity_generator_mini.rsi
+ snapCardinals: true
+ layers:
+ - state: on
+ map: ["enum.GravityGeneratorVisualLayers.Base"]
+ - sprite: Structures/Machines/gravity_generator_core.rsi
+ state: activated
+ shader: unshaded
+ map: ["enum.GravityGeneratorVisualLayers.Core"]
+ scale: "0.4,0.4"
+ offset: "0,0.2"
+ - type: Fixtures
+ fixtures:
+ fix1:
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.4,-0.4,0.4,0.4"
+ density: 3125
+ mask:
+ - LargeMobMask
+ layer:
+ - WallLayer
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 500
+ behaviors:
+ - !type:DoActsBehavior
+ acts: ["Destruction"]
+ - !type:PlaySoundBehavior
+ sound:
+ collection: MetalGlassBreak
+ - !type:SpawnEntitiesBehavior
+ spawn:
+ MachineFrameDestroyed:
+ min: 1
+ max: 1
+ - type: Machine
+ board: PacificatorCircuitboard
+ - type: Pacificator
+ range: 128
+ idlePower: 15
+ activePower: 500
+ lightRadiusMin: 0.75
+ lightRadiusMax: 2.5
+ - type: StaticPrice
+ price: 5000
+ - type: UserInterface
+ interfaces:
+ enum.PacificatorUiKey.Key:
+ type: PacificatorBoundUserInterface
+ - type: Appearance
+ - type: PointLight
+ radius: 2.5
+ energy: 0.5
+ # Gravity generator is a large machine, not casting shadows is fine within the radius set above.
+ castShadows: false
+ color: "#a8ffd9"
+ - type: Repairable
+ fuelCost: 10
+ doAfterDelay: 5
+ - type: ExtensionCableReceiver
+ - type: Physics
+ bodyType: Static
+ - type: Transform
+ anchored: true
+ - type: ApcPowerReceiver
+ powerLoad: 500
+ - type: AmbientSound
+ enabled: false
+ volume: -6
+ range: 7
+ sound:
+ path: /Audio/Ambience/Objects/gravity_gen_hum.ogg
+
+- type: entity
+ parent: BaseMachineCircuitboard
+ id: PacificatorCircuitboard
+ name: генератор пацифизма (машинная плата)
+ description:
+ components:
+ - type: MachineBoard
+ prototype: Pacificator
+ stackRequirements:
+ Capacitor: 4
+ MatterBin: 3
+ Steel: 5
+ CableHV: 5
+ Uranium: 2