]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Make funding allocation computer more configurable (#36790)
authorpathetic meowmeow <uhhadd@gmail.com>
Tue, 22 Apr 2025 12:34:53 +0000 (08:34 -0400)
committerGitHub <noreply@github.com>
Tue, 22 Apr 2025 12:34:53 +0000 (08:34 -0400)
* Make funding allocation computer more configurable

* admin logging

* unused

* ccvar enabled

---------

Co-authored-by: ScarKy0 <scarky0@onet.eu>
Content.Client/Cargo/BUI/FundingAllocationConsoleBoundUserInterface.cs
Content.Client/Cargo/UI/FundingAllocationMenu.xaml
Content.Client/Cargo/UI/FundingAllocationMenu.xaml.cs
Content.Server/Cargo/Systems/CargoSystem.Funds.cs
Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs
Content.Server/Cargo/Systems/CargoSystem.cs
Content.Shared/CCVar/CCVars.Cargo.cs [new file with mode: 0644]
Content.Shared/Cargo/Components/FundingAllocationConsoleComponent.cs
Content.Shared/Cargo/Components/OverrideSellComponent.cs
Content.Shared/Cargo/Components/StationBankAccountComponent.cs
Resources/Locale/en-US/cargo/cargo-console-component.ftl

index eb65be40d37c214b7fe5254d9bc670c0975f2010..49a545b480acedf3314f2d556d0f9fc40877dfc5 100644 (file)
@@ -17,9 +17,9 @@ public sealed class FundingAllocationConsoleBoundUserInterface(EntityUid owner,
 
         _menu = this.CreateWindow<FundingAllocationMenu>();
 
-        _menu.OnSavePressed += d =>
+        _menu.OnSavePressed += (dicts, primary, lockbox) =>
         {
-            SendMessage(new SetFundingAllocationBuiMessage(d));
+            SendMessage(new SetFundingAllocationBuiMessage(dicts, primary, lockbox));
         };
     }
 
index 0686ea77d81ae33ffc79c9f668f7f1eeb2d5bb22..62f0ae924ac4cb11fa3085e500b98e1b64d10a78 100644 (file)
@@ -1,15 +1,18 @@
 <controls:FancyWindow xmlns="https://spacestation14.io"
                       xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
                       xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
-                      Title="{Loc 'cargo-funding-alloc-console-menu-title'}"
-                      SetSize="680 310"
-                      MinSize="680 310">
+                      Title="{Loc 'cargo-funding-alloc-console-menu-title'}">
     <BoxContainer Orientation="Vertical"
                   VerticalExpand="True"
                   HorizontalExpand="True"
                   Margin="10 5 10 10">
-        <Label Name="HelpLabel" HorizontalAlignment="Center" StyleClasses="LabelSubText"/>
-        <Control MinHeight="10"/>
+        <controls:TableContainer Columns="2" HorizontalExpand="True" VerticalExpand="True">
+            <RichTextLabel Name="PrimaryCutLabel" Text="{Loc 'cargo-funding-alloc-console-label-primary-cut'}"/>
+            <SpinBox Name="PrimaryCut"/>
+            <RichTextLabel Name="LockboxCutLabel" Text="{Loc 'cargo-funding-alloc-console-label-lockbox-cut'}"/>
+            <SpinBox Name="LockboxCut"/>
+        </controls:TableContainer>
+        <Label Name="HelpLabel" HorizontalAlignment="Center" StyleClasses="LabelSubText" Margin="0 10"/>
         <PanelContainer VerticalExpand="True" HorizontalExpand="True" VerticalAlignment="Top" MaxHeight="250">
             <PanelContainer.PanelOverride>
                 <graphics:StyleBoxFlat BackgroundColor="#1B1B1E"/>
index d605d4c48ef19ebbcbfb0193065cc93807b36511..fdba5f5bd832c1a1fcf5d009eba8294a3b5eaa97 100644 (file)
@@ -1,12 +1,15 @@
+using System.Collections.Generic;
 using System.Linq;
 using Content.Client.Message;
 using Content.Client.UserInterface.Controls;
 using Content.Shared.Cargo.Components;
 using Content.Shared.Cargo.Prototypes;
+using Content.Shared.CCVar;
 using Robust.Client.AutoGenerated;
 using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Configuration;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Timing;
 
@@ -15,14 +18,21 @@ namespace Content.Client.Cargo.UI;
 [GenerateTypedNameReferences]
 public sealed partial class FundingAllocationMenu : FancyWindow
 {
+    [Dependency] private readonly IConfigurationManager _cfg = default!;
     [Dependency] private readonly IEntityManager _entityManager = default!;
     [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
 
     private readonly EntityQuery<StationBankAccountComponent> _bankQuery;
 
-    public event Action<Dictionary<ProtoId<CargoAccountPrototype>, int>>? OnSavePressed;
+    public event Action<Dictionary<ProtoId<CargoAccountPrototype>, int>, double, double>? OnSavePressed;
 
     private EntityUid? _station;
+    private bool _allowPrimaryAccountAllocation;
+    private bool _allowPrimaryCutAdjustment;
+    private bool _lockboxCutEnabled;
+
+    private double _primaryCut;
+    private double _lockboxCut;
 
     private readonly HashSet<Control> _addedControls = new();
     private readonly List<SpinBox> _spinBoxes = new();
@@ -35,30 +45,65 @@ public sealed partial class FundingAllocationMenu : FancyWindow
 
         _bankQuery = _entityManager.GetEntityQuery<StationBankAccountComponent>();
 
+        PrimaryCut.ValueChanged += args =>
+        {
+            _primaryCut = (double)args.Value / 100.0;
+            UpdateButtonDisabled();
+        };
+
+        LockboxCut.ValueChanged += args =>
+        {
+            _lockboxCut = 1.0 - (double)args.Value / 100.0;
+            UpdateButtonDisabled();
+        };
+
         SaveButton.OnPressed += _ =>
         {
             if (!_entityManager.TryGetComponent<StationBankAccountComponent>(_station, out var bank))
                 return;
-            var accounts = bank.Accounts.Keys.OrderBy(p => p.Id).ToList();
+            var accounts = EditableAccounts(bank).OrderBy(p => p.Key).Select(p => p.Key).ToList();
             var dicts = new Dictionary<ProtoId<CargoAccountPrototype>, int>();
             for (var i = 0; i< accounts.Count; i++)
             {
                 dicts.Add(accounts[i], _spinBoxes[i].Value);
             }
 
-            OnSavePressed?.Invoke(dicts);
+            OnSavePressed?.Invoke(dicts, _primaryCut, _lockboxCut);
             SaveButton.Disabled = true;
         };
 
+        _cfg.OnValueChanged(CCVars.AllowPrimaryAccountAllocation, enabled => { _allowPrimaryAccountAllocation = enabled; }, true);
+        _cfg.OnValueChanged(CCVars.AllowPrimaryCutAdjustment, enabled => { _allowPrimaryCutAdjustment = enabled; }, true);
+        _cfg.OnValueChanged(CCVars.LockboxCutEnabled, enabled => { _lockboxCutEnabled = enabled; }, true);
+
         BuildEntries();
     }
 
+    private IEnumerable<KeyValuePair<ProtoId<CargoAccountPrototype>, int>> EditableAccounts(StationBankAccountComponent bank)
+    {
+        foreach (var kvp in bank.Accounts)
+        {
+            if (_allowPrimaryAccountAllocation || kvp.Key != bank.PrimaryAccount)
+            {
+                yield return kvp;
+            }
+        }
+    }
+
     private void BuildEntries()
     {
         if (!_entityManager.TryGetComponent<StationBankAccountComponent>(_station, out var bank))
             return;
-        HelpLabel.Text = Loc.GetString("cargo-funding-alloc-console-label-help",
-            ("percent", (int) (bank.PrimaryCut * 100)));
+
+        if (_allowPrimaryCutAdjustment)
+        {
+            HelpLabel.Text = Loc.GetString("cargo-funding-alloc-console-label-help-adjustible");
+        }
+        else
+        {
+            HelpLabel.Text = Loc.GetString("cargo-funding-alloc-console-label-help-non-adjustible",
+                ("percent", (int) (bank.PrimaryCut * 100)));
+        }
 
         foreach (var ctrl in _addedControls)
         {
@@ -69,7 +114,21 @@ public sealed partial class FundingAllocationMenu : FancyWindow
         _spinBoxes.Clear();
         _balanceLabels.Clear();
 
-        var accounts = bank.Accounts.ToList().OrderBy(p => p.Key);
+        _primaryCut = bank.PrimaryCut;
+        _lockboxCut = bank.LockboxCut;
+
+        LockboxCut.OverrideValue(100 - (int)(_lockboxCut * 100));
+        PrimaryCut.OverrideValue((int)(_primaryCut * 100));
+
+        LockboxCut.IsValid = val => val is >= 0 and <= 100;
+        PrimaryCut.IsValid = val => val is >= 0 and <= 100;
+
+        LockboxCut.Visible = _lockboxCutEnabled;
+        LockboxCutLabel.Visible = _lockboxCutEnabled;
+        PrimaryCut.Visible = _allowPrimaryCutAdjustment;
+        PrimaryCutLabel.Visible = _allowPrimaryCutAdjustment;
+
+        var accounts = EditableAccounts(bank).OrderBy(p => p.Key);
         foreach (var (account, balance) in accounts)
         {
             var accountProto = _prototypeManager.Index(account);
@@ -127,7 +186,7 @@ public sealed partial class FundingAllocationMenu : FancyWindow
         var incorrectSum = sum != 100;
 
         var differs = false;
-        var accounts = bank.Accounts.Keys.OrderBy(p => p.Id).ToList();
+        var accounts = EditableAccounts(bank).OrderBy(p => p.Key).Select(p => p.Key).ToList();
         for (var i = 0; i < accounts.Count; i++)
         {
             var percent = _spinBoxes[i].Value;
@@ -137,6 +196,7 @@ public sealed partial class FundingAllocationMenu : FancyWindow
                 break;
             }
         }
+        differs = differs || _primaryCut != bank.PrimaryCut || _lockboxCut != bank.LockboxCut;
 
         SaveButton.Disabled = !differs || incorrectSum;
 
index d64c4676643c0d781231a2a6aa1573f9bb2f3b30..4a3fa5330e5ebf2054397b380b0a71d7ea44ab5e 100644 (file)
@@ -1,5 +1,6 @@
 using System.Linq;
 using Content.Shared.Cargo.Components;
+using Content.Shared.CCVar;
 using Content.Shared.Database;
 using Content.Shared.Emag.Systems;
 using Content.Shared.IdentityManagement;
@@ -9,12 +10,18 @@ namespace Content.Server.Cargo.Systems;
 
 public sealed partial class CargoSystem
 {
+    private bool _allowPrimaryAccountAllocation;
+    private bool _allowPrimaryCutAdjustment;
+
     public void InitializeFunds()
     {
         SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleWithdrawFundsMessage>(OnWithdrawFunds);
         SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleToggleLimitMessage>(OnToggleLimit);
         SubscribeLocalEvent<FundingAllocationConsoleComponent, SetFundingAllocationBuiMessage>(OnSetFundingAllocation);
         SubscribeLocalEvent<FundingAllocationConsoleComponent, BeforeActivatableUIOpenEvent>(OnFundAllocationBuiOpen);
+
+        _cfg.OnValueChanged(CCVars.AllowPrimaryAccountAllocation, enabled => { _allowPrimaryAccountAllocation = enabled; }, true);
+        _cfg.OnValueChanged(CCVars.AllowPrimaryCutAdjustment, enabled => { _allowPrimaryCutAdjustment = enabled; }, true);
     }
 
     private void OnWithdrawFunds(Entity<CargoOrderConsoleComponent> ent, ref CargoConsoleWithdrawFundsMessage args)
@@ -102,7 +109,8 @@ public sealed partial class CargoSystem
             !TryComp<StationBankAccountComponent>(station, out var bank))
             return;
 
-        if (args.Percents.Count != bank.RevenueDistribution.Count)
+        var expectedCount = _allowPrimaryAccountAllocation ? bank.RevenueDistribution.Count : bank.RevenueDistribution.Count - 1;
+        if (args.Percents.Count != expectedCount)
             return;
 
         var differs = false;
@@ -114,6 +122,7 @@ public sealed partial class CargoSystem
                 break;
             }
         }
+        differs = differs || args.PrimaryCut != bank.PrimaryCut || args.LockboxCut != bank.LockboxCut;
 
         if (!differs)
             return;
@@ -121,18 +130,33 @@ public sealed partial class CargoSystem
         if (args.Percents.Values.Sum() != 100)
             return;
 
+        var primaryCut = bank.RevenueDistribution[bank.PrimaryAccount];
         bank.RevenueDistribution.Clear();
         foreach (var (account, percent )in args.Percents)
         {
             bank.RevenueDistribution.Add(account, percent / 100.0);
         }
+        if (!_allowPrimaryAccountAllocation)
+        {
+            bank.RevenueDistribution.Add(bank.PrimaryAccount, 0);
+        }
+
+        if (_allowPrimaryCutAdjustment && args.PrimaryCut is >= 0.0 and <= 1.0)
+        {
+            bank.PrimaryCut = args.PrimaryCut;
+        }
+        if (_lockboxCutEnabled && args.LockboxCut is >= 0.0 and <= 1.0)
+        {
+            bank.LockboxCut = args.LockboxCut;
+        }
+
         Dirty(station, bank);
 
         _audio.PlayPvs(ent.Comp.SetDistributionSound, ent);
         _adminLogger.Add(
             LogType.Action,
             LogImpact.Medium,
-            $"{ToPrettyString(args.Actor):player} set station {ToPrettyString(station)} fund distribution: {string.Join(',', bank.RevenueDistribution.Select(p => $"{p.Key}: {p.Value}").ToList())}");
+            $"{ToPrettyString(args.Actor):player} set station {ToPrettyString(station)} fund distribution: {string.Join(',', bank.RevenueDistribution.Select(p => $"{p.Key}: {p.Value}").ToList())}, primary cut: {bank.PrimaryCut}, lockbox cut: {bank.LockboxCut}");
     }
 
     private void OnFundAllocationBuiOpen(Entity<FundingAllocationConsoleComponent> ent, ref BeforeActivatableUIOpenEvent args)
