]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Adding a random gate (#41627)
authorBorsh <85323386+NeBorsh@users.noreply.github.com>
Sun, 14 Dec 2025 19:15:22 +0000 (22:15 +0300)
committerGitHub <noreply@github.com>
Sun, 14 Dec 2025 19:15:22 +0000 (19:15 +0000)
* Added random gate

* minor edit

* cleaning up my shit after trying to do something faster

* new lines

* some changes

* joke

* UI

* Long Division

* Dont use ctrl + x in 3 am

* I hope these are the final touches

* One thing, I don't know why

* noname commit

* no way, 1kk of code lines edit

* sudo rm -rf ... and something there...

* update

* sometimes its sad

16 files changed:
Content.Client/DeviceLinking/Systems/RandomGateSystem.cs [new file with mode: 0644]
Content.Client/DeviceLinking/UI/RandomGateBoundUserInterface.cs [new file with mode: 0644]
Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml [new file with mode: 0644]
Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml.cs [new file with mode: 0644]
Content.Server/DeviceLinking/Systems/RandomGateSystem.cs [new file with mode: 0644]
Content.Shared/DeviceLinking/Components/RandomGateComponent.cs [new file with mode: 0644]
Content.Shared/DeviceLinking/SharedRandomGateEvents.cs [new file with mode: 0644]
Content.Shared/DeviceLinking/Systems/SharedRandomGateSystem.cs [new file with mode: 0644]
Resources/Locale/en-US/deviceLinking/randomgate.ftl [new file with mode: 0644]
Resources/Locale/en-US/machine-linking/receiver_ports.ftl
Resources/Prototypes/DeviceLinking/sink_ports.yml
Resources/Prototypes/Entities/Structures/gates.yml
Resources/Prototypes/Recipes/Construction/Graphs/tools/logic_gate.yml
Resources/Prototypes/Recipes/Construction/tools.yml
Resources/Textures/Objects/Devices/gates.rsi/meta.json
Resources/Textures/Objects/Devices/gates.rsi/random_gate.png [new file with mode: 0644]

diff --git a/Content.Client/DeviceLinking/Systems/RandomGateSystem.cs b/Content.Client/DeviceLinking/Systems/RandomGateSystem.cs
new file mode 100644 (file)
index 0000000..db0d956
--- /dev/null
@@ -0,0 +1,5 @@
+using Content.Shared.DeviceLinking.Systems;
+
+namespace Content.Client.DeviceLinking.Systems;
+
+public sealed class RandomGateSystem : SharedRandomGateSystem;
diff --git a/Content.Client/DeviceLinking/UI/RandomGateBoundUserInterface.cs b/Content.Client/DeviceLinking/UI/RandomGateBoundUserInterface.cs
new file mode 100644 (file)
index 0000000..c8c97b8
--- /dev/null
@@ -0,0 +1,37 @@
+using Content.Shared.DeviceLinking;
+using JetBrains.Annotations;
+using Robust.Client.UserInterface;
+
+namespace Content.Client.DeviceLinking.UI;
+
+[UsedImplicitly]
+public sealed class RandomGateBoundUserInterface : BoundUserInterface
+{
+    private RandomGateSetupWindow? _window;
+
+    public RandomGateBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { }
+
+    protected override void Open()
+    {
+        base.Open();
+        _window = this.CreateWindow<RandomGateSetupWindow>();
+        _window.OnApplyPressed += OnProbabilityChanged;
+    }
+
+    private void OnProbabilityChanged(string value)
+    {
+        if (!float.TryParse(value, out var probability))
+            return;
+
+        SendPredictedMessage(new RandomGateProbabilityChangedMessage(probability));
+    }
+
+    protected override void UpdateState(BoundUserInterfaceState state)
+    {
+        base.UpdateState(state);
+        if (state is not RandomGateBoundUserInterfaceState castState || _window == null)
+            return;
+
+        _window.SetProbability(castState.SuccessProbability * 100);
+    }
+}
diff --git a/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml b/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml
new file mode 100644 (file)
index 0000000..d9273c9
--- /dev/null
@@ -0,0 +1,19 @@
+<controls:FancyWindow xmlns="https://spacestation14.io"
+            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+            xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
+            Title="{Loc 'random-gate-menu-setup'}"
+            MinSize="260 115">
+    <BoxContainer Orientation="Vertical" Margin="5" SeparationOverride="10">
+        <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
+            <Label Text="{Loc 'random-gate-menu-settings'}" VerticalAlignment="Center" />
+            <Control HorizontalExpand="True" />
+            <LineEdit Name="ProbabilityInput" MinSize="70 0" />
+        </BoxContainer>
+        <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
+            <Control HorizontalExpand="True" />
+            <Button Name="ApplyButton"
+                    Text="{Loc 'random-gate-menu-apply'}"
+                    HorizontalAlignment="Right" />
+        </BoxContainer>
+    </BoxContainer>
+</controls:FancyWindow>
diff --git a/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml.cs b/Content.Client/DeviceLinking/UI/RandomGateSetupWindow.xaml.cs
new file mode 100644 (file)
index 0000000..64e0690
--- /dev/null
@@ -0,0 +1,28 @@
+using Content.Client.UserInterface.Controls;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.DeviceLinking.UI;
+
+/// <summary>
+/// Window for setting up the random gate probability.
+/// </summary>
+[GenerateTypedNameReferences]
+public sealed partial class RandomGateSetupWindow : FancyWindow
+{
+    /// <summary>
+    /// Event triggered when the "Apply" button is pressed.
+    /// </summary>
+    public event Action<string>? OnApplyPressed;
+
+    public RandomGateSetupWindow()
+    {
+        RobustXamlLoader.Load(this);
+        ApplyButton.OnPressed += _ => OnApplyPressed?.Invoke(ProbabilityInput.Text);
+    }
+
+    public void SetProbability(float probability)
+    {
+        ProbabilityInput.Text = probability.ToString("0.00");
+    }
+}
diff --git a/Content.Server/DeviceLinking/Systems/RandomGateSystem.cs b/Content.Server/DeviceLinking/Systems/RandomGateSystem.cs
new file mode 100644 (file)
index 0000000..a961039
--- /dev/null
@@ -0,0 +1,32 @@
+using Content.Shared.DeviceLinking.Components;
+using Content.Shared.DeviceLinking.Events;
+using Content.Shared.DeviceLinking.Systems;
+using Robust.Shared.Random;
+
+namespace Content.Server.DeviceLinking.Systems;
+
+public sealed class RandomGateSystem : SharedRandomGateSystem
+{
+    [Dependency] private readonly DeviceLinkSystem _deviceLink = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        SubscribeLocalEvent<RandomGateComponent, SignalReceivedEvent>(OnSignalReceived);
+    }
+
+    private void OnSignalReceived(Entity<RandomGateComponent> ent, ref SignalReceivedEvent args)
+    {
+        if (args.Port != ent.Comp.InputPort)
+            return;
+
+        var output = _random.Prob(ent.Comp.SuccessProbability);
+        if (output != ent.Comp.LastOutput)
+        {
+            ent.Comp.LastOutput = output;
+            Dirty(ent);
+            _deviceLink.SendSignal(ent.Owner, ent.Comp.OutputPort, output);
+        }
+    }
+}
diff --git a/Content.Shared/DeviceLinking/Components/RandomGateComponent.cs b/Content.Shared/DeviceLinking/Components/RandomGateComponent.cs
new file mode 100644 (file)
index 0000000..0be9b6b
--- /dev/null
@@ -0,0 +1,35 @@
+using Robust.Shared.Prototypes;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.DeviceLinking.Components;
+
+/// <summary>
+/// A component for a random gate, which outputs a signal with a given probability.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class RandomGateComponent : Component
+{
+    /// <summary>
+    /// The input port for receiving signals.
+    /// </summary>
+    [DataField]
+    public ProtoId<SinkPortPrototype> InputPort = "RandomGateInput";
+
+    /// <summary>
+    /// The output port for sending signals.
+    /// </summary>
+    [DataField]
+    public ProtoId<SourcePortPrototype> OutputPort = "Output";
+
+    /// <summary>
+    /// The last output state of the gate.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public bool LastOutput;
+
+    /// <summary>
+    /// The probability (0.0 to 1.0) that the gate will output a signal.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public float SuccessProbability = 0.5f;
+}
diff --git a/Content.Shared/DeviceLinking/SharedRandomGateEvents.cs b/Content.Shared/DeviceLinking/SharedRandomGateEvents.cs
new file mode 100644 (file)
index 0000000..7d26ff8
--- /dev/null
@@ -0,0 +1,21 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.DeviceLinking;
+
+[Serializable, NetSerializable]
+public sealed class RandomGateBoundUserInterfaceState(float successProbability) : BoundUserInterfaceState
+{
+    public float SuccessProbability = successProbability;
+}
+
+[Serializable, NetSerializable]
+public sealed class RandomGateProbabilityChangedMessage(float probability) : BoundUserInterfaceMessage
+{
+    public float Probability = probability;
+}
+
+[Serializable, NetSerializable]
+public enum RandomGateUiKey : byte
+{
+    Key
+}
diff --git a/Content.Shared/DeviceLinking/Systems/SharedRandomGateSystem.cs b/Content.Shared/DeviceLinking/Systems/SharedRandomGateSystem.cs
new file mode 100644 (file)
index 0000000..74d25cd
--- /dev/null
@@ -0,0 +1,35 @@
+using Content.Shared.DeviceLinking.Components;
+using Content.Shared.UserInterface;
+
+namespace Content.Shared.DeviceLinking.Systems;
+
+public abstract class SharedRandomGateSystem : EntitySystem
+{
+    [Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
+
+    public override void Initialize()
+    {
+        SubscribeLocalEvent<RandomGateComponent, AfterActivatableUIOpenEvent>(OnAfterActivatableUIOpen);
+        SubscribeLocalEvent<RandomGateComponent, RandomGateProbabilityChangedMessage>(OnProbabilityChanged);
+    }
+
+    private void OnAfterActivatableUIOpen(Entity<RandomGateComponent> ent, ref AfterActivatableUIOpenEvent args)
+    {
+        UpdateUI(ent);
+    }
+
+    private void OnProbabilityChanged(Entity<RandomGateComponent> ent, ref RandomGateProbabilityChangedMessage args)
+    {
+        ent.Comp.SuccessProbability = Math.Clamp(args.Probability, 0f, 100f) / 100f;
+        Dirty(ent);
+        UpdateUI(ent);
+    }
+
+    private void UpdateUI(Entity<RandomGateComponent> ent)
+    {
+        if (!_ui.HasUi(ent.Owner, RandomGateUiKey.Key))
+            return;
+
+        _ui.SetUiState(ent.Owner, RandomGateUiKey.Key, new RandomGateBoundUserInterfaceState(ent.Comp.SuccessProbability));
+    }
+}
diff --git a/Resources/Locale/en-US/deviceLinking/randomgate.ftl b/Resources/Locale/en-US/deviceLinking/randomgate.ftl
new file mode 100644 (file)
index 0000000..664fdf5
--- /dev/null
@@ -0,0 +1,3 @@
+random-gate-menu-settings = Success Probability (%):
+random-gate-menu-setup = Random Gate Setup
+random-gate-menu-apply = Apply
index 7d91b418515f6b9bfe4b9da40d33e42b639752a5..aa34b415c5ccd338721abf389fd8f4d6cd3a917b 100644 (file)
@@ -86,3 +86,6 @@ signal-port-description-logic-memory-input = Signal to load into the memory cell
 
 signal-port-name-logic-enable = Enable
 signal-port-description-logic-enable = Only loads the input signal into the memory cell when HIGH.
+
+signal-port-name-logic-random-input = Input Signal
+signal-port-description-logic-random-input = Receives any signal to trigger a random output.
index 66e2bee27dbed874f2a4d5edf3acf50f3610e08a..45e15ba0d6d4c1b097249ac3121beea6ae691d86 100644 (file)
   name: signal-port-name-logic-enable
   description: signal-port-description-logic-enable
 
+- type: sinkPort
+  id: RandomGateInput
+  name: signal-port-name-logic-random-input
+  description: signal-port-description-logic-random-input
+  
 - type: sinkPort
   id: SetParticleDelta
   name: signal-port-name-set-particle-delta
index 3479d93fe083641316673c96e75f56e9a127c5b1..6540445f0d33d21fc9e22a9ab5c0be85d17accb8 100644 (file)
     - Output
   - type: Construction
     node: memory_cell
+    
+- type: entity
+  parent: BaseLogicItem
+  id: RandomGate
+  name: random gate
+  description: A logic gate that outputs a random signal when input changes.
+  components:
+  - type: Sprite
+    layers:
+    - state: base
+    - state: random_gate
+  - type: RandomGate
+  - type: DeviceLinkSink
+    ports:
+    - RandomGateInput
+  - type: DeviceLinkSource
+    ports:
+    - Output
+  - type: UserInterface
+    interfaces:
+      enum.RandomGateUiKey.Key:
+        type: RandomGateBoundUserInterface
+  - type: ActivatableUI
+    key: enum.RandomGateUiKey.Key
+  - type: Construction
+    node: random_gate
index bceed82123b681c6af30606ea6ada3fb9acd67a7..43c44eb9b1c162aba38dcac2ff91cf67737aafe2 100644 (file)
       - material: Cable
         amount: 2
         doAfter: 1
+    - to: random_gate
+      steps:
+      - material: MetalRod
+        amount: 1
+        doAfter: 1
+      - material: Cable
+        amount: 1
+        doAfter: 1
   - node: logic_gate
     entity: LogicGateOr
     edges:
       - !type:SpawnPrototype
         prototype: CableApcStack1
         amount: 2
+  - node: random_gate
+    entity: RandomGate
+    edges:
+    - to: empty
+      steps:
+      - tool: Prying
+        doAfter: 2
+      completed:
+      - !type:SpawnPrototype
+        prototype: CableApcStack1
+        amount: 1
+      - !type:SpawnPrototype
+        prototype: PartRodMetal1
+        amount: 1
index d5b363ebe5f84e78b7193c97603141a2b9b7f274..ed83abfc1a32b4d5309358a6eb4603b7361f99bc 100644 (file)
   targetNode: memory_cell
   category: construction-category-tools
   objectType: Item
+
+- type: construction
+  id: RandomGate
+  graph: LogicGate
+  startNode: start
+  targetNode: random_gate
+  category: construction-category-tools
+  objectType: Item
index ba7c7ea232df7a69b8217d92245f42e44fec54e1..eb5ae78a621d78f07ec6624b0ccc484ed8bb6c31 100644 (file)
@@ -1,7 +1,7 @@
 {
   "version": 1,
   "license": "CC-BY-SA-3.0",
-  "copyright": "or.png originally created by Kevin Zheng, 2022. All are modified by deltanedas (github) for SS14, 2024. Sprites logic_a logic_b logic_o were made by 0tito (github) for SS14",
+  "copyright": "or.png originally created by Kevin Zheng, 2022. All are modified by deltanedas (github) for SS14, 2024. Sprites logic_a logic_b logic_o were made by 0tito (github) for SS14. 2025, added random_gate.png by borsh.",
   "size": {
     "x": 32,
     "y": 32
@@ -51,6 +51,9 @@
     },
     {
       "name": "memory_cell"
+    },
+    {
+      "name": "random_gate"
     }
   ]
 }
diff --git a/Resources/Textures/Objects/Devices/gates.rsi/random_gate.png b/Resources/Textures/Objects/Devices/gates.rsi/random_gate.png
new file mode 100644 (file)
index 0000000..f2f4642
Binary files /dev/null and b/Resources/Textures/Objects/Devices/gates.rsi/random_gate.png differ