diff --git a/Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs b/Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs index dfc61c0527..03246cfdfe 100644 --- a/Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs +++ b/Content.Client/Cargo/UI/CargoConsoleMenu.xaml.cs @@ -203,6 +203,9 @@ namespace Content.Client.Cargo.UI /// public void PopulateOrders(IEnumerable orders) { + if (!_orderConsoleQuery.TryComp(_owner, out var orderConsole)) + return; + Requests.DisposeAllChildren(); foreach (var order in orders) @@ -237,6 +240,7 @@ namespace Content.Client.Cargo.UI row.Cancel.OnPressed += (args) => { OnOrderCanceled?.Invoke(args); }; // TODO: Disable based on access. + row.SetApproveVisible(orderConsole.Mode != CargoOrderConsoleMode.SendToPrimary); row.Approve.OnPressed += (args) => { OnOrderApproved?.Invoke(args); }; Requests.AddChild(row); } @@ -290,8 +294,8 @@ namespace Content.Client.Cargo.UI TransferSpinBox.Value > bankAccount.Accounts[orderConsole.Account] * orderConsole.TransferLimit || _timing.CurTime < orderConsole.NextAccountActionTime; - OrdersSpacer.Visible = !orderConsole.SlipPrinter; - Orders.Visible = !orderConsole.SlipPrinter; + OrdersSpacer.Visible = orderConsole.Mode != CargoOrderConsoleMode.PrintSlip; + Orders.Visible = orderConsole.Mode != CargoOrderConsoleMode.PrintSlip; } } } diff --git a/Content.Client/Cargo/UI/CargoOrderRow.xaml.cs b/Content.Client/Cargo/UI/CargoOrderRow.xaml.cs index 77abcf4069..d2a23b5a2e 100644 --- a/Content.Client/Cargo/UI/CargoOrderRow.xaml.cs +++ b/Content.Client/Cargo/UI/CargoOrderRow.xaml.cs @@ -14,5 +14,15 @@ namespace Content.Client.Cargo.UI { RobustXamlLoader.Load(this); } + + public void SetApproveVisible(bool visible) + { + Approve.Visible = visible; + + if (visible) + Cancel.AddStyleClass("OpenLeft"); + else + Cancel.RemoveStyleClass("OpenLeft"); + } } } diff --git a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs index e6248f1772..aecba50dff 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.Orders.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.Orders.cs @@ -100,7 +100,7 @@ namespace Content.Server.Cargo.Systems { OnInteractUsingCash(uid, component, ref args); } - else if (TryComp(args.Used, out var slip) && !component.SlipPrinter) + else if (TryComp(args.Used, out var slip) && component.Mode == CargoOrderConsoleMode.DirectOrder) { OnInteractUsingSlip((uid, component), ref args, slip); } @@ -144,7 +144,7 @@ namespace Content.Server.Cargo.Systems if (args.Actor is not { Valid: true } player) return; - if (component.SlipPrinter) + if (component.Mode != CargoOrderConsoleMode.DirectOrder) return; if (!_accessReaderSystem.IsAllowed(player, uid)) @@ -181,7 +181,7 @@ namespace Content.Server.Cargo.Systems return; } - var amount = GetOutstandingOrderCount(orderDatabase, order.Account); + var amount = GetOutstandingOrderCount((station.Value, orderDatabase), order.Account); var capacity = orderDatabase.Capacity; // Too many orders, avoid them getting spammed in the UI. @@ -312,7 +312,7 @@ namespace Content.Server.Cargo.Systems { var station = _station.GetOwningStation(uid); - if (component.SlipPrinter) + if (component.Mode != CargoOrderConsoleMode.DirectOrder) return; if (!TryGetOrderDatabase(station, out var orderDatabase)) @@ -367,6 +367,9 @@ namespace Content.Server.Cargo.Systems if (!TryGetOrderDatabase(stationUid, out var orderDatabase)) return; + if (!TryComp(stationUid, out var bank)) + return; + if (!_protoMan.TryIndex(args.CargoProductId, out var product)) { Log.Error($"Tried to add invalid cargo product {args.CargoProductId} as order!"); @@ -376,15 +379,17 @@ namespace Content.Server.Cargo.Systems if (!GetAvailableProducts((uid, component)).Contains(args.CargoProductId)) return; - if (component.SlipPrinter) + if (component.Mode == CargoOrderConsoleMode.PrintSlip) { OnAddOrderMessageSlipPrinter(uid, component, args, product); return; } + var targetAccount = component.Mode == CargoOrderConsoleMode.SendToPrimary ? bank.PrimaryAccount : component.Account; + var data = GetOrderData(args, product, GenerateOrderId(orderDatabase), component.Account); - if (!TryAddOrder(stationUid.Value, component.Account, data, orderDatabase)) + if (!TryAddOrder(stationUid.Value, targetAccount, data, orderDatabase)) { PlayDenySound(uid, component); return; @@ -419,15 +424,33 @@ namespace Content.Server.Cargo.Systems CargoConsoleUiKey.Orders, new CargoConsoleInterfaceState( MetaData(station.Value).EntityName, - GetOutstandingOrderCount(orderDatabase, console.Account), + GetOutstandingOrderCount((station!.Value, orderDatabase), console.Account), orderDatabase.Capacity, GetNetEntity(station.Value), - orderDatabase.Orders[console.Account], + RelevantOrders((station!.Value, orderDatabase), (consoleUid, console)), GetAvailableProducts((consoleUid, console)) )); } } + /// + /// Gets orders relevant to this account, i.e. orders on the account directly or orders on behalf of the account in the primary account. + /// + private List RelevantOrders(Entity station, Entity console) + { + if (!TryComp(station, out var bank)) + return []; + + var ourOrders = station.Comp.Orders[console.Comp.Account]; + + if (console.Comp.Account == bank.PrimaryAccount) + return ourOrders; + + var otherOrders = station.Comp.Orders[bank.PrimaryAccount].Where(order => order.Account == console.Comp.Account); + + return ourOrders.Concat(otherOrders).ToList(); + } + private void ConsolePopup(EntityUid actor, string text) { _popup.PopupCursor(text, actor); @@ -447,17 +470,32 @@ namespace Content.Server.Cargo.Systems return new CargoOrderData(id, cargoProduct.Product, cargoProduct.Name, cargoProduct.Cost, args.Amount, args.Requester, args.Reason, account); } - public static int GetOutstandingOrderCount(StationCargoOrderDatabaseComponent component, ProtoId account) + public int GetOutstandingOrderCount(Entity station, ProtoId account) { var amount = 0; - foreach (var order in component.Orders[account]) + if (!TryComp(station, out var bank)) + return amount; + + foreach (var order in station.Comp.Orders[account]) { if (!order.Approved) continue; amount += order.OrderQuantity - order.NumDispatched; } + if (account == bank.PrimaryAccount) + return amount; + + foreach (var order in station.Comp.Orders[bank.PrimaryAccount]) + { + if (order.Account != account) + continue; + if (!order.Approved) + continue; + amount += order.OrderQuantity - order.NumDispatched; + } + return amount; } diff --git a/Content.Server/StationEvents/Events/CargoGiftsRule.cs b/Content.Server/StationEvents/Events/CargoGiftsRule.cs index f8a718a536..91baf2ecad 100644 --- a/Content.Server/StationEvents/Events/CargoGiftsRule.cs +++ b/Content.Server/StationEvents/Events/CargoGiftsRule.cs @@ -53,7 +53,7 @@ public sealed class CargoGiftsRule : StationEventSystem } // Add some presents - var outstanding = CargoSystem.GetOutstandingOrderCount(cargoDb, component.Account); + var outstanding = _cargoSystem.GetOutstandingOrderCount((station.Value, cargoDb), component.Account); while (outstanding < cargoDb.Capacity - component.OrderSpaceToLeave && component.Gifts.Count > 0) { // I wish there was a nice way to pop this diff --git a/Content.Shared/Cargo/Components/CargoOrderConsoleComponent.cs b/Content.Shared/Cargo/Components/CargoOrderConsoleComponent.cs index e930fbda23..1d3aa6fc9e 100644 --- a/Content.Shared/Cargo/Components/CargoOrderConsoleComponent.cs +++ b/Content.Shared/Cargo/Components/CargoOrderConsoleComponent.cs @@ -104,10 +104,10 @@ public sealed partial class CargoOrderConsoleComponent : Component public static readonly ProtoId BaseAnnouncementChannel = "Supply"; /// - /// If set to true, restricts this console from ordering and has it print slips instead + /// The behaviour of the cargo console regarding orders /// [DataField] - public bool SlipPrinter; + public CargoOrderConsoleMode Mode = CargoOrderConsoleMode.DirectOrder; /// /// The time at which the console will be able to print a slip again. @@ -146,6 +146,26 @@ public sealed partial class CargoOrderConsoleComponent : Component public TimeSpan DenySoundDelay = TimeSpan.FromSeconds(2); } +/// +/// The behaviour of the cargo order console +/// +[Serializable, NetSerializable] +public enum CargoOrderConsoleMode : byte +{ + /// + /// Place orders directly + /// + DirectOrder, + /// + /// Print a slip to be inserted into a DirectOrder console + /// + PrintSlip, + /// + /// Transfers the order to the primary account + /// + SendToPrimary, +} + /// /// Withdraw funds from an account /// diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index ca9b5fabba..bc50c4fe39 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -931,7 +931,7 @@ account: Engineering announcementChannel: Engineering removeLimitAccess: [ "ChiefEngineer" ] - slipPrinter: true + mode: SendToPrimary - type: ActiveRadio channels: - Engineering @@ -964,7 +964,7 @@ account: Medical announcementChannel: Medical removeLimitAccess: [ "ChiefMedicalOfficer" ] - slipPrinter: true + mode: SendToPrimary - type: ActiveRadio channels: - Medical @@ -997,7 +997,7 @@ account: Science announcementChannel: Science removeLimitAccess: [ "ResearchDirector" ] - slipPrinter: true + mode: SendToPrimary - type: ActiveRadio channels: - Science @@ -1030,7 +1030,7 @@ account: Security announcementChannel: Security removeLimitAccess: [ "HeadOfSecurity" ] - slipPrinter: true + mode: SendToPrimary - type: ActiveRadio channels: - Security @@ -1063,7 +1063,7 @@ account: Service announcementChannel: Service removeLimitAccess: [ "HeadOfPersonnel" ] - slipPrinter: true + mode: SendToPrimary - type: ActiveRadio channels: - Service