index ce2642e1b673eae35dab48df47a07d3460380879..2516965b6deb59fe8d398b82390240f599a3c0d9 100644 (file)
@@ -5,6 +5,7 @@ using Content.Shared.Cargo.BUI;
 using Content.Shared.Cargo.Components;
 using Content.Shared.Cargo.Events;
 using Content.Shared.Cargo.Prototypes;
+using Content.Shared.CCVar;
 using JetBrains.Annotations;
 using Robust.Shared.Audio;
 using Robust.Shared.Prototypes;
@@ -18,6 +19,7 @@ public sealed partial class CargoSystem
      */
 
     private static readonly SoundPathSpecifier ApproveSound = new("/Audio/Effects/Cargo/ping.ogg");
+    private bool _lockboxCutEnabled;
 
     private void InitializeShuttle()
     {
@@ -28,6 +30,8 @@ public sealed partial class CargoSystem
         SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletSellMessage>(OnPalletSale);
         SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletAppraiseMessage>(OnPalletAppraise);
         SubscribeLocalEvent<CargoPalletConsoleComponent, BoundUIOpenedEvent>(OnPalletUIOpen);
+
+        _cfg.OnValueChanged(CCVars.LockboxCutEnabled, (enabled) => { _lockboxCutEnabled = enabled; }, true);
     }
 
     #region Console
