]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Cargo Pallet Sale Console (#14422)
authorCheckraze <71046427+Cheackraze@users.noreply.github.com>
Mon, 13 Mar 2023 20:36:35 +0000 (16:36 -0400)
committerGitHub <noreply@github.com>
Mon, 13 Mar 2023 20:36:35 +0000 (16:36 -0400)
Content.Client/Cargo/BUI/CargoPalletConsoleBoundUserInterface.cs [new file with mode: 0644]
Content.Client/Cargo/UI/CargoPalletMenu.xaml [new file with mode: 0644]
Content.Client/Cargo/UI/CargoPalletMenu.xaml.cs [new file with mode: 0644]
Content.Server/Cargo/Components/CargoPalletConsoleComponent.cs [new file with mode: 0644]
Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs
Content.Shared/Cargo/BUI/CargoPalletConsoleInterfaceState.cs [new file with mode: 0644]
Content.Shared/Cargo/Events/CargoPalletAppraiseMessage.cs [new file with mode: 0644]
Content.Shared/Cargo/Events/CargoPalletSellMessage.cs [new file with mode: 0644]
Content.Shared/Cargo/SharedCargoSystem.cs
Resources/Locale/en-US/cargo/cargo-pallet-console-component.ftl [new file with mode: 0644]
Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml

diff --git a/Content.Client/Cargo/BUI/CargoPalletConsoleBoundUserInterface.cs b/Content.Client/Cargo/BUI/CargoPalletConsoleBoundUserInterface.cs
new file mode 100644 (file)
index 0000000..3c7b7fe
--- /dev/null
@@ -0,0 +1,56 @@
+using Content.Client.Cargo.UI;
+using Content.Shared.Cargo.BUI;
+using Content.Shared.Cargo.Events;
+using Robust.Client.GameObjects;
+
+namespace Content.Client.Cargo.BUI;
+
+public sealed class CargoPalletConsoleBoundUserInterface : BoundUserInterface
+{
+    private CargoPalletMenu? _menu;
+
+    public CargoPalletConsoleBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey) {}
+
+    protected override void Open()
+    {
+        base.Open();
+
+        _menu = new CargoPalletMenu();
+        _menu.AppraiseRequested += OnAppraisal;
+        _menu.SellRequested += OnSell;
+        _menu.OnClose += Close;
+
+        _menu.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (disposing)
+        {
+            _menu?.Dispose();
+        }
+    }
+
+    private void OnAppraisal()
+    {
+        SendMessage(new CargoPalletAppraiseMessage());
+    }
+
+    private void OnSell()
+    {
+        SendMessage(new CargoPalletSellMessage());
+    }
+
+    protected override void UpdateState(BoundUserInterfaceState state)
+    {
+        base.UpdateState(state);
+
+        if (state is not CargoPalletConsoleInterfaceState palletState)
+            return;
+
+        _menu?.SetEnabled(palletState.Enabled);
+        _menu?.SetAppraisal(palletState.Appraisal);
+        _menu?.SetCount(palletState.Count);
+    }
+}
diff --git a/Content.Client/Cargo/UI/CargoPalletMenu.xaml b/Content.Client/Cargo/UI/CargoPalletMenu.xaml
new file mode 100644 (file)
index 0000000..489c6cb
--- /dev/null
@@ -0,0 +1,25 @@
+<controls:FancyWindow xmlns="https://spacestation14.io"
+            xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
+            xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
+            SetSize="300 150"
+            MinSize="300 150">
+    <BoxContainer Orientation="Vertical">
+        <BoxContainer Orientation="Horizontal">
+            <Label Text="{Loc 'cargo-pallet-menu-appraisal-label'}"
+                   StyleClasses="LabelKeyText" />
+            <Label Name="AppraisalLabel"
+                   Text="{Loc 'cargo-pallet-menu-no-goods-text'}" />
+        </BoxContainer>
+        <BoxContainer Orientation="Horizontal">
+            <Label Text="{Loc 'cargo-pallet-menu-count-label'}"
+                   StyleClasses="LabelKeyText" />
+            <Label Name="CountLabel"
+                   Text="{Loc 'cargo-pallet-menu-no-goods-text'}" />
+        </BoxContainer>
+        <Button Name="AppraiseButton"
+                Text="{Loc 'cargo-pallet-appraise-button'}"/>
+        <Button Name="SellButton"
+                Text="{Loc 'cargo-pallet-sell-button'}"/>
+        <TextureButton VerticalExpand="True" />
+    </BoxContainer>
+</controls:FancyWindow>
diff --git a/Content.Client/Cargo/UI/CargoPalletMenu.xaml.cs b/Content.Client/Cargo/UI/CargoPalletMenu.xaml.cs
new file mode 100644 (file)
index 0000000..c46ecf5
--- /dev/null
@@ -0,0 +1,47 @@
+using Content.Client.UserInterface.Controls;
+using Content.Shared.Cargo;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.Cargo.UI;
+
+[GenerateTypedNameReferences]
+public sealed partial class CargoPalletMenu : FancyWindow
+{
+    public Action? SellRequested;
+    public Action? AppraiseRequested;
+
+    public CargoPalletMenu()
+    {
+        RobustXamlLoader.Load(this);
+        SellButton.OnPressed += OnSellPressed;
+        AppraiseButton.OnPressed += OnAppraisePressed;
+        Title = Loc.GetString("cargo-pallet-console-menu-title");
+    }
+
+    public void SetAppraisal(int amount)
+    {
+        AppraisalLabel.Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", amount.ToString()));
+    }
+
+    public void SetCount(int count)
+    {
+        CountLabel.Text = count.ToString();
+    }
+    public void SetEnabled(bool enabled)
+    {
+        AppraiseButton.Disabled = !enabled;
+        SellButton.Disabled = !enabled;
+    }
+
+    private void OnSellPressed(BaseButton.ButtonEventArgs obj)
+    {
+        SellRequested?.Invoke();
+    }
+
+    private void OnAppraisePressed(BaseButton.ButtonEventArgs obj)
+    {
+        AppraiseRequested?.Invoke();
+    }
+}
diff --git a/Content.Server/Cargo/Components/CargoPalletConsoleComponent.cs b/Content.Server/Cargo/Components/CargoPalletConsoleComponent.cs
new file mode 100644 (file)
index 0000000..86102bb
--- /dev/null
@@ -0,0 +1,13 @@
+using Content.Server.Cargo.Systems;
+using Content.Shared.Stacks;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+
+namespace Content.Server.Cargo.Components;
+
+[RegisterComponent]
+[Access(typeof(CargoSystem))]
+public sealed class CargoPalletConsoleComponent : Component
+{
+    [ViewVariables(VVAccess.ReadWrite), DataField("cashType", customTypeSerializer:typeof(PrototypeIdSerializer<StackPrototype>))]
+    public string CashType = "Credit";
+}
index fbf7bda83bb1b301a3f5f7701627feeedb361cf3..3bd90aeb3eb1f4e5d5a08f56154722690c163373 100644 (file)
@@ -7,6 +7,8 @@ using Content.Server.UserInterface;
 using Content.Server.Paper;
 using Content.Server.Shuttles.Systems;
 using Content.Server.Station.Components;
