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; 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 _bankQuery; public event Action, 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 _addedControls = new(); private readonly List _spinBoxes = new(); private readonly Dictionary, RichTextLabel> _balanceLabels = new(); public FundingAllocationMenu() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _bankQuery = _entityManager.GetEntityQuery(); 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(_station, out var bank)) return; var accounts = EditableAccounts(bank).OrderBy(p => p.Key).Select(p => p.Key).ToList(); var dicts = new Dictionary, int>(); for (var i = 0; i< accounts.Count; i++) { dicts.Add(accounts[i], _spinBoxes[i].Value); } 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, 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(_station, out var bank)) return; 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) { ctrl.Orphan(); } _addedControls.Clear(); _spinBoxes.Clear(); _balanceLabels.Clear(); _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); var accountNameLabel = new RichTextLabel { Modulate = accountProto.Color, Margin = new Thickness(0, 0, 10, 0) }; accountNameLabel.SetMarkup($"[bold]{Loc.GetString(accountProto.Name)}[/bold]"); EntriesContainer.AddChild(accountNameLabel); var codeLabel = new RichTextLabel { Text = $"[font=\"Monospace\"]{Loc.GetString(accountProto.Code)}[/font]", HorizontalAlignment = HAlignment.Center, Margin = new Thickness(5, 0), }; EntriesContainer.AddChild(codeLabel); var balanceLabel = new RichTextLabel { Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", balance)), HorizontalExpand = true, HorizontalAlignment = HAlignment.Center, Margin = new Thickness(5, 0), }; EntriesContainer.AddChild(balanceLabel); var box = new SpinBox { HorizontalAlignment = HAlignment.Center, HorizontalExpand = true, Value = (int) (bank.RevenueDistribution[account] * 100), IsValid = val => val is >= 0 and <= 100, }; box.ValueChanged += _ => UpdateButtonDisabled(); EntriesContainer.AddChild(box); _spinBoxes.Add(box); _balanceLabels.Add(account, balanceLabel); _addedControls.Add(accountNameLabel); _addedControls.Add(codeLabel); _addedControls.Add(balanceLabel); _addedControls.Add(box); } } private void UpdateButtonDisabled() { if (!_entityManager.TryGetComponent(_station, out var bank)) return; var sum = _spinBoxes.Sum(s => s.Value); var incorrectSum = sum != 100; var differs = false; 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; if (percent != (int) Math.Round(bank.RevenueDistribution[accounts[i]] * 100)) { differs = true; break; } } differs = differs || _primaryCut != bank.PrimaryCut || _lockboxCut != bank.LockboxCut; SaveButton.Disabled = !differs || incorrectSum; var diff = sum - 100; SaveAlertLabel.Visible = incorrectSum; SaveAlertLabel.SetMarkup(Loc.GetString("cargo-funding-alloc-console-label-save-fail", ("pos", Math.Sign(diff)), ("val", Math.Abs(diff)))); } public void Update(FundingAllocationConsoleBuiState state) { _station = _entityManager.GetEntity(state.Station); BuildEntries(); UpdateButtonDisabled(); } protected override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); if (!_bankQuery.TryComp(_station, out var bank)) return; foreach (var (account, label) in _balanceLabels) { label.Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", bank.Accounts[account])); } } }