@@ -340,10 +344,11 @@ public sealed partial class CargoSystem
             Dictionary<ProtoId<CargoAccountPrototype>, double> distribution;
             if (sellComponent != null)
             {
+                var cut = _lockboxCutEnabled ? bankAccount.LockboxCut : bankAccount.PrimaryCut;
                 distribution = new Dictionary<ProtoId<CargoAccountPrototype>, double>
                 {
-                    { sellComponent.OverrideAccount, sellComponent.OverrideCut },
-                    { bankAccount.PrimaryAccount, 1.0 - sellComponent.OverrideCut },
+                    { sellComponent.OverrideAccount, cut },
+                    { bankAccount.PrimaryAccount, 1.0 - cut },
                 };
             }
             else
index d0ec138e4e036888ec62f6de9e99f82747a92de3..1b6f1973ea50bc20ee78ae08279445f4d45599d9 100644 (file)
@@ -10,12 +10,14 @@ using Content.Server.Radio.EntitySystems;
 using Content.Shared.Cargo;
 using Content.Shared.Cargo.Components;
 using Content.Shared.Cargo.Prototypes;
+using Content.Shared.CCVar;
 using Content.Shared.Containers.ItemSlots;
 using Content.Shared.Mobs.Components;
 using Content.Shared.Paper;
 using JetBrains.Annotations;
 using Robust.Server.GameObjects;
 using Robust.Shared.Audio.Systems;