+using Content.Server.Stack;
+using Content.Shared.Stacks;
 using Content.Shared.Cargo;
 using Content.Shared.Cargo.BUI;
 using Content.Shared.Cargo.Components;
@@ -27,6 +29,8 @@ using Robust.Shared.Player;
 using Robust.Shared.Random;
 using Robust.Shared.Timing;
 using Robust.Shared.Utility;
+using Robust.Shared.Prototypes;
+using Content.Shared.Coordinates;
 
 namespace Content.Server.Cargo.Systems;
 
@@ -40,13 +44,14 @@ public sealed partial class CargoSystem
     [Dependency] private readonly IGameTiming _timing = default!;
     [Dependency] private readonly IMapManager _mapManager = default!;
     [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
     [Dependency] private readonly EntityLookupSystem _lookup = default!;
     [Dependency] private readonly MapLoaderSystem _map = default!;
     [Dependency] private readonly MobStateSystem _mobState = default!;
     [Dependency] private readonly PricingSystem _pricing = default!;
     [Dependency] private readonly ShuttleConsoleSystem _console = default!;
     [Dependency] private readonly ShuttleSystem _shuttle = default!;
-
+    [Dependency] private readonly StackSystem _stack = default!;
     public MapId? CargoMap { get; private set; }
 
     private const float CallOffset = 50f;
@@ -69,6 +74,10 @@ public sealed partial class CargoSystem
         SubscribeLocalEvent<CargoShuttleConsoleComponent, CargoCallShuttleMessage>(OnCargoShuttleCall);
         SubscribeLocalEvent<CargoShuttleConsoleComponent, CargoRecallShuttleMessage>(RecallCargoShuttle);
 
+        SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletSellMessage>(OnPalletSale);
+        SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletAppraiseMessage>(OnPalletAppraise);
+        SubscribeLocalEvent<CargoPalletConsoleComponent, BoundUIOpenedEvent>(OnPalletUIOpen);
+
         SubscribeLocalEvent<CargoPilotConsoleComponent, ConsoleShuttleEvent>(OnCargoGetConsole);
         SubscribeLocalEvent<CargoPilotConsoleComponent, AfterActivatableUIOpenEvent>(OnCargoPilotConsoleOpen);
         SubscribeLocalEvent<CargoPilotConsoleComponent, BoundUIClosedEvent>(OnCargoPilotConsoleClose);
@@ -144,6 +153,48 @@ public sealed partial class CargoSystem
         }
     }
 
