Departmental Economy (#36445)
* Cargo Accounts, Request Consoles, and lock boxes * Funding Allocation Computer * final changes * test fix * remove dumb code * ScarKy0 review * first cour * second cour * Update machines.yml * review --------- Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Co-authored-by: Milon <milonpl.git@proton.me>
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
namespace Content.Server.Cargo.Components;
|
||||
using Content.Shared.Actions;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
|
||||
/// <summary>
|
||||
/// Any entities intersecting when a shuttle is recalled will be sold.
|
||||
|
||||
@@ -6,8 +6,4 @@ namespace Content.Server.Cargo.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(CargoSystem))]
|
||||
public sealed partial class CargoPalletConsoleComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("cashType", customTypeSerializer:typeof(PrototypeIdSerializer<StackPrototype>))]
|
||||
public string CashType = "Credit";
|
||||
}
|
||||
public sealed partial class CargoPalletConsoleComponent : Component;
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
using Content.Shared.Cargo;
|
||||
|
||||
namespace Content.Server.Cargo.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Added to the abstract representation of a station to track its money.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedCargoSystem))]
|
||||
public sealed partial class StationBankAccountComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("balance")]
|
||||
public int Balance = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// How much the bank balance goes up per second, every Delay period. Rounded down when multiplied.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("increasePerSecond")]
|
||||
public int IncreasePerSecond = 1;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Shared.Cargo;
|
||||
using Content.Shared.Cargo.Components;
|
||||
using Content.Shared.Cargo.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Cargo.Components;
|
||||
|
||||
@@ -16,15 +16,19 @@ public sealed partial class StationCargoOrderDatabaseComponent : Component
|
||||
/// <summary>
|
||||
/// Maximum amount of orders a station is allowed, approved or not.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("capacity")]
|
||||
[DataField]
|
||||
public int Capacity = 20;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("orders")]
|
||||
public List<CargoOrderData> Orders = new();
|
||||
[ViewVariables]
|
||||
public IEnumerable<CargoOrderData> AllOrders => Orders.SelectMany(p => p.Value);
|
||||
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<CargoAccountPrototype>, List<CargoOrderData>> Orders = new();
|
||||
|
||||
/// <summary>
|
||||
/// Used to determine unique order IDs
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public int NumOrdersCreated;
|
||||
|
||||
// TODO: Can probably dump this
|
||||
|
||||
@@ -27,7 +27,6 @@ public sealed partial class CargoSystem
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly NameIdentifierSystem _nameIdentifier = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelistSys = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
[ValidatePrototypeId<NameIdentifierGroupPrototype>]
|
||||
private const string BountyNameIdentifierGroup = "Bounty";
|
||||
@@ -472,7 +471,7 @@ public sealed partial class CargoSystem
|
||||
skipped
|
||||
? CargoBountyHistoryData.BountyResult.Skipped
|
||||
: CargoBountyHistoryData.BountyResult.Completed,
|
||||
_gameTiming.CurTime,
|
||||
_timing.CurTime,
|
||||
actorName));
|
||||
ent.Comp.Bounties.RemoveAt(i);
|
||||
return true;
|
||||
|
||||
144
Content.Server/Cargo/Systems/CargoSystem.Funds.cs
Normal file
144
Content.Server/Cargo/Systems/CargoSystem.Funds.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Cargo.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.UserInterface;
|
||||
|
||||
namespace Content.Server.Cargo.Systems;
|
||||
|
||||
public sealed partial class CargoSystem
|
||||
{
|
||||
public void InitializeFunds()
|
||||
{
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleWithdrawFundsMessage>(OnWithdrawFunds);
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleToggleLimitMessage>(OnToggleLimit);
|
||||
SubscribeLocalEvent<FundingAllocationConsoleComponent, SetFundingAllocationBuiMessage>(OnSetFundingAllocation);
|
||||
SubscribeLocalEvent<FundingAllocationConsoleComponent, BeforeActivatableUIOpenEvent>(OnFundAllocationBuiOpen);
|
||||
}
|
||||
|
||||
private void OnWithdrawFunds(Entity<CargoOrderConsoleComponent> ent, ref CargoConsoleWithdrawFundsMessage args)
|
||||
{
|
||||
if (_station.GetOwningStation(ent) is not { } station ||
|
||||
!TryComp<StationBankAccountComponent>(station, out var bank))
|
||||
return;
|
||||
|
||||
if (args.Account == ent.Comp.Account ||
|
||||
args.Amount <= 0 ||
|
||||
args.Amount > GetBalanceFromAccount((station, bank), ent.Comp.Account) * ent.Comp.TransferLimit)
|
||||
return;
|
||||
|
||||
if (_timing.CurTime < ent.Comp.NextAccountActionTime)
|
||||
return;
|
||||
|
||||
if (!_accessReaderSystem.IsAllowed(args.Actor, ent))
|
||||
{
|
||||
ConsolePopup(args.Actor, Loc.GetString("cargo-console-order-not-allowed"));
|
||||
PlayDenySound(ent, ent.Comp);
|
||||
return;
|
||||
}
|
||||
|
||||
ent.Comp.NextAccountActionTime = _timing.CurTime + ent.Comp.AccountActionDelay;
|
||||
Dirty(ent);
|
||||
UpdateBankAccount((station, bank), -args.Amount, CreateAccountDistribution(ent.Comp.Account, bank));
|
||||
_audio.PlayPvs(ApproveSound, ent);
|
||||
|
||||
var tryGetIdentityShortInfoEvent = new TryGetIdentityShortInfoEvent(ent, args.Actor);
|
||||
RaiseLocalEvent(tryGetIdentityShortInfoEvent);
|
||||
|
||||
var ourAccount = _protoMan.Index(ent.Comp.Account);
|
||||
if (args.Account == null)
|
||||
{
|
||||
var stackPrototype = _protoMan.Index(ent.Comp.CashType);
|
||||
_stack.Spawn(args.Amount, stackPrototype, Transform(ent).Coordinates);
|
||||
|
||||
if (!_emag.CheckFlag(ent, EmagType.Interaction))
|
||||
{
|
||||
var msg = Loc.GetString("cargo-console-fund-withdraw-broadcast",
|
||||
("name", tryGetIdentityShortInfoEvent.Title ?? Loc.GetString("cargo-console-fund-transfer-user-unknown")),
|
||||
("amount", args.Amount),
|
||||
("name1", Loc.GetString(ourAccount.Name)),
|
||||
("code1", Loc.GetString(ourAccount.Code)));
|
||||
_radio.SendRadioMessage(ent, msg, ourAccount.RadioChannel, ent, escapeMarkup: false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var otherAccount = _protoMan.Index(args.Account.Value);
|
||||
UpdateBankAccount((station, bank), args.Amount, CreateAccountDistribution(args.Account.Value, bank));
|
||||
|
||||
if (!_emag.CheckFlag(ent, EmagType.Interaction))
|
||||
{
|
||||
var msg = Loc.GetString("cargo-console-fund-transfer-broadcast",
|
||||
("name", tryGetIdentityShortInfoEvent.Title ?? Loc.GetString("cargo-console-fund-transfer-user-unknown")),
|
||||
("amount", args.Amount),
|
||||
("name1", Loc.GetString(ourAccount.Name)),
|
||||
("code1", Loc.GetString(ourAccount.Code)),
|
||||
("name2", Loc.GetString(otherAccount.Name)),
|
||||
("code2", Loc.GetString(otherAccount.Code)));
|
||||
_radio.SendRadioMessage(ent, msg, ourAccount.RadioChannel, ent, escapeMarkup: false);
|
||||
_radio.SendRadioMessage(ent, msg, otherAccount.RadioChannel, ent, escapeMarkup: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnToggleLimit(Entity<CargoOrderConsoleComponent> ent, ref CargoConsoleToggleLimitMessage args)
|
||||
{
|
||||
if (!_accessReaderSystem.FindAccessTags(args.Actor).Intersect(ent.Comp.RemoveLimitAccess).Any())
|
||||
{
|
||||
ConsolePopup(args.Actor, Loc.GetString("cargo-console-order-not-allowed"));
|
||||
PlayDenySound(ent, ent.Comp);
|
||||
return;
|
||||
}
|
||||
|
||||
_audio.PlayPvs(ent.Comp.ToggleLimitSound, ent);
|
||||
ent.Comp.TransferUnbounded = !ent.Comp.TransferUnbounded;
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
|
||||
private void OnSetFundingAllocation(Entity<FundingAllocationConsoleComponent> ent, ref SetFundingAllocationBuiMessage args)
|
||||
{
|
||||
if (_station.GetOwningStation(ent) is not { } station ||
|
||||
!TryComp<StationBankAccountComponent>(station, out var bank))
|
||||
return;
|
||||
|
||||
if (args.Percents.Count != bank.RevenueDistribution.Count)
|
||||
return;
|
||||
|
||||
var differs = false;
|
||||
foreach (var (account, percent) in args.Percents)
|
||||
{
|
||||
if (percent != (int) Math.Round(bank.RevenueDistribution[account] * 100))
|
||||
{
|
||||
differs = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!differs)
|
||||
return;
|
||||
|
||||
if (args.Percents.Values.Sum() != 100)
|
||||
return;
|
||||
|
||||
bank.RevenueDistribution.Clear();
|
||||
foreach (var (account, percent )in args.Percents)
|
||||
{
|
||||
bank.RevenueDistribution.Add(account, percent / 100.0);
|
||||
}
|
||||
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())}");
|
||||
}
|
||||
|
||||
private void OnFundAllocationBuiOpen(Entity<FundingAllocationConsoleComponent> ent, ref BeforeActivatableUIOpenEvent args)
|
||||
{
|
||||
if (_station.GetOwningStation(ent) is { } station)
|
||||
_uiSystem.SetUiState(ent.Owner, FundingAllocationConsoleUiKey.Key, new FundingAllocationConsoleBuiState(GetNetEntity(station)));
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Labels.Components;
|
||||
using Content.Shared.Paper;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -23,16 +24,6 @@ namespace Content.Server.Cargo.Systems
|
||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||
[Dependency] private readonly EmagSystem _emag = default!;
|
||||
|
||||
/// <summary>
|
||||
/// How much time to wait (in seconds) before increasing bank accounts balance.
|
||||
/// </summary>
|
||||
private const int Delay = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Keeps track of how much time has elapsed since last balance increase.
|
||||
/// </summary>
|
||||
private float _timer;
|
||||
|
||||
private void InitializeConsole()
|
||||
{
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleAddOrderMessage>(OnAddOrderMessage);
|
||||
@@ -41,9 +32,7 @@ namespace Content.Server.Cargo.Systems
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, BoundUIOpenedEvent>(OnOrderUIOpened);
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, BankBalanceUpdatedEvent>(OnOrderBalanceUpdated);
|
||||
SubscribeLocalEvent<CargoOrderConsoleComponent, GotEmaggedEvent>(OnEmagged);
|
||||
Reset();
|
||||
}
|
||||
|
||||
private void OnInteractUsing(EntityUid uid, CargoOrderConsoleComponent component, ref InteractUsingEvent args)
|
||||
@@ -61,8 +50,8 @@ namespace Content.Server.Cargo.Systems
|
||||
if (!TryComp(stationUid, out StationBankAccountComponent? bank))
|
||||
return;
|
||||
|
||||
_audio.PlayPvs(component.ConfirmSound, uid);
|
||||
UpdateBankAccount((stationUid.Value, bank), (int) price);
|
||||
_audio.PlayPvs(ApproveSound, uid);
|
||||
UpdateBankAccount((stationUid.Value, bank), (int) price, CreateAccountDistribution(component.Account, bank));
|
||||
QueueDel(args.Used);
|
||||
args.Handled = true;
|
||||
}
|
||||
@@ -73,11 +62,6 @@ namespace Content.Server.Cargo.Systems
|
||||
UpdateOrderState(uid, station);
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
_timer = 0;
|
||||
}
|
||||
|
||||
private void OnEmagged(Entity<CargoOrderConsoleComponent> ent, ref GotEmaggedEvent args)
|
||||
{
|
||||
if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
|
||||
@@ -89,31 +73,17 @@ namespace Content.Server.Cargo.Systems
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void UpdateConsole(float frameTime)
|
||||
private void UpdateConsole()
|
||||
{
|
||||
_timer += frameTime;
|
||||
|
||||
// TODO: Doesn't work with serialization and shouldn't just be updating every delay
|
||||
// client can just interp this just fine on its own.
|
||||
while (_timer > Delay)
|
||||
var stationQuery = EntityQueryEnumerator<StationBankAccountComponent>();
|
||||
while (stationQuery.MoveNext(out var uid, out var bank))
|
||||
{
|
||||
_timer -= Delay;
|
||||
if (_timing.CurTime < bank.NextIncomeTime)
|
||||
continue;
|
||||
bank.NextIncomeTime += bank.IncomeDelay;
|
||||
|
||||
var stationQuery = EntityQueryEnumerator<StationBankAccountComponent>();
|
||||
while (stationQuery.MoveNext(out var uid, out var bank))
|
||||
{
|
||||
var balanceToAdd = bank.IncreasePerSecond * Delay;
|
||||
UpdateBankAccount((uid, bank), balanceToAdd);
|
||||
}
|
||||
|
||||
var query = EntityQueryEnumerator<CargoOrderConsoleComponent>();
|
||||
while (query.MoveNext(out var uid, out var _))
|
||||
{
|
||||
if (!_uiSystem.IsUiOpen(uid, CargoConsoleUiKey.Orders)) continue;
|
||||
|
||||
var station = _station.GetOwningStation(uid);
|
||||
UpdateOrderState(uid, station);
|
||||
}
|
||||
var balanceToAdd = (int) Math.Round(bank.IncreasePerSecond * bank.IncomeDelay.TotalSeconds);
|
||||
UpdateBankAccount((uid, bank), balanceToAdd, bank.RevenueDistribution);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +114,7 @@ namespace Content.Server.Cargo.Systems
|
||||
}
|
||||
|
||||
// Find our order again. It might have been dispatched or approved already
|
||||
var order = orderDatabase.Orders.Find(order => args.OrderId == order.OrderId && !order.Approved);
|
||||
var order = orderDatabase.Orders[component.Account].Find(order => args.OrderId == order.OrderId && !order.Approved);
|
||||
if (order == null)
|
||||
{
|
||||
return;
|
||||
@@ -158,7 +128,7 @@ namespace Content.Server.Cargo.Systems
|
||||
return;
|
||||
}
|
||||
|
||||
var amount = GetOutstandingOrderCount(orderDatabase);
|
||||
var amount = GetOutstandingOrderCount(orderDatabase, component.Account);
|
||||
var capacity = orderDatabase.Capacity;
|
||||
|
||||
// Too many orders, avoid them getting spammed in the UI.
|
||||
@@ -180,9 +150,10 @@ namespace Content.Server.Cargo.Systems
|
||||
}
|
||||
|
||||
var cost = order.Price * order.OrderQuantity;
|
||||
var accountBalance = GetBalanceFromAccount((station.Value, bank), component.Account);
|
||||
|
||||
// Not enough balance
|
||||
if (cost > bank.Balance)
|
||||
if (cost > accountBalance)
|
||||
{
|
||||
ConsolePopup(args.Actor, Loc.GetString("cargo-console-insufficient-funds", ("cost", cost)));
|
||||
PlayDenySound(uid, component);
|
||||
@@ -195,7 +166,7 @@ namespace Content.Server.Cargo.Systems
|
||||
|
||||
if (!ev.Handled)
|
||||
{
|
||||
ev.FulfillmentEntity = TryFulfillOrder((station.Value, stationData), order, orderDatabase);
|
||||
ev.FulfillmentEntity = TryFulfillOrder((station.Value, stationData), component.Account, order, orderDatabase);
|
||||
|
||||
if (ev.FulfillmentEntity == null)
|
||||
{
|
||||
@@ -206,7 +177,7 @@ namespace Content.Server.Cargo.Systems
|
||||
}
|
||||
|
||||
order.Approved = true;
|
||||
_audio.PlayPvs(component.ConfirmSound, uid);
|
||||
_audio.PlayPvs(ApproveSound, uid);
|
||||
|
||||
if (!_emag.CheckFlag(uid, EmagType.Interaction))
|
||||
{
|
||||
@@ -220,20 +191,23 @@ namespace Content.Server.Cargo.Systems
|
||||
("approver", order.Approver ?? string.Empty),
|
||||
("cost", cost));
|
||||
_radio.SendRadioMessage(uid, message, component.AnnouncementChannel, uid, escapeMarkup: false);
|
||||
if (CargoOrderConsoleComponent.BaseAnnouncementChannel != component.AnnouncementChannel)
|
||||
_radio.SendRadioMessage(uid, message, CargoOrderConsoleComponent.BaseAnnouncementChannel, uid, escapeMarkup: false);
|
||||
}
|
||||
|
||||
ConsolePopup(args.Actor, Loc.GetString("cargo-console-trade-station", ("destination", MetaData(ev.FulfillmentEntity.Value).EntityName)));
|
||||
|
||||
// Log order approval
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||
$"{ToPrettyString(player):user} approved order [orderId:{order.OrderId}, quantity:{order.OrderQuantity}, product:{order.ProductId}, requester:{order.Requester}, reason:{order.Reason}] with balance at {bank.Balance}");
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(player):user} approved order [orderId:{order.OrderId}, quantity:{order.OrderQuantity}, product:{order.ProductId}, requester:{order.Requester}, reason:{order.Reason}] on account {component.Account} with balance at {accountBalance}");
|
||||
|
||||
orderDatabase.Orders.Remove(order);
|
||||
UpdateBankAccount((station.Value, bank), -cost);
|
||||
orderDatabase.Orders[component.Account].Remove(order);
|
||||
UpdateBankAccount((station.Value, bank), -cost, CreateAccountDistribution(component.Account, bank));
|
||||
UpdateOrders(station.Value);
|
||||
}
|
||||
|
||||
private EntityUid? TryFulfillOrder(Entity<StationDataComponent> stationData, CargoOrderData order, StationCargoOrderDatabaseComponent orderDatabase)
|
||||
private EntityUid? TryFulfillOrder(Entity<StationDataComponent> stationData, ProtoId<CargoAccountPrototype> account, CargoOrderData order, StationCargoOrderDatabaseComponent orderDatabase)
|
||||
{
|
||||
// No slots at the trade station
|
||||
_listEnts.Clear();
|
||||
@@ -253,7 +227,7 @@ namespace Content.Server.Cargo.Systems
|
||||
{
|
||||
var coordinates = new EntityCoordinates(trade, pad.Transform.LocalPosition);
|
||||
|
||||
if (FulfillOrder(order, coordinates, orderDatabase.PrinterOutput))
|
||||
if (FulfillOrder(order, account, coordinates, orderDatabase.PrinterOutput))
|
||||
{
|
||||
tradeDestination = trade;
|
||||
order.NumDispatched++;
|
||||
@@ -288,7 +262,7 @@ namespace Content.Server.Cargo.Systems
|
||||
if (!TryGetOrderDatabase(station, out var orderDatabase))
|
||||
return;
|
||||
|
||||
RemoveOrder(station.Value, args.OrderId, orderDatabase);
|
||||
RemoveOrder(station.Value, component.Account, args.OrderId, orderDatabase);
|
||||
}
|
||||
|
||||
private void OnAddOrderMessage(EntityUid uid, CargoOrderConsoleComponent component, CargoConsoleAddOrderMessage args)
|
||||
@@ -315,14 +289,15 @@ namespace Content.Server.Cargo.Systems
|
||||
|
||||
var data = GetOrderData(args, product, GenerateOrderId(orderDatabase));
|
||||
|
||||
if (!TryAddOrder(stationUid.Value, data, orderDatabase))
|
||||
if (!TryAddOrder(stationUid.Value, component.Account, data, orderDatabase))
|
||||
{
|
||||
PlayDenySound(uid, component);
|
||||
return;
|
||||
}
|
||||
|
||||
// Log order addition
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"{ToPrettyString(player):user} added order [orderId:{data.OrderId}, quantity:{data.OrderQuantity}, product:{data.ProductId}, requester:{data.Requester}, reason:{data.Reason}]");
|
||||
|
||||
}
|
||||
@@ -335,29 +310,24 @@ namespace Content.Server.Cargo.Systems
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void OnOrderBalanceUpdated(Entity<CargoOrderConsoleComponent> ent, ref BankBalanceUpdatedEvent args)
|
||||
{
|
||||
if (!_uiSystem.IsUiOpen(ent.Owner, CargoConsoleUiKey.Orders))
|
||||
return;
|
||||
|
||||
UpdateOrderState(ent, args.Station);
|
||||
}
|
||||
|
||||
private void UpdateOrderState(EntityUid consoleUid, EntityUid? station)
|
||||
{
|
||||
if (station == null ||
|
||||
!TryComp<StationCargoOrderDatabaseComponent>(station, out var orderDatabase) ||
|
||||
!TryComp<StationBankAccountComponent>(station, out var bankAccount)) return;
|
||||
if (!TryComp<CargoOrderConsoleComponent>(consoleUid, out var console))
|
||||
return;
|
||||
|
||||
if (!TryComp<StationCargoOrderDatabaseComponent>(station, out var orderDatabase))
|
||||
return;
|
||||
|
||||
if (_uiSystem.HasUi(consoleUid, CargoConsoleUiKey.Orders))
|
||||
{
|
||||
_uiSystem.SetUiState(consoleUid, CargoConsoleUiKey.Orders, new CargoConsoleInterfaceState(
|
||||
_uiSystem.SetUiState(consoleUid,
|
||||
CargoConsoleUiKey.Orders,
|
||||
new CargoConsoleInterfaceState(
|
||||
MetaData(station.Value).EntityName,
|
||||
GetOutstandingOrderCount(orderDatabase),
|
||||
GetOutstandingOrderCount(orderDatabase, console.Account),
|
||||
orderDatabase.Capacity,
|
||||
bankAccount.Balance,
|
||||
orderDatabase.Orders
|
||||
GetNetEntity(station.Value),
|
||||
orderDatabase.Orders[console.Account]
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -377,11 +347,11 @@ namespace Content.Server.Cargo.Systems
|
||||
return new CargoOrderData(id, cargoProduct.Product, cargoProduct.Name, cargoProduct.Cost, args.Amount, args.Requester, args.Reason);
|
||||
}
|
||||
|
||||
public static int GetOutstandingOrderCount(StationCargoOrderDatabaseComponent component)
|
||||
public static int GetOutstandingOrderCount(StationCargoOrderDatabaseComponent component, ProtoId<CargoAccountPrototype> account)
|
||||
{
|
||||
var amount = 0;
|
||||
|
||||
foreach (var order in component.Orders)
|
||||
foreach (var order in component.Orders[account])
|
||||
{
|
||||
if (!order.Approved)
|
||||
continue;
|
||||
@@ -430,6 +400,7 @@ namespace Content.Server.Cargo.Systems
|
||||
string description,
|
||||
string dest,
|
||||
StationCargoOrderDatabaseComponent component,
|
||||
ProtoId<CargoAccountPrototype> account,
|
||||
Entity<StationDataComponent> stationData
|
||||
)
|
||||
{
|
||||
@@ -443,16 +414,17 @@ namespace Content.Server.Cargo.Systems
|
||||
order.Approved = true;
|
||||
|
||||
// Log order addition
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||
_adminLogger.Add(LogType.Action,
|
||||
LogImpact.Low,
|
||||
$"AddAndApproveOrder {description} added order [orderId:{order.OrderId}, quantity:{order.OrderQuantity}, product:{order.ProductId}, requester:{order.Requester}, reason:{order.Reason}]");
|
||||
|
||||
// Add it to the list
|
||||
return TryAddOrder(dbUid, order, component) && TryFulfillOrder(stationData, order, component).HasValue;
|
||||
return TryAddOrder(dbUid, account, order, component) && TryFulfillOrder(stationData, account, order, component).HasValue;
|
||||
}
|
||||
|
||||
private bool TryAddOrder(EntityUid dbUid, CargoOrderData data, StationCargoOrderDatabaseComponent component)
|
||||
private bool TryAddOrder(EntityUid dbUid, ProtoId<CargoAccountPrototype> account, CargoOrderData data, StationCargoOrderDatabaseComponent component)
|
||||
{
|
||||
component.Orders.Add(data);
|
||||
component.Orders[account].Add(data);
|
||||
UpdateOrders(dbUid);
|
||||
return true;
|
||||
}
|
||||
@@ -464,12 +436,12 @@ namespace Content.Server.Cargo.Systems
|
||||
return ++orderDB.NumOrdersCreated;
|
||||
}
|
||||
|
||||
public void RemoveOrder(EntityUid dbUid, int index, StationCargoOrderDatabaseComponent orderDB)
|
||||
public void RemoveOrder(EntityUid dbUid, ProtoId<CargoAccountPrototype> account, int index, StationCargoOrderDatabaseComponent orderDB)
|
||||
{
|
||||
var sequenceIdx = orderDB.Orders.FindIndex(order => order.OrderId == index);
|
||||
var sequenceIdx = orderDB.Orders[account].FindIndex(order => order.OrderId == index);
|
||||
if (sequenceIdx != -1)
|
||||
{
|
||||
orderDB.Orders.RemoveAt(sequenceIdx);
|
||||
orderDB.Orders[account].RemoveAt(sequenceIdx);
|
||||
}
|
||||
UpdateOrders(dbUid);
|
||||
}
|
||||
@@ -482,22 +454,22 @@ namespace Content.Server.Cargo.Systems
|
||||
component.Orders.Clear();
|
||||
}
|
||||
|
||||
private static bool PopFrontOrder(StationCargoOrderDatabaseComponent orderDB, [NotNullWhen(true)] out CargoOrderData? orderOut)
|
||||
private static bool PopFrontOrder(StationCargoOrderDatabaseComponent orderDB, ProtoId<CargoAccountPrototype> account, [NotNullWhen(true)] out CargoOrderData? orderOut)
|
||||
{
|
||||
var orderIdx = orderDB.Orders.FindIndex(order => order.Approved);
|
||||
var orderIdx = orderDB.Orders[account].FindIndex(order => order.Approved);
|
||||
if (orderIdx == -1)
|
||||
{
|
||||
orderOut = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
orderOut = orderDB.Orders[orderIdx];
|
||||
orderOut = orderDB.Orders[account][orderIdx];
|
||||
orderOut.NumDispatched++;
|
||||
|
||||
if (orderOut.NumDispatched >= orderOut.OrderQuantity)
|
||||
{
|
||||
// Order is complete. Remove from the queue.
|
||||
orderDB.Orders.RemoveAt(orderIdx);
|
||||
orderDB.Orders[account].RemoveAt(orderIdx);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -505,18 +477,19 @@ namespace Content.Server.Cargo.Systems
|
||||
/// <summary>
|
||||
/// Tries to fulfill the next outstanding order.
|
||||
/// </summary>
|
||||
private bool FulfillNextOrder(StationCargoOrderDatabaseComponent orderDB, EntityCoordinates spawn, string? paperProto)
|
||||
[PublicAPI]
|
||||
private bool FulfillNextOrder(StationCargoOrderDatabaseComponent orderDB, ProtoId<CargoAccountPrototype> account, EntityCoordinates spawn, string? paperProto)
|
||||
{
|
||||
if (!PopFrontOrder(orderDB, out var order))
|
||||
if (!PopFrontOrder(orderDB, account, out var order))
|
||||
return false;
|
||||
|
||||
return FulfillOrder(order, spawn, paperProto);
|
||||
return FulfillOrder(order, account, spawn, paperProto);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fulfills the specified cargo order and spawns paper attached to it.
|
||||
/// </summary>
|
||||
private bool FulfillOrder(CargoOrderData order, EntityCoordinates spawn, string? paperProto)
|
||||
private bool FulfillOrder(CargoOrderData order, ProtoId<CargoAccountPrototype> account, EntityCoordinates spawn, string? paperProto)
|
||||
{
|
||||
// Create the item itself
|
||||
var item = Spawn(order.ProductId, spawn);
|
||||
@@ -532,14 +505,18 @@ namespace Content.Server.Cargo.Systems
|
||||
var val = Loc.GetString("cargo-console-paper-print-name", ("orderNumber", order.OrderId));
|
||||
_metaSystem.SetEntityName(printed, val);
|
||||
|
||||
_paperSystem.SetContent((printed, paper), Loc.GetString(
|
||||
var accountProto = _protoMan.Index(account);
|
||||
_paperSystem.SetContent((printed, paper),
|
||||
Loc.GetString(
|
||||
"cargo-console-paper-print-text",
|
||||
("orderNumber", order.OrderId),
|
||||
("itemName", MetaData(item).EntityName),
|
||||
("orderQuantity", order.OrderQuantity),
|
||||
("requester", order.Requester),
|
||||
("reason", order.Reason),
|
||||
("approver", order.Approver ?? string.Empty)));
|
||||
("reason", string.IsNullOrWhiteSpace(order.Reason) ? Loc.GetString("cargo-console-paper-reason-default") : order.Reason),
|
||||
("account", Loc.GetString(accountProto.Name)),
|
||||
("accountcode", Loc.GetString(accountProto.Code)),
|
||||
("approver", string.IsNullOrWhiteSpace(order.Approver) ? Loc.GetString("cargo-console-paper-approver-default") : order.Approver)));
|
||||
|
||||
// attempt to attach the label to the item
|
||||
if (TryComp<PaperLabelComponent>(item, out var label))
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Cargo.Components;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Cargo;
|
||||
using Content.Shared.Cargo.BUI;
|
||||
using Content.Shared.Cargo.Components;
|
||||
using Content.Shared.Cargo.Events;
|
||||
using Content.Shared.GameTicking;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Shared.Cargo.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Cargo.Systems;
|
||||
|
||||
@@ -28,12 +28,11 @@ public sealed partial class CargoSystem
|
||||
SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletSellMessage>(OnPalletSale);
|
||||
SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletAppraiseMessage>(OnPalletAppraise);
|
||||
SubscribeLocalEvent<CargoPalletConsoleComponent, BoundUIOpenedEvent>(OnPalletUIOpen);
|
||||
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
||||
}
|
||||
|
||||
#region Console
|
||||
|
||||
[PublicAPI]
|
||||
private void UpdateCargoShuttleConsoles(EntityUid shuttleUid, CargoShuttleComponent _)
|
||||
{
|
||||
// Update pilot consoles that are already open.
|
||||
@@ -54,15 +53,18 @@ public sealed partial class CargoSystem
|
||||
|
||||
private void UpdatePalletConsoleInterface(EntityUid uid)
|
||||
{
|
||||
if (Transform(uid).GridUid is not EntityUid gridUid)
|
||||
if (Transform(uid).GridUid is not { } gridUid)
|
||||
{
|
||||
_uiSystem.SetUiState(uid, CargoPalletConsoleUiKey.Sale,
|
||||
new CargoPalletConsoleInterfaceState(0, 0, false));
|
||||
_uiSystem.SetUiState(uid,
|
||||
CargoPalletConsoleUiKey.Sale,
|
||||
new CargoPalletConsoleInterfaceState(0, 0, false));
|
||||
return;
|
||||
}
|
||||
GetPalletGoods(gridUid, out var toSell, out var amount);
|
||||
_uiSystem.SetUiState(uid, CargoPalletConsoleUiKey.Sale,
|
||||
new CargoPalletConsoleInterfaceState((int) amount, toSell.Count, true));
|
||||
GetPalletGoods(gridUid, out var toSell, out var goods);
|
||||
var totalAmount = goods.Sum(t => t.Item3);
|
||||
_uiSystem.SetUiState(uid,
|
||||
CargoPalletConsoleUiKey.Sale,
|
||||
new CargoPalletConsoleInterfaceState((int) totalAmount, toSell.Count, true));
|
||||
}
|
||||
|
||||
private void OnPalletUIOpen(EntityUid uid, CargoPalletConsoleComponent component, BoundUIOpenedEvent args)
|
||||
@@ -98,11 +100,15 @@ public sealed partial class CargoSystem
|
||||
var shuttleName = orderDatabase?.Shuttle != null ? MetaData(orderDatabase.Shuttle.Value).EntityName : string.Empty;
|
||||
|
||||
if (_uiSystem.HasUi(uid, CargoConsoleUiKey.Shuttle))
|
||||
_uiSystem.SetUiState(uid, CargoConsoleUiKey.Shuttle, new CargoShuttleConsoleBoundUserInterfaceState(
|
||||
{
|
||||
_uiSystem.SetUiState(uid,
|
||||
CargoConsoleUiKey.Shuttle,
|
||||
new CargoShuttleConsoleBoundUserInterfaceState(
|
||||
station != null ? MetaData(station.Value).EntityName : Loc.GetString("cargo-shuttle-console-station-unknown"),
|
||||
string.IsNullOrEmpty(shuttleName) ? Loc.GetString("cargo-shuttle-console-shuttle-not-found") : shuttleName,
|
||||
orders
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -132,9 +138,10 @@ public sealed partial class CargoSystem
|
||||
return orders;
|
||||
|
||||
var spaceRemaining = GetCargoSpace(shuttleUid);
|
||||
for (var i = 0; i < component.Orders.Count && spaceRemaining > 0; i++)
|
||||
var allOrders = component.AllOrders.ToList();
|
||||
for (var i = 0; i < allOrders.Count && spaceRemaining > 0; i++)
|
||||
{
|
||||
var order = component.Orders[i];
|
||||
var order = allOrders[i];
|
||||
if (order.Approved)
|
||||
{
|
||||
var numToShip = order.OrderQuantity - order.NumDispatched;
|
||||
@@ -142,8 +149,14 @@ public sealed partial class CargoSystem
|
||||
{
|
||||
// We won't be able to fit the whole order on, so make one
|
||||
// which represents the space we do have left:
|
||||
var reducedOrder = new CargoOrderData(order.OrderId,
|
||||
order.ProductId, order.ProductName, order.Price, spaceRemaining, order.Requester, order.Reason);
|
||||
var reducedOrder = new CargoOrderData(
|
||||
order.OrderId,
|
||||
order.ProductId,
|
||||
order.ProductName,
|
||||
order.Price,
|
||||
spaceRemaining,
|
||||
order.Requester,
|
||||
order.Reason);
|
||||
orders.Add(reducedOrder);
|
||||
}
|
||||
else
|
||||
@@ -219,16 +232,13 @@ public sealed partial class CargoSystem
|
||||
|
||||
#region Station
|
||||
|
||||
private bool SellPallets(EntityUid gridUid, out double amount)
|
||||
private bool SellPallets(EntityUid gridUid, out HashSet<(EntityUid, OverrideSellComponent?, double)> goods)
|
||||
{
|
||||
GetPalletGoods(gridUid, out var toSell, out amount);
|
||||
|
||||
Log.Debug($"Cargo sold {toSell.Count} entities for {amount}");
|
||||
GetPalletGoods(gridUid, out var toSell, out goods);
|
||||
|
||||
if (toSell.Count == 0)
|
||||
return false;
|
||||
|
||||
|
||||
var ev = new EntitySoldEvent(toSell);
|
||||
RaiseLocalEvent(ref ev);
|
||||
|
||||
@@ -240,9 +250,9 @@ public sealed partial class CargoSystem
|
||||
return true;
|
||||
}
|
||||
|
||||
private void GetPalletGoods(EntityUid gridUid, out HashSet<EntityUid> toSell, out double amount)
|
||||
private void GetPalletGoods(EntityUid gridUid, out HashSet<EntityUid> toSell, out HashSet<(EntityUid, OverrideSellComponent?, double)> goods)
|
||||
{
|
||||
amount = 0;
|
||||
goods = new HashSet<(EntityUid, OverrideSellComponent?, double)>();
|
||||
toSell = new HashSet<EntityUid>();
|
||||
|
||||
foreach (var (palletUid, _, _) in GetCargoPallets(gridUid, BuySellType.Sell))
|
||||
@@ -250,7 +260,9 @@ public sealed partial class CargoSystem
|
||||
// Containers should already get the sell price of their children so can skip those.
|
||||
_setEnts.Clear();
|
||||
|
||||
_lookup.GetEntitiesIntersecting(palletUid, _setEnts,
|
||||
_lookup.GetEntitiesIntersecting(
|
||||
palletUid,
|
||||
_setEnts,
|
||||
LookupFlags.Dynamic | LookupFlags.Sundries);
|
||||
|
||||
foreach (var ent in _setEnts)
|
||||
@@ -273,7 +285,7 @@ public sealed partial class CargoSystem
|
||||
if (price == 0)
|
||||
continue;
|
||||
toSell.Add(ent);
|
||||
amount += price;
|
||||
goods.Add((ent, CompOrNull<OverrideSellComponent>(ent), price));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,28 +317,49 @@ public sealed partial class CargoSystem
|
||||
{
|
||||
var xform = Transform(uid);
|
||||
|
||||
if (xform.GridUid is not EntityUid gridUid)
|
||||
if (_station.GetOwningStation(uid) is not { } station ||
|
||||
!TryComp<StationBankAccountComponent>(station, out var bankAccount))
|
||||
{
|
||||
_uiSystem.SetUiState(uid, CargoPalletConsoleUiKey.Sale,
|
||||
new CargoPalletConsoleInterfaceState(0, 0, false));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SellPallets(gridUid, out var price))
|
||||
if (xform.GridUid is not { } gridUid)
|
||||
{
|
||||
_uiSystem.SetUiState(uid,
|
||||
CargoPalletConsoleUiKey.Sale,
|
||||
new CargoPalletConsoleInterfaceState(0, 0, false));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SellPallets(gridUid, out var goods))
|
||||
return;
|
||||
|
||||
var stackPrototype = _protoMan.Index<StackPrototype>(component.CashType);
|
||||
_stack.Spawn((int) price, stackPrototype, xform.Coordinates);
|
||||
var baseDistribution = CreateAccountDistribution(bankAccount.PrimaryAccount, bankAccount, bankAccount.PrimaryCut);
|
||||
foreach (var (_, sellComponent, value) in goods)
|
||||
{
|
||||
Dictionary<ProtoId<CargoAccountPrototype>, double> distribution;
|
||||
if (sellComponent != null)
|
||||
{
|
||||
distribution = new Dictionary<ProtoId<CargoAccountPrototype>, double>()
|
||||
{
|
||||
{ sellComponent.OverrideAccount, bankAccount.PrimaryCut },
|
||||
{ bankAccount.PrimaryAccount, 1.0 - bankAccount.PrimaryCut },
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
distribution = baseDistribution;
|
||||
}
|
||||
|
||||
UpdateBankAccount((station, bankAccount), (int) Math.Round(value), distribution, false);
|
||||
}
|
||||
|
||||
Dirty(station, bankAccount);
|
||||
_audio.PlayPvs(ApproveSound, uid);
|
||||
UpdatePalletConsoleInterface(uid);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Cargo.Components;
|
||||
using Content.Server.Power.Components;
|
||||
@@ -40,9 +41,8 @@ public sealed partial class CargoSystem
|
||||
continue;
|
||||
|
||||
// todo cannot be fucking asked to figure out device linking rn but this shouldn't just default to the first port.
|
||||
if (!TryComp<DeviceLinkSinkComponent>(uid, out var sinkComponent) ||
|
||||
sinkComponent.LinkedSources.FirstOrNull() is not { } console ||
|
||||
console != args.OrderConsole.Owner)
|
||||
if (!TryGetLinkedConsole((uid, tele), out var console) ||
|
||||
console.Value.Owner != args.OrderConsole.Owner)
|
||||
continue;
|
||||
|
||||
for (var i = 0; i < args.Order.OrderQuantity; i++)
|
||||
@@ -56,10 +56,26 @@ public sealed partial class CargoSystem
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetLinkedConsole(Entity<CargoTelepadComponent> ent,
|
||||
[NotNullWhen(true)] out Entity<CargoOrderConsoleComponent>? console)
|
||||
{
|
||||
console = null;
|
||||
if (!TryComp<DeviceLinkSinkComponent>(ent, out var sinkComponent) ||
|
||||
sinkComponent.LinkedSources.FirstOrNull() is not { } linked)
|
||||
return false;
|
||||
|
||||
if (!TryComp<CargoOrderConsoleComponent>(linked, out var consoleComp))
|
||||
return false;
|
||||
|
||||
console = (linked, consoleComp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void UpdateTelepad(float frameTime)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CargoTelepadComponent>();
|
||||
while (query.MoveNext(out var uid, out var comp))
|
||||
var query = EntityQueryEnumerator<CargoTelepadComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var uid, out var comp, out var xform))
|
||||
{
|
||||
// Don't EntityQuery for it as it's not required.
|
||||
TryComp<AppearanceComponent>(uid, out var appearance);
|
||||
@@ -82,15 +98,14 @@ public sealed partial class CargoSystem
|
||||
continue;
|
||||
}
|
||||
|
||||
if (comp.CurrentOrders.Count == 0)
|
||||
if (comp.CurrentOrders.Count == 0 || !TryGetLinkedConsole((uid, comp), out var console))
|
||||
{
|
||||
comp.Accumulator += comp.Delay;
|
||||
continue;
|
||||
}
|
||||
|
||||
var xform = Transform(uid);
|
||||
var currentOrder = comp.CurrentOrders.First();
|
||||
if (FulfillOrder(currentOrder, xform.Coordinates, comp.PrinterOutput))
|
||||
if (FulfillOrder(currentOrder, console.Value.Comp.Account, xform.Coordinates, comp.PrinterOutput))
|
||||
{
|
||||
_audio.PlayPvs(_audio.ResolveSound(comp.TeleportSound), uid, AudioParams.Default.WithVolume(-8f));
|
||||
|
||||
@@ -128,9 +143,12 @@ public sealed partial class CargoSystem
|
||||
!TryComp<StationDataComponent>(station, out var data))
|
||||
return;
|
||||
|
||||
if (!TryGetLinkedConsole(ent, out var console))
|
||||
return;
|
||||
|
||||
foreach (var order in ent.Comp.CurrentOrders)
|
||||
{
|
||||
TryFulfillOrder((station, data), order, db);
|
||||
TryFulfillOrder((station, data), console.Value.Comp.Account, order, db);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using Content.Shared.Administration.Logs;
|
||||
using Content.Server.Radio.EntitySystems;
|
||||
using Content.Shared.Cargo;
|
||||
using Content.Shared.Cargo.Components;
|
||||
using Content.Shared.Cargo.Prototypes;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Paper;
|
||||
@@ -65,36 +66,46 @@ public sealed partial class CargoSystem : SharedCargoSystem
|
||||
InitializeShuttle();
|
||||
InitializeTelepad();
|
||||
InitializeBounty();
|
||||
InitializeFunds();
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
UpdateConsole(frameTime);
|
||||
UpdateConsole();
|
||||
UpdateTelepad(frameTime);
|
||||
UpdateBounty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or removes funds from the <see cref="StationBankAccountComponent"/>.
|
||||
/// </summary>
|
||||
/// <param name="ent">The station.</param>
|
||||
/// <param name="balanceAdded">The amount of funds to add or remove.</param>
|
||||
/// <param name="accountDistribution">The distribution between individual <see cref="CargoAccountPrototype"/>.</param>
|
||||
/// <param name="dirty">Whether to mark the bank accoujnt component as dirty.</param>
|
||||
[PublicAPI]
|
||||
public void UpdateBankAccount(Entity<StationBankAccountComponent?> ent, int balanceAdded)
|
||||
public void UpdateBankAccount(
|
||||
Entity<StationBankAccountComponent?> ent,
|
||||
int balanceAdded,
|
||||
Dictionary<ProtoId<CargoAccountPrototype>, double> accountDistribution,
|
||||
bool dirty = true)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp))
|
||||
return;
|
||||
|
||||
ent.Comp.Balance += balanceAdded;
|
||||
|
||||
var ev = new BankBalanceUpdatedEvent(ent, ent.Comp.Balance);
|
||||
|
||||
var query = EntityQueryEnumerator<BankClientComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var client, out var comp, out var xform))
|
||||
foreach (var (account, percent) in accountDistribution)
|
||||
{
|
||||
var station = _station.GetOwningStation(client, xform);
|
||||
if (station != ent)
|
||||
continue;
|
||||
|
||||
comp.Balance = ent.Comp.Balance;
|
||||
Dirty(client, comp);
|
||||
RaiseLocalEvent(client, ref ev);
|
||||
var accountBalancedAdded = (int) Math.Round(percent * balanceAdded);
|
||||
ent.Comp.Accounts[account] += accountBalancedAdded;
|
||||
}
|
||||
|
||||
var ev = new BankBalanceUpdatedEvent(ent, ent.Comp.Accounts);
|
||||
RaiseLocalEvent(ent, ref ev, true);
|
||||
|
||||
if (!dirty)
|
||||
return;
|
||||
|
||||
Dirty(ent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Server.Cargo.Components;
|
||||
using Content.Server.Cargo.Systems;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.StationRecords.Systems;
|
||||
using Content.Shared.Cargo.Components;
|
||||
using Content.Shared.Delivery;
|
||||
using Content.Shared.FingerprintReader;
|
||||
using Content.Shared.Labels.EntitySystems;
|
||||
@@ -73,7 +73,10 @@ public sealed partial class DeliverySystem : SharedDeliverySystem
|
||||
if (!TryComp<StationBankAccountComponent>(ent.Comp.RecipientStation, out var account))
|
||||
return;
|
||||
|
||||
_cargo.UpdateBankAccount((ent.Comp.RecipientStation.Value, account), ent.Comp.SpesoReward);
|
||||
_cargo.UpdateBankAccount(
|
||||
(ent.Comp.RecipientStation.Value, account),
|
||||
ent.Comp.SpesoReward,
|
||||
_cargo.CreateAccountDistribution(account.PrimaryAccount, account, account.PrimaryCut));
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Content.Server.Stack
|
||||
public EntityUid Spawn(int amount, StackPrototype prototype, EntityCoordinates spawnPosition)
|
||||
{
|
||||
// Set the output result parameter to the new stack entity...
|
||||
var entity = Spawn(prototype.Spawn, spawnPosition);
|
||||
var entity = SpawnAtPosition(prototype.Spawn, spawnPosition);
|
||||
var stack = Comp<StackComponent>(entity);
|
||||
|
||||
// And finally, set the correct amount!
|
||||
|
||||
@@ -8,6 +8,7 @@ using Content.Shared.Station;
|
||||
using Content.Shared.Station.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Configuration;
|
||||
@@ -34,6 +35,7 @@ public sealed class StationSystem : EntitySystem
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly MapSystem _map = default!;
|
||||
[Dependency] private readonly PvsOverrideSystem _pvsOverride = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
@@ -97,7 +99,7 @@ public sealed class StationSystem : EntitySystem
|
||||
var metaData = MetaData(uid);
|
||||
RaiseLocalEvent(new StationInitializedEvent(uid));
|
||||
_sawmill.Info($"Set up station {metaData.EntityName} ({uid}).");
|
||||
|
||||
_pvsOverride.AddGlobalOverride(uid);
|
||||
}
|
||||
|
||||
private void OnStationDeleted(EntityUid uid, StationDataComponent component, ComponentShutdown args)
|
||||
|
||||
@@ -34,6 +34,12 @@ public sealed partial class CargoGiftsRuleComponent : Component
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public LocId Dest = "cargo-gift-default-dest";
|
||||
|
||||
/// <summary>
|
||||
/// Account the gifts are deposited into
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ProtoId<CargoAccountPrototype> Account = "Cargo";
|
||||
|
||||
/// <summary>
|
||||
/// Cargo that you would like gifted to the station, with the quantity for each
|
||||
/// Use Ids from cargoProduct Prototypes
|
||||
|
||||
@@ -53,7 +53,7 @@ public sealed class CargoGiftsRule : StationEventSystem<CargoGiftsRuleComponent>
|
||||
}
|
||||
|
||||
// Add some presents
|
||||
var outstanding = CargoSystem.GetOutstandingOrderCount(cargoDb);
|
||||
var outstanding = CargoSystem.GetOutstandingOrderCount(cargoDb, component.Account);
|
||||
while (outstanding < cargoDb.Capacity - component.OrderSpaceToLeave && component.Gifts.Count > 0)
|
||||
{
|
||||
// I wish there was a nice way to pop this
|
||||
@@ -72,6 +72,7 @@ public sealed class CargoGiftsRule : StationEventSystem<CargoGiftsRuleComponent>
|
||||
Loc.GetString(component.Description),
|
||||
Loc.GetString(component.Dest),
|
||||
cargoDb,
|
||||
component.Account,
|
||||
(station.Value, stationData)
|
||||
))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user