+using Robust.Shared.Configuration;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Random;
 
@@ -23,6 +25,7 @@ namespace Content.Server.Cargo.Systems;
 
 public sealed partial class CargoSystem : SharedCargoSystem
 {
+    [Dependency] private readonly IConfigurationManager _cfg = default!;
     [Dependency] private readonly IPrototypeManager _protoMan = default!;
     [Dependency] private readonly IRobustRandom _random = default!;
     [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
diff --git a/Content.Shared/CCVar/CCVars.Cargo.cs b/Content.Shared/CCVar/CCVars.Cargo.cs
new file mode 100644 (file)
index 0000000..dd47bfb
--- /dev/null
@@ -0,0 +1,26 @@
+using Robust.Shared.Configuration;
+
+namespace Content.Shared.CCVar;
+
+public sealed partial class CCVars
+{
+    /// <summary>
+    ///     Whether or not the primary account of a bank should be listed
+    ///     in the funding allocation console
+    /// </summary>
+    public static readonly CVarDef<bool> AllowPrimaryAccountAllocation =
+        CVarDef.Create("cargo.allow_primary_account_allocation", false, CVar.REPLICATED);
+
+    /// <summary>
+    ///     Whether or not the primary cut of a bank should be manipulable
+    ///     in the funding allocation console
+    /// </summary>
+    public static readonly CVarDef<bool> AllowPrimaryCutAdjustment =
+        CVarDef.Create("cargo.allow_primary_cut_adjustment", true, CVar.REPLICATED);
+
+    /// <summary>
+    ///     Whether or not the separate lockbox cut is enabled
+    /// </summary>
+    public static readonly CVarDef<bool> LockboxCutEnabled =
+        CVarDef.Create("cargo.enable_lockbox_cut", true, CVar.REPLICATED);
+}
index 65fd09a1b715fae3c5cac5685d0be207cb7ac217..d4afd72309a6ba972bf3d660b7a9fa5fb47ef93c 100644 (file)
@@ -24,10 +24,14 @@ public sealed partial class FundingAllocationConsoleComponent : Component
 public sealed class SetFundingAllocationBuiMessage : BoundUserInterfaceMessage
 {
     public Dictionary<ProtoId<CargoAccountPrototype>, int> Percents;
+    public double PrimaryCut;
+    public double LockboxCut;
 
-    public SetFundingAllocationBuiMessage(Dictionary<ProtoId<CargoAccountPrototype>, int> percents)
+    public SetFundingAllocationBuiMessage(Dictionary<ProtoId<CargoAccountPrototype>, int> percents, double primaryCut, double lockboxCut)
     {
         Percents = percents;
+        PrimaryCut = primaryCut;
+        LockboxCut = lockboxCut;
     }
 }
 
index 13e72486ecb50ebe4dcb065192c665509d9ff993..7d798c9ad104b187f1fb7f6d7731676cb0eba890 100644 (file)
@@ -14,10 +14,4 @@ public sealed partial class OverrideSellComponent : Component
     /// </summary>
     [DataField(required: true)]
     public ProtoId<CargoAccountPrototype> OverrideAccount;
-
-    /// <summary>
-    /// The cut that the OverrideAccount will get from the price. The rest is given to the primary station account.
-    /// </summary>
-    [DataField]
-    public float OverrideCut = 0.75f;
 }
index a52f5ee61c5997702b06a6739160004c11fe2917..944f03cd72aaef79f3a9005d925157603cf2769c 100644 (file)
@@ -23,6 +23,12 @@ public sealed partial class StationBankAccountComponent : Component
     [DataField, AutoNetworkedField]
     public double PrimaryCut = 0.50;
 
+    /// <summary>
+    /// When giving funds to a particular account from an override sell, the proportion of funds they should receive compared to remaining accounts.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public double LockboxCut = 0.75;
+
     /// <summary>
     /// A dictionary corresponding to the money held by each cargo account.
     /// </summary>
index b7467771d95bd0ed90360e0f563868bad6da4c59..22e75ae6dc15f1f4225f052a8fa9b1e26639abb2 100644 (file)
@@ -72,7 +72,11 @@ cargo-funding-alloc-console-label-code = [bold] Code [/bold]
 cargo-funding-alloc-console-label-balance = [bold] Balance [/bold]
 cargo-funding-alloc-console-label-cut = [bold] Revenue Division (%) [/bold]
 
-cargo-funding-alloc-console-label-help = Cargo receives {$percent}% of all profits. The rest is split as specified below:
+cargo-funding-alloc-console-label-primary-cut = Cargo's cut of funds from non-lockbox sources (%):
+cargo-funding-alloc-console-label-lockbox-cut = Cargo's cut of funds from lockbox sales (%):
+
+cargo-funding-alloc-console-label-help-non-adjustible = Cargo receives {$percent}% of profits from non-lockbox sales. The rest is split as specified below:
+cargo-funding-alloc-console-label-help-adjustible = Remaining funds from non-lockbox sources are distributed as specified below:
 cargo-funding-alloc-console-button-save = Save Changes
 cargo-funding-alloc-console-label-save-fail = [bold]Revenue Divisions Invalid![/bold] [color=red]({$pos ->
     [1] +