+    private void UpdatePalletConsoleInterface(EntityUid uid, CargoPalletConsoleComponent component)
+    {
+        var bui = _uiSystem.GetUi(component.Owner, CargoPalletConsoleUiKey.Sale);
+        if (Transform(uid).GridUid is not EntityUid gridUid)
+        {
+            _uiSystem.SetUiState(bui,
+            new CargoPalletConsoleInterfaceState(0, 0, false));
+            return;
+        }
+        GetPalletGoods(gridUid, out var toSell, out var amount);
+        _uiSystem.SetUiState(bui,
+            new CargoPalletConsoleInterfaceState((int) amount, toSell.Count, true));
+    }
+
+    private void OnPalletUIOpen(EntityUid uid, CargoPalletConsoleComponent component, BoundUIOpenedEvent args)
+    {
+        var player = args.Session.AttachedEntity;
+
+        if (player == null)
+            return;
+
+        UpdatePalletConsoleInterface(uid, component);
+    }
+
+    /// <summary>
+    /// Ok so this is just the same thing as opening the UI, its a refresh button.
+    /// I know this would probably feel better if it were like predicted and dynamic as pallet contents change
+    /// However.
+    /// I dont want it to explode if cargo uses a conveyor to move 8000 pineapple slices or whatever, they are
+    /// known for their entity spam i wouldnt put it past them
+    /// </summary>
+
+    private void OnPalletAppraise(EntityUid uid, CargoPalletConsoleComponent component, CargoPalletAppraiseMessage args)
+    {
+        var player = args.Session.AttachedEntity;
+
+        if (player == null)
+            return;
+
+        UpdatePalletConsoleInterface(uid, component);
+    }
+
     private void OnCargoShuttleConsoleStartup(EntityUid uid, CargoShuttleConsoleComponent component, ComponentStartup args)
     {
         var station = _station.GetOwningStation(uid);
@@ -209,7 +260,7 @@ public sealed partial class CargoSystem
         if (component == null || shuttle == null || component.Orders.Count == 0)
             return orders;
 
-        var spaceRemaining = GetCargoSpace(shuttle);
+        var spaceRemaining = GetCargoSpace(shuttle.Owner);
         for( var i = 0; i < component.Orders.Count && spaceRemaining > 0; i++)
         {
             var order = component.Orders[i];
@@ -238,19 +289,19 @@ public sealed partial class CargoSystem
     /// <summary>
     /// Get the amount of space the cargo shuttle can fit for orders.
     /// </summary>
-    private int GetCargoSpace(CargoShuttleComponent component)
+    private int GetCargoSpace(EntityUid gridUid)
     {
-        var space = GetCargoPallets(component).Count;
+        var space = GetCargoPallets(gridUid).Count;
         return space;
     }
 
-    private List<CargoPalletComponent> GetCargoPallets(CargoShuttleComponent component)
+    private List<CargoPalletComponent> GetCargoPallets(EntityUid gridUid)
     {
         var pads = new List<CargoPalletComponent>();
 
         foreach (var (comp, compXform) in EntityQuery<CargoPalletComponent, TransformComponent>(true))
         {
-            if (compXform.ParentUid != component.Owner ||
+            if (compXform.ParentUid != gridUid ||
                 !compXform.Anchored) continue;
 
             pads.Add(comp);
@@ -306,14 +357,25 @@ public sealed partial class CargoSystem
         _sawmill.Info($"Added cargo shuttle to {ToPrettyString(shuttleUid)}");
     }
 
-    private void SellPallets(CargoShuttleComponent component, StationBankAccountComponent bank)
+    private void SellPallets(EntityUid gridUid, out double amount)
     {
-        double amount = 0;
-        var toSell = new HashSet<EntityUid>();
+        GetPalletGoods(gridUid, out var toSell, out amount);
+
+        _sawmill.Debug($"Cargo sold {toSell.Count} entities for {amount}");
+
+        foreach (var ent in toSell)
+        {
+            Del(ent);
+        }
+    }
+
+    private void GetPalletGoods(EntityUid gridUid, out HashSet<EntityUid> toSell, out double amount)
+    {
+        amount = 0;
         var xformQuery = GetEntityQuery<TransformComponent>();
         var blacklistQuery = GetEntityQuery<CargoSellBlacklistComponent>();
-
-        foreach (var pallet in GetCargoPallets(component))
+        toSell = new HashSet<EntityUid>();
+        foreach (var pallet in GetCargoPallets(gridUid))
         {
             // Containers should already get the sell price of their children so can skip those.
             foreach (var ent in _lookup.GetEntitiesIntersecting(pallet.Owner, LookupFlags.Dynamic | LookupFlags.Sundries | LookupFlags.Approximate))
@@ -336,14 +398,6 @@ public sealed partial class CargoSystem
                 amount += price;
             }
         }
-
-        bank.Balance += (int) amount;
-        _sawmill.Debug($"Cargo sold {toSell.Count} entities for {amount}");
-
-        foreach (var ent in toSell)
-        {
-            Del(ent);
-        }
     }
 
     private void SendToCargoMap(EntityUid uid, CargoShuttleComponent? component = null)
@@ -424,7 +478,7 @@ public sealed partial class CargoSystem
     {
         var xformQuery = GetEntityQuery<TransformComponent>();
 
-        var pads = GetCargoPallets(shuttle);
+        var pads = GetCargoPallets(shuttle.Owner);
         while (pads.Count > 0)
         {
             var coordinates = new EntityCoordinates(shuttle.Owner, xformQuery.GetComponent(_random.PickAndTake(pads).Owner).LocalPosition);
@@ -435,13 +489,34 @@ public sealed partial class CargoSystem
         }
     }
 
+    private void OnPalletSale(EntityUid uid, CargoPalletConsoleComponent component, CargoPalletSellMessage args)
+    {
+        var player = args.Session.AttachedEntity;
+
+        if (player == null)
+            return;
+
+        var bui = _uiSystem.GetUi(component.Owner, CargoPalletConsoleUiKey.Sale);
+        if (Transform(uid).GridUid is not EntityUid gridUid)
+        {
+            _uiSystem.SetUiState(bui,
+            new CargoPalletConsoleInterfaceState(0, 0, false));
+            return;
+        }
+
+        SellPallets(gridUid, out var price);
+        var stackPrototype = _prototypeManager.Index<StackPrototype>(component.CashType);
+        _stack.Spawn((int)price, stackPrototype, uid.ToCoordinates());
+        UpdatePalletConsoleInterface(uid, component);
+    }
+
     private void RecallCargoShuttle(EntityUid uid, CargoShuttleConsoleComponent component, CargoRecallShuttleMessage args)
     {
         var player = args.Session.AttachedEntity;
 
         if (player == null) return;
 
-        var stationUid = _station.GetOwningStation(component.Owner);
+        var stationUid = _station.GetOwningStation(uid);
 
         if (!TryComp<StationCargoOrderDatabaseComponent>(stationUid, out var orderDatabase) ||
             !TryComp<StationBankAccountComponent>(stationUid, out var bank)) return;
@@ -465,7 +540,8 @@ public sealed partial class CargoSystem
             return;
         }
 
-        SellPallets(shuttle, bank);
+        SellPallets((EntityUid) orderDatabase.Shuttle, out double price);
+        bank.Balance += (int) price;
         _console.RefreshShuttleConsoles();
         SendToCargoMap(orderDatabase.Shuttle.Value);
     }
diff --git a/Content.Shared/Cargo/BUI/CargoPalletConsoleInterfaceState.cs b/Content.Shared/Cargo/BUI/CargoPalletConsoleInterfaceState.cs
new file mode 100644 (file)
index 0000000..810801c
--- /dev/null
@@ -0,0 +1,29 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.BUI;
+
+[NetSerializable, Serializable]
+public sealed class CargoPalletConsoleInterfaceState : BoundUserInterfaceState
+{
+    /// <summary>
+    /// estimated apraised value of all the entities on top of pallets on the same grid as the console
+    /// </summary>
+    public int Appraisal;
+
+    /// <summary>
+    /// number of entities on top of pallets on the same grid as the console
+    /// </summary>
+    public int Count;
+
+    /// <summary>
+    /// are the buttons enabled
+    /// </summary>
+    public bool Enabled;
+
+    public CargoPalletConsoleInterfaceState(int appraisal, int count, bool enabled)
+    {
+        Appraisal = appraisal;
+        Count = count;
+        Enabled = enabled;
+    }
+}
diff --git a/Content.Shared/Cargo/Events/CargoPalletAppraiseMessage.cs b/Content.Shared/Cargo/Events/CargoPalletAppraiseMessage.cs
new file mode 100644 (file)
index 0000000..a5e2455
--- /dev/null
@@ -0,0 +1,12 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.Events;
+
+/// <summary>
+/// Raised on a client request to refresh the pallet console
+/// </summary>
+[Serializable, NetSerializable]
+public sealed class CargoPalletAppraiseMessage : BoundUserInterfaceMessage
+{
+
+}
diff --git a/Content.Shared/Cargo/Events/CargoPalletSellMessage.cs b/Content.Shared/Cargo/Events/CargoPalletSellMessage.cs
new file mode 100644 (file)
index 0000000..ffb7595
--- /dev/null
@@ -0,0 +1,12 @@
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Cargo.Events;
+
+/// <summary>
+/// Raised on a client request pallet sale
+/// </summary>
+[Serializable, NetSerializable]
+public sealed class CargoPalletSellMessage : BoundUserInterfaceMessage
+{
+
+}
index 2e2546dadb7dfd0a643e34b1ad57b8e1cb286840..98ea3bc00c20ecea3a7bf69127c3230bac05cbda 100644 (file)
@@ -10,6 +10,12 @@ public enum CargoConsoleUiKey : byte
     Telepad
 }
 
+[NetSerializable, Serializable]
+public enum CargoPalletConsoleUiKey : byte
+{
+    Sale
+}
+
 public abstract class SharedCargoSystem : EntitySystem {}
 
 [Serializable, NetSerializable]
diff --git a/Resources/Locale/en-US/cargo/cargo-pallet-console-component.ftl b/Resources/Locale/en-US/cargo/cargo-pallet-console-component.ftl
new file mode 100644 (file)
index 0000000..b9fbd0f
--- /dev/null
@@ -0,0 +1,7 @@
+
+# Cargo pallet sale console
+cargo-pallet-console-menu-title = Cargo sale console
+cargo-pallet-menu-appraisal-label = Estimated Value:{" "}
+cargo-pallet-menu-count-label = Number of sale items:{" "}
+cargo-pallet-appraise-button = Appraise
+cargo-pallet-sell-button = Sell
index 418858aa834593346ec28c47b70349c65d787a39..4d586521da75fb62fbb0313ebf5819233c18a313 100644 (file)
     interfaces:
       - key: enum.SurveillanceCameraMonitorUiKey.Key
         type: SurveillanceCameraMonitorBoundUserInterface
+
+- type: entity
+  id: ComputerPalletConsole
+  parent: BaseComputer
+  name: cargo sale computer
+  description: Used to sell goods loaded onto cargo pallets
+  components:
+  - type: Sprite
+    layers:
+    - map: ["computerLayerBody"]
+      state: computer
+    - map: ["computerLayerKeyboard"]
+      state: generic_keyboard
+    - map: ["computerLayerScreen"]
+      state: request
+    - map: ["computerLayerKeys"]
+      state: tech_key
+  - type: CargoPalletConsole
+  - type: ActivatableUI
+    key: enum.CargoPalletConsoleUiKey.Sale
+  - type: UserInterface
+    interfaces:
+    - key: enum.CargoPalletConsoleUiKey.Sale
+      type: CargoPalletConsoleBoundUserInterface
+  - type: Computer
+    board: CargoRequestComputerCircuitboard
+  - type: PointLight
+    radius: 1.5
+    energy: 1.6
+    color: "#b89f25"
\ No newline at end of file