using System.Runtime.InteropServices; using Content.Server._NF.SectorServices; using Content.Shared._NF.Bank.BUI; using Content.Shared._NF.Bank; using Content.Shared._NF.Bank.Components; using JetBrains.Annotations; namespace Content.Server._NF.Bank; public sealed partial class BankSystem : SharedBankSystem { [Dependency] private readonly SectorServiceSystem _sectorService = default!; // The interval between sector account increases, in seconds. private const float AccountIncreaseInterval = 10.0f; // Creates ledger entries for starting account balances. private void OnSectorInit(EntityUid entity, SectorBankComponent component, ComponentInit args) { foreach (var account in component.Accounts) AddLedgerEntry(account.Key, LedgerEntryType.TickingIncome, account.Value.Balance); } /// /// Attempts to remove money from a sector bank account. /// /// The account to be withdrawn from /// The amount of spesos to remove from the account. /// true if the transaction was successful, false if it was not. [PublicAPI] public bool TrySectorWithdraw(SectorBankAccount account, int amount, LedgerEntryType reason, SectorBankComponent? bank = null) { if (amount <= 0) { _log.Info($"TryBankWithdraw: {amount} is invalid"); return false; } // Lookup sector banks if (bank == null && !TryComp(_sectorService.GetServiceEntity(), out bank)) { _log.Info($"TryBankWithdraw: no bank component"); return false; } if (!bank.Accounts.ContainsKey(account)) { _log.Info($"TryBankWithdraw: invalid account"); return false; } var bankAccount = CollectionsMarshal.GetValueRefOrNullRef(bank.Accounts, account); if (bankAccount.Balance < amount) { _log.Info($"TryBankWithdraw: account has less money {bankAccount.Balance} than requested {amount}"); return false; } bankAccount.Balance -= amount; AddLedgerEntry(account, reason, amount); return true; } /// /// Attempts to add money to a sector bank account. /// /// The UID that the bank account is connected to, typically the player controlled mob /// The amount of spesos to remove from the bank account /// The purpose of this withdrawal /// true if the transaction was successful, false if it was not [PublicAPI] public bool TrySectorDeposit(SectorBankAccount account, int amount, LedgerEntryType reason, SectorBankComponent? bank=null) { if (amount <= 0) { _log.Info($"TryBankDeposit: {amount} is invalid"); return false; } // Lookup sector banks if (bank == null && !TryComp(_sectorService.GetServiceEntity(), out bank)) { _log.Info($"TryBankDeposit: no bank component"); return false; } if (!bank.Accounts.ContainsKey(account)) { _log.Info($"TryBankDeposit: invalid account"); return false; } var bankAccount = CollectionsMarshal.GetValueRefOrNullRef(bank.Accounts, account); bankAccount.Balance += amount; AddLedgerEntry(account, reason, amount); return true; } /// /// Retrieves a character's balance via its in-game entity, if it has one. /// /// The UID that the bank account is connected to, typically the player controlled mob /// When successful, contains the account balance in spesos. Otherwise, set to 0. /// true if the account was successfully queried. [PublicAPI] public bool TryGetBalance(SectorBankAccount account, out int balance) { // Lookup sector banks if (!TryComp(_sectorService.GetServiceEntity(), out SectorBankComponent? bank)) { _log.Info($"TryGetBalance: no bank component"); balance = 0; return false; } if (!bank.Accounts.ContainsKey(account)) { _log.Info($"TryGetBalance: invalid account"); balance = 0; return false; } balance = bank.Accounts[account].Balance; return true; } private void UpdateSectorBanks(float frameTime) { if (!TryComp(_sectorService.GetServiceEntity(), out SectorBankComponent? bank)) return; bank.SecondsSinceLastIncrease += frameTime; float secondsToCredit = 0; while (bank.SecondsSinceLastIncrease > AccountIncreaseInterval) { bank.SecondsSinceLastIncrease -= AccountIncreaseInterval; secondsToCredit += AccountIncreaseInterval; } int seconds = (int)secondsToCredit; if (seconds <= 0) return; foreach (var (accountId, accountInfo) in bank.Accounts) TrySectorDeposit(accountId, seconds * accountInfo.IncreasePerSecond, LedgerEntryType.TickingIncome, bank); } }