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>
@@ -1,6 +1,7 @@
|
|||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
using Content.Client.Cargo.UI;
|
using Content.Client.Cargo.UI;
|
||||||
using Content.Shared.Cargo.BUI;
|
using Content.Shared.Cargo.BUI;
|
||||||
|
using Content.Shared.Cargo.Components;
|
||||||
using Content.Shared.Cargo.Events;
|
using Content.Shared.Cargo.Events;
|
||||||
using Content.Shared.Cargo.Prototypes;
|
using Content.Shared.Cargo.Prototypes;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
@@ -14,6 +15,8 @@ namespace Content.Client.Cargo.BUI
|
|||||||
{
|
{
|
||||||
public sealed class CargoOrderConsoleBoundUserInterface : BoundUserInterface
|
public sealed class CargoOrderConsoleBoundUserInterface : BoundUserInterface
|
||||||
{
|
{
|
||||||
|
private readonly SharedCargoSystem _cargoSystem;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private CargoConsoleMenu? _menu;
|
private CargoConsoleMenu? _menu;
|
||||||
|
|
||||||
@@ -43,6 +46,7 @@ namespace Content.Client.Cargo.BUI
|
|||||||
|
|
||||||
public CargoOrderConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
public CargoOrderConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||||
{
|
{
|
||||||
|
_cargoSystem = EntMan.System<SharedCargoSystem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Open()
|
protected override void Open()
|
||||||
@@ -57,7 +61,7 @@ namespace Content.Client.Cargo.BUI
|
|||||||
|
|
||||||
string orderRequester;
|
string orderRequester;
|
||||||
|
|
||||||
if (EntMan.TryGetComponent<MetaDataComponent>(localPlayer, out var metadata))
|
if (EntMan.EntityExists(localPlayer))
|
||||||
orderRequester = Identity.Name(localPlayer.Value, EntMan);
|
orderRequester = Identity.Name(localPlayer.Value, EntMan);
|
||||||
else
|
else
|
||||||
orderRequester = string.Empty;
|
orderRequester = string.Empty;
|
||||||
@@ -96,41 +100,54 @@ namespace Content.Client.Cargo.BUI
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_menu.OnAccountAction += (account, amount) =>
|
||||||
|
{
|
||||||
|
SendMessage(new CargoConsoleWithdrawFundsMessage(account, amount));
|
||||||
|
};
|
||||||
|
|
||||||
|
_menu.OnToggleUnboundedLimit += _ =>
|
||||||
|
{
|
||||||
|
SendMessage(new CargoConsoleToggleLimitMessage());
|
||||||
|
};
|
||||||
|
|
||||||
_menu.OpenCentered();
|
_menu.OpenCentered();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Populate(List<CargoOrderData> orders)
|
private void Populate(List<CargoOrderData> orders)
|
||||||
{
|
{
|
||||||
if (_menu == null) return;
|
if (_menu == null)
|
||||||
|
return;
|
||||||
|
|
||||||
_menu.PopulateProducts();
|
_menu.PopulateProducts();
|
||||||
_menu.PopulateCategories();
|
_menu.PopulateCategories();
|
||||||
_menu.PopulateOrders(orders);
|
_menu.PopulateOrders(orders);
|
||||||
|
_menu.PopulateAccountActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateState(BoundUserInterfaceState state)
|
protected override void UpdateState(BoundUserInterfaceState state)
|
||||||
{
|
{
|
||||||
base.UpdateState(state);
|
base.UpdateState(state);
|
||||||
|
|
||||||
if (state is not CargoConsoleInterfaceState cState)
|
if (state is not CargoConsoleInterfaceState cState || !EntMan.TryGetComponent<CargoOrderConsoleComponent>(Owner, out var orderConsole))
|
||||||
return;
|
return;
|
||||||
|
var station = EntMan.GetEntity(cState.Station);
|
||||||
|
|
||||||
OrderCapacity = cState.Capacity;
|
OrderCapacity = cState.Capacity;
|
||||||
OrderCount = cState.Count;
|
OrderCount = cState.Count;
|
||||||
BankBalance = cState.Balance;
|
BankBalance = _cargoSystem.GetBalanceFromAccount(station, orderConsole.Account);
|
||||||
|
|
||||||
AccountName = cState.Name;
|
AccountName = cState.Name;
|
||||||
|
|
||||||
|
_menu?.UpdateStation(station);
|
||||||
Populate(cState.Orders);
|
Populate(cState.Orders);
|
||||||
_menu?.UpdateCargoCapacity(OrderCount, OrderCapacity);
|
|
||||||
_menu?.UpdateBankData(AccountName, BankBalance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|
||||||
if (!disposing) return;
|
if (!disposing)
|
||||||
|
return;
|
||||||
|
|
||||||
_menu?.Dispose();
|
_menu?.Dispose();
|
||||||
_orderMenu?.Dispose();
|
_orderMenu?.Dispose();
|
||||||
@@ -170,8 +187,6 @@ namespace Content.Client.Cargo.BUI
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
SendMessage(new CargoConsoleApproveOrderMessage(row.Order.OrderId));
|
SendMessage(new CargoConsoleApproveOrderMessage(row.Order.OrderId));
|
||||||
// Most of the UI isn't predicted anyway so.
|
|
||||||
// _menu?.UpdateCargoCapacity(OrderCount + row.Order.Amount, OrderCapacity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using Content.Client.Cargo.UI;
|
||||||
|
using Content.Shared.Cargo.Components;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
|
||||||
|
namespace Content.Client.Cargo.BUI;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class FundingAllocationConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
||||||
|
{
|
||||||
|
[ViewVariables]
|
||||||
|
private FundingAllocationMenu? _menu;
|
||||||
|
|
||||||
|
protected override void Open()
|
||||||
|
{
|
||||||
|
base.Open();
|
||||||
|
|
||||||
|
_menu = this.CreateWindow<FundingAllocationMenu>();
|
||||||
|
|
||||||
|
_menu.OnSavePressed += d =>
|
||||||
|
{
|
||||||
|
SendMessage(new SetFundingAllocationBuiMessage(d));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateState(BoundUserInterfaceState message)
|
||||||
|
{
|
||||||
|
base.UpdateState(message);
|
||||||
|
|
||||||
|
if (message is not FundingAllocationConsoleBuiState state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_menu?.Update(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,25 +3,22 @@
|
|||||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
SetSize="600 600"
|
SetSize="600 600"
|
||||||
MinSize="600 600">
|
MinSize="600 600">
|
||||||
<BoxContainer Orientation="Vertical" Margin="5 0 5 0">
|
<BoxContainer Orientation="Vertical" Margin="15 5 15 10">
|
||||||
<BoxContainer Orientation="Horizontal">
|
<BoxContainer Orientation="Horizontal">
|
||||||
<Label Text="{Loc 'cargo-console-menu-account-name-label'}"
|
<Label Text="{Loc 'cargo-console-menu-account-name-label'}"
|
||||||
StyleClasses="LabelKeyText" />
|
StyleClasses="LabelKeyText" />
|
||||||
<Label Name="AccountNameLabel"
|
<RichTextLabel Name="AccountNameLabel"
|
||||||
Text="{Loc 'cargo-console-menu-account-name-none-text'}" />
|
Text="{Loc 'cargo-console-menu-account-name-none-text'}" />
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<BoxContainer Orientation="Horizontal">
|
<BoxContainer Orientation="Horizontal">
|
||||||
<Label Text="{Loc 'cargo-console-menu-points-label'}"
|
<Label Text="{Loc 'cargo-console-menu-points-label'}"
|
||||||
StyleClasses="LabelKeyText" />
|
StyleClasses="LabelKeyText" />
|
||||||
<Label Name="PointsLabel"
|
<RichTextLabel Name="PointsLabel"
|
||||||
Text="$0" />
|
Text="$0" />
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<BoxContainer Orientation="Horizontal">
|
<Control MinHeight="10"/>
|
||||||
<Label Text="{Loc 'cargo-console-menu-order-capacity-label'}"
|
<TabContainer Name="TabContainer" VerticalExpand="True">
|
||||||
StyleClasses="LabelKeyText" />
|
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||||
<Label Name="ShuttleCapacityLabel"
|
|
||||||
Text="0/20" />
|
|
||||||
</BoxContainer>
|
|
||||||
<BoxContainer Orientation="Horizontal">
|
<BoxContainer Orientation="Horizontal">
|
||||||
<OptionButton Name="Categories"
|
<OptionButton Name="Categories"
|
||||||
Prefix="{Loc 'cargo-console-menu-categories-label'}"
|
Prefix="{Loc 'cargo-console-menu-categories-label'}"
|
||||||
@@ -30,9 +27,10 @@
|
|||||||
PlaceHolder="{Loc 'cargo-console-menu-search-bar-placeholder'}"
|
PlaceHolder="{Loc 'cargo-console-menu-search-bar-placeholder'}"
|
||||||
HorizontalExpand="True" />
|
HorizontalExpand="True" />
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
|
<Control MinHeight="5"/>
|
||||||
<ScrollContainer HorizontalExpand="True"
|
<ScrollContainer HorizontalExpand="True"
|
||||||
VerticalExpand="True"
|
VerticalExpand="True"
|
||||||
SizeFlagsStretchRatio="6">
|
SizeFlagsStretchRatio="2">
|
||||||
<BoxContainer Name="Products"
|
<BoxContainer Name="Products"
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
@@ -40,29 +38,48 @@
|
|||||||
<!-- Products get added here by code -->
|
<!-- Products get added here by code -->
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</ScrollContainer>
|
</ScrollContainer>
|
||||||
|
<Control MinHeight="5"/>
|
||||||
<PanelContainer VerticalExpand="True"
|
<PanelContainer VerticalExpand="True"
|
||||||
SizeFlagsStretchRatio="6">
|
SizeFlagsStretchRatio="1">
|
||||||
<PanelContainer.PanelOverride>
|
<PanelContainer.PanelOverride>
|
||||||
<gfx:StyleBoxFlat BackgroundColor="#000000" />
|
<gfx:StyleBoxFlat BackgroundColor="#000000" />
|
||||||
</PanelContainer.PanelOverride>
|
</PanelContainer.PanelOverride>
|
||||||
<ScrollContainer VerticalExpand="True">
|
<ScrollContainer VerticalExpand="True">
|
||||||
<BoxContainer Orientation="Vertical">
|
<BoxContainer Orientation="Vertical" Margin="5">
|
||||||
<Label Text="{Loc 'cargo-console-menu-requests-label'}" />
|
<Label Text="{Loc 'cargo-console-menu-requests-label'}" />
|
||||||
<BoxContainer Name="Requests"
|
<BoxContainer Name="Requests"
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
VerticalExpand="True">
|
VerticalExpand="True">
|
||||||
<!-- Requests are added here by code -->
|
<!-- Requests are added here by code -->
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<Label Text="{Loc 'cargo-console-menu-orders-label'}" />
|
|
||||||
<BoxContainer Name="Orders"
|
|
||||||
Orientation="Vertical"
|
|
||||||
StyleClasses="transparentItemList"
|
|
||||||
VerticalExpand="True">
|
|
||||||
<!-- Orders are added here by code -->
|
|
||||||
</BoxContainer>
|
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</ScrollContainer>
|
</ScrollContainer>
|
||||||
</PanelContainer>
|
</PanelContainer>
|
||||||
<TextureButton VerticalExpand="True" />
|
</BoxContainer>
|
||||||
|
<!-- Funds tab -->
|
||||||
|
<BoxContainer Orientation="Vertical" Margin="15">
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<RichTextLabel Name="TransferLimitLabel" Margin="0 0 15 0"/>
|
||||||
|
<RichTextLabel Name="UnlimitedNotifier" Text="{Loc 'cargo-console-menu-account-action-transfer-limit-unlimited-notifier'}"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<RichTextLabel Text="{Loc 'cargo-console-menu-account-action-select'}" Margin="0 0 10 0"/>
|
||||||
|
<OptionButton Name="ActionOptions"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<Control MinHeight="5"/>
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<RichTextLabel Name="AmountText" Text="{ Loc 'cargo-console-menu-account-action-amount'}"/>
|
||||||
|
<SpinBox Name="TransferSpinBox" MinWidth="100" Value="10"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<Control MinHeight="15"/>
|
||||||
|
<BoxContainer HorizontalAlignment="Center">
|
||||||
|
<Button Name="AccountActionButton" Text="{ Loc 'cargo-console-menu-account-action-button'}" MinHeight="45" MinWidth="120"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<Control VerticalExpand="True"/>
|
||||||
|
<BoxContainer VerticalAlignment="Bottom" HorizontalAlignment="Center">
|
||||||
|
<Button Name="AccountLimitToggleButton" Text="{ Loc 'cargo-console-menu-toggle-account-lock-button'}" MinHeight="45" MinWidth="120"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</TabContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</controls:FancyWindow>
|
</controls:FancyWindow>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Client.Cargo.Systems;
|
||||||
using Content.Client.UserInterface.Controls;
|
using Content.Client.UserInterface.Controls;
|
||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
@@ -8,6 +9,7 @@ using Robust.Client.GameObjects;
|
|||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
using static Robust.Client.UserInterface.Controls.BaseButton;
|
using static Robust.Client.UserInterface.Controls.BaseButton;
|
||||||
|
|
||||||
namespace Content.Client.Cargo.UI
|
namespace Content.Client.Cargo.UI
|
||||||
@@ -15,30 +17,83 @@ namespace Content.Client.Cargo.UI
|
|||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public sealed partial class CargoConsoleMenu : FancyWindow
|
public sealed partial class CargoConsoleMenu : FancyWindow
|
||||||
{
|
{
|
||||||
private IEntityManager _entityManager;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
private IPrototypeManager _protoManager;
|
|
||||||
private SpriteSystem _spriteSystem;
|
private readonly IEntityManager _entityManager;
|
||||||
|
private readonly IPrototypeManager _protoManager;
|
||||||
|
private readonly CargoSystem _cargoSystem;
|
||||||
|
private readonly SpriteSystem _spriteSystem;
|
||||||
private EntityUid _owner;
|
private EntityUid _owner;
|
||||||
|
private EntityUid? _station;
|
||||||
|
|
||||||
|
private readonly EntityQuery<CargoOrderConsoleComponent> _orderConsoleQuery;
|
||||||
|
private readonly EntityQuery<StationBankAccountComponent> _bankQuery;
|
||||||
|
|
||||||
public event Action<ButtonEventArgs>? OnItemSelected;
|
public event Action<ButtonEventArgs>? OnItemSelected;
|
||||||
public event Action<ButtonEventArgs>? OnOrderApproved;
|
public event Action<ButtonEventArgs>? OnOrderApproved;
|
||||||
public event Action<ButtonEventArgs>? OnOrderCanceled;
|
public event Action<ButtonEventArgs>? OnOrderCanceled;
|
||||||
|
|
||||||
|
public event Action<ProtoId<CargoAccountPrototype>?, int>? OnAccountAction;
|
||||||
|
|
||||||
|
public event Action<ButtonEventArgs>? OnToggleUnboundedLimit;
|
||||||
|
|
||||||
private readonly List<string> _categoryStrings = new();
|
private readonly List<string> _categoryStrings = new();
|
||||||
private string? _category;
|
private string? _category;
|
||||||
|
|
||||||
public CargoConsoleMenu(EntityUid owner, IEntityManager entMan, IPrototypeManager protoManager, SpriteSystem spriteSystem)
|
public CargoConsoleMenu(EntityUid owner, IEntityManager entMan, IPrototypeManager protoManager, SpriteSystem spriteSystem)
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
_entityManager = entMan;
|
_entityManager = entMan;
|
||||||
_protoManager = protoManager;
|
_protoManager = protoManager;
|
||||||
|
_cargoSystem = entMan.System<CargoSystem>();
|
||||||
_spriteSystem = spriteSystem;
|
_spriteSystem = spriteSystem;
|
||||||
_owner = owner;
|
_owner = owner;
|
||||||
|
|
||||||
Title = Loc.GetString("cargo-console-menu-title");
|
_orderConsoleQuery = _entityManager.GetEntityQuery<CargoOrderConsoleComponent>();
|
||||||
|
_bankQuery = _entityManager.GetEntityQuery<StationBankAccountComponent>();
|
||||||
|
|
||||||
|
Title = entMan.GetComponent<MetaDataComponent>(owner).EntityName;
|
||||||
|
|
||||||
SearchBar.OnTextChanged += OnSearchBarTextChanged;
|
SearchBar.OnTextChanged += OnSearchBarTextChanged;
|
||||||
Categories.OnItemSelected += OnCategoryItemSelected;
|
Categories.OnItemSelected += OnCategoryItemSelected;
|
||||||
|
|
||||||
|
if (entMan.TryGetComponent<CargoOrderConsoleComponent>(owner, out var orderConsole))
|
||||||
|
{
|
||||||
|
var accountProto = _protoManager.Index(orderConsole.Account);
|
||||||
|
AccountNameLabel.Text = Loc.GetString("cargo-console-menu-account-name-format",
|
||||||
|
("color", accountProto.Color),
|
||||||
|
("name", Loc.GetString(accountProto.Name)),
|
||||||
|
("code", Loc.GetString(accountProto.Code)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TabContainer.SetTabTitle(0, Loc.GetString("cargo-console-menu-tab-title-orders"));
|
||||||
|
TabContainer.SetTabTitle(1, Loc.GetString("cargo-console-menu-tab-title-funds"));
|
||||||
|
|
||||||
|
ActionOptions.OnItemSelected += idx =>
|
||||||
|
{
|
||||||
|
ActionOptions.SelectId(idx.Id);
|
||||||
|
};
|
||||||
|
|
||||||
|
TransferSpinBox.IsValid = val =>
|
||||||
|
{
|
||||||
|
if (!_entityManager.TryGetComponent<CargoOrderConsoleComponent>(owner, out var console) ||
|
||||||
|
!_entityManager.TryGetComponent<StationBankAccountComponent>(_station, out var bank))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return val >= 0 && val <= (int) (console.TransferLimit * bank.Accounts[console.Account]);
|
||||||
|
};
|
||||||
|
|
||||||
|
AccountActionButton.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
var account = (ProtoId<CargoAccountPrototype>?) ActionOptions.SelectedMetadata;
|
||||||
|
OnAccountAction?.Invoke(account, TransferSpinBox.Value);
|
||||||
|
};
|
||||||
|
|
||||||
|
AccountLimitToggleButton.OnPressed += a =>
|
||||||
|
{
|
||||||
|
OnToggleUnboundedLimit?.Invoke(a);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCategoryItemSelected(OptionButton.ItemSelectedEventArgs args)
|
private void OnCategoryItemSelected(OptionButton.ItemSelectedEventArgs args)
|
||||||
@@ -144,11 +199,13 @@ namespace Content.Client.Cargo.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void PopulateOrders(IEnumerable<CargoOrderData> orders)
|
public void PopulateOrders(IEnumerable<CargoOrderData> orders)
|
||||||
{
|
{
|
||||||
Orders.DisposeAllChildren();
|
|
||||||
Requests.DisposeAllChildren();
|
Requests.DisposeAllChildren();
|
||||||
|
|
||||||
foreach (var order in orders)
|
foreach (var order in orders)
|
||||||
{
|
{
|
||||||
|
if (order.Approved)
|
||||||
|
continue;
|
||||||
|
|
||||||
var product = _protoManager.Index<EntityPrototype>(order.ProductId);
|
var product = _protoManager.Index<EntityPrototype>(order.ProductId);
|
||||||
var productName = product.Name;
|
var productName = product.Name;
|
||||||
|
|
||||||
@@ -164,35 +221,67 @@ namespace Content.Client.Cargo.UI
|
|||||||
("orderAmount", order.OrderQuantity),
|
("orderAmount", order.OrderQuantity),
|
||||||
("orderRequester", order.Requester))
|
("orderRequester", order.Requester))
|
||||||
},
|
},
|
||||||
Description = {Text = Loc.GetString("cargo-console-menu-order-reason-description",
|
Description =
|
||||||
("reason", order.Reason))}
|
{
|
||||||
|
Text = Loc.GetString("cargo-console-menu-order-reason-description",
|
||||||
|
("reason", order.Reason))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
row.Cancel.OnPressed += (args) => { OnOrderCanceled?.Invoke(args); };
|
row.Cancel.OnPressed += (args) => { OnOrderCanceled?.Invoke(args); };
|
||||||
if (order.Approved)
|
|
||||||
{
|
|
||||||
row.Approve.Visible = false;
|
|
||||||
row.Cancel.Visible = false;
|
|
||||||
Orders.AddChild(row);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: Disable based on access.
|
// TODO: Disable based on access.
|
||||||
row.Approve.OnPressed += (args) => { OnOrderApproved?.Invoke(args); };
|
row.Approve.OnPressed += (args) => { OnOrderApproved?.Invoke(args); };
|
||||||
Requests.AddChild(row);
|
Requests.AddChild(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PopulateAccountActions()
|
||||||
|
{
|
||||||
|
if (!_entityManager.TryGetComponent<StationBankAccountComponent>(_station, out var bank) ||
|
||||||
|
!_entityManager.TryGetComponent<CargoOrderConsoleComponent>(_owner, out var console))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
ActionOptions.Clear();
|
||||||
|
ActionOptions.AddItem(Loc.GetString("cargo-console-menu-account-action-option-withdraw"), i);
|
||||||
|
i++;
|
||||||
|
foreach (var account in bank.Accounts.Keys)
|
||||||
|
{
|
||||||
|
if (account == console.Account)
|
||||||
|
continue;
|
||||||
|
var accountProto = _protoManager.Index(account);
|
||||||
|
ActionOptions.AddItem(Loc.GetString("cargo-console-menu-account-action-option-transfer",
|
||||||
|
("code", Loc.GetString(accountProto.Code))),
|
||||||
|
i);
|
||||||
|
ActionOptions.SetItemMetadata(i, account);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateCargoCapacity(int count, int capacity)
|
public void UpdateStation(EntityUid station)
|
||||||
{
|
{
|
||||||
// TODO: Rename + Loc.
|
_station = station;
|
||||||
ShuttleCapacityLabel.Text = $"{count}/{capacity}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateBankData(string name, int points)
|
protected override void FrameUpdate(FrameEventArgs args)
|
||||||
{
|
{
|
||||||
AccountNameLabel.Text = name;
|
base.FrameUpdate(args);
|
||||||
PointsLabel.Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", points.ToString()));
|
|
||||||
|
if (!_bankQuery.TryComp(_station, out var bankAccount) ||
|
||||||
|
!_orderConsoleQuery.TryComp(_owner, out var orderConsole))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var balance = _cargoSystem.GetBalanceFromAccount((_station.Value, bankAccount), orderConsole.Account);
|
||||||
|
PointsLabel.Text = Loc.GetString("cargo-console-menu-points-amount", ("amount", balance));
|
||||||
|
TransferLimitLabel.Text = Loc.GetString("cargo-console-menu-account-action-transfer-limit",
|
||||||
|
("limit", (int) (balance * orderConsole.TransferLimit)));
|
||||||
|
|
||||||
|
UnlimitedNotifier.Visible = orderConsole.TransferUnbounded;
|
||||||
|
AccountActionButton.Disabled = TransferSpinBox.Value <= 0 ||
|
||||||
|
TransferSpinBox.Value > bankAccount.Accounts[orderConsole.Account] * orderConsole.TransferLimit ||
|
||||||
|
_timing.CurTime < orderConsole.NextAccountActionTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
<PanelContainer xmlns="https://spacestation14.io"
|
<PanelContainer xmlns="https://spacestation14.io"
|
||||||
HorizontalExpand="True">
|
HorizontalExpand="True"
|
||||||
|
Margin="0 1">
|
||||||
<BoxContainer Orientation="Horizontal"
|
<BoxContainer Orientation="Horizontal"
|
||||||
HorizontalExpand="True">
|
HorizontalExpand="True">
|
||||||
<TextureRect Name="Icon"
|
<TextureRect Name="Icon"
|
||||||
Access="Public"
|
Access="Public"
|
||||||
MinSize="32 32"
|
MinSize="32 32"
|
||||||
RectClipContent="True" />
|
RectClipContent="True" />
|
||||||
|
<Control MinWidth="5"/>
|
||||||
<BoxContainer Orientation="Vertical"
|
<BoxContainer Orientation="Vertical"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
VerticalExpand="True">
|
VerticalExpand="True">
|
||||||
@@ -23,10 +25,10 @@
|
|||||||
<Button Name="Approve"
|
<Button Name="Approve"
|
||||||
Access="Public"
|
Access="Public"
|
||||||
Text="{Loc 'cargo-console-menu-cargo-order-row-approve-button'}"
|
Text="{Loc 'cargo-console-menu-cargo-order-row-approve-button'}"
|
||||||
StyleClasses="LabelSubText" />
|
StyleClasses="OpenRight" />
|
||||||
<Button Name="Cancel"
|
<Button Name="Cancel"
|
||||||
Access="Public"
|
Access="Public"
|
||||||
Text="{Loc 'cargo-console-menu-cargo-order-row-cancel-button'}"
|
Text="{Loc 'cargo-console-menu-cargo-order-row-cancel-button'}"
|
||||||
StyleClasses="LabelSubText" />
|
StyleClasses="OpenLeft" />
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</PanelContainer>
|
</PanelContainer>
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
ToolTip=""
|
ToolTip=""
|
||||||
Access="Public"
|
Access="Public"
|
||||||
HorizontalExpand="True"
|
HorizontalExpand="True"
|
||||||
VerticalExpand="True" />
|
VerticalExpand="True"
|
||||||
|
StyleClasses="OpenBoth"/>
|
||||||
<BoxContainer Orientation="Horizontal"
|
<BoxContainer Orientation="Horizontal"
|
||||||
HorizontalExpand="True">
|
HorizontalExpand="True">
|
||||||
<TextureRect Name="Icon"
|
<TextureRect Name="Icon"
|
||||||
@@ -18,7 +19,8 @@
|
|||||||
<Label Name="PointCost"
|
<Label Name="PointCost"
|
||||||
Access="Public"
|
Access="Public"
|
||||||
MinSize="52 32"
|
MinSize="52 32"
|
||||||
Align="Right" />
|
Align="Right"
|
||||||
|
Margin="0 0 5 0"/>
|
||||||
</PanelContainer>
|
</PanelContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</PanelContainer>
|
</PanelContainer>
|
||||||
|
|||||||
29
Content.Client/Cargo/UI/FundingAllocationMenu.xaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<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">
|
||||||
|
<BoxContainer Orientation="Vertical"
|
||||||
|
VerticalExpand="True"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Margin="10 5 10 10">
|
||||||
|
<Label Name="HelpLabel" HorizontalAlignment="Center" StyleClasses="LabelSubText"/>
|
||||||
|
<Control MinHeight="10"/>
|
||||||
|
<PanelContainer VerticalExpand="True" HorizontalExpand="True" VerticalAlignment="Top" MaxHeight="250">
|
||||||
|
<PanelContainer.PanelOverride>
|
||||||
|
<graphics:StyleBoxFlat BackgroundColor="#1B1B1E"/>
|
||||||
|
</PanelContainer.PanelOverride>
|
||||||
|
<controls:TableContainer Name="EntriesContainer" Columns="4" HorizontalExpand="True" VerticalExpand="True" Margin="5 0">
|
||||||
|
<RichTextLabel Text="{Loc 'cargo-funding-alloc-console-label-account'}" HorizontalAlignment="Center"/>
|
||||||
|
<RichTextLabel Text="{Loc 'cargo-funding-alloc-console-label-code'}" HorizontalAlignment="Center"/>
|
||||||
|
<RichTextLabel Text="{Loc 'cargo-funding-alloc-console-label-balance'}" HorizontalAlignment="Center"/>
|
||||||
|
<RichTextLabel Text="{Loc 'cargo-funding-alloc-console-label-cut'}" HorizontalAlignment="Center"/>
|
||||||
|
</controls:TableContainer>
|
||||||
|
</PanelContainer>
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="5 0">
|
||||||
|
<Button Name="SaveButton" Text="{Loc 'cargo-funding-alloc-console-button-save'}" Disabled="True"/>
|
||||||
|
<RichTextLabel Name="SaveAlertLabel" HorizontalExpand="True" HorizontalAlignment="Right" Visible="False"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</controls:FancyWindow>
|
||||||
169
Content.Client/Cargo/UI/FundingAllocationMenu.xaml.cs
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Client.Message;
|
||||||
|
using Content.Client.UserInterface.Controls;
|
||||||
|
using Content.Shared.Cargo.Components;
|
||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Client.Cargo.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class FundingAllocationMenu : FancyWindow
|
||||||
|
{
|
||||||
|
[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;
|
||||||
|
|
||||||
|
private EntityUid? _station;
|
||||||
|
|
||||||
|
private readonly HashSet<Control> _addedControls = new();
|
||||||
|
private readonly List<SpinBox> _spinBoxes = new();
|
||||||
|
private readonly Dictionary<ProtoId<CargoAccountPrototype>, RichTextLabel> _balanceLabels = new();
|
||||||
|
|
||||||
|
public FundingAllocationMenu()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
|
_bankQuery = _entityManager.GetEntityQuery<StationBankAccountComponent>();
|
||||||
|
|
||||||
|
SaveButton.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
if (!_entityManager.TryGetComponent<StationBankAccountComponent>(_station, out var bank))
|
||||||
|
return;
|
||||||
|
var accounts = bank.Accounts.Keys.OrderBy(p => p.Id).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);
|
||||||
|
SaveButton.Disabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
BuildEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
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)));
|
||||||
|
|
||||||
|
foreach (var ctrl in _addedControls)
|
||||||
|
{
|
||||||
|
ctrl.Orphan();
|
||||||
|
}
|
||||||
|
|
||||||
|
_addedControls.Clear();
|
||||||
|
_spinBoxes.Clear();
|
||||||
|
_balanceLabels.Clear();
|
||||||
|
|
||||||
|
var accounts = bank.Accounts.ToList().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<StationBankAccountComponent>(_station, out var bank))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sum = _spinBoxes.Sum(s => s.Value);
|
||||||
|
var incorrectSum = sum != 100;
|
||||||
|
|
||||||
|
var differs = false;
|
||||||
|
var accounts = bank.Accounts.Keys.OrderBy(p => p.Id).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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
namespace Content.Server.Cargo.Components;
|
namespace Content.Server.Cargo.Components;
|
||||||
using Content.Shared.Actions;
|
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Any entities intersecting when a shuttle is recalled will be sold.
|
/// Any entities intersecting when a shuttle is recalled will be sold.
|
||||||
|
|||||||
@@ -6,8 +6,4 @@ namespace Content.Server.Cargo.Components;
|
|||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[Access(typeof(CargoSystem))]
|
[Access(typeof(CargoSystem))]
|
||||||
public sealed partial class CargoPalletConsoleComponent : Component
|
public sealed partial class CargoPalletConsoleComponent : Component;
|
||||||
{
|
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField("cashType", customTypeSerializer:typeof(PrototypeIdSerializer<StackPrototype>))]
|
|
||||||
public string CashType = "Credit";
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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.Server.Station.Components;
|
||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
using Content.Shared.Cargo.Prototypes;
|
using Content.Shared.Cargo.Prototypes;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Server.Cargo.Components;
|
namespace Content.Server.Cargo.Components;
|
||||||
|
|
||||||
@@ -16,15 +16,19 @@ public sealed partial class StationCargoOrderDatabaseComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum amount of orders a station is allowed, approved or not.
|
/// Maximum amount of orders a station is allowed, approved or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField("capacity")]
|
[DataField]
|
||||||
public int Capacity = 20;
|
public int Capacity = 20;
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite), DataField("orders")]
|
[ViewVariables]
|
||||||
public List<CargoOrderData> Orders = new();
|
public IEnumerable<CargoOrderData> AllOrders => Orders.SelectMany(p => p.Value);
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public Dictionary<ProtoId<CargoAccountPrototype>, List<CargoOrderData>> Orders = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to determine unique order IDs
|
/// Used to determine unique order IDs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
public int NumOrdersCreated;
|
public int NumOrdersCreated;
|
||||||
|
|
||||||
// TODO: Can probably dump this
|
// TODO: Can probably dump this
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ public sealed partial class CargoSystem
|
|||||||
[Dependency] private readonly ContainerSystem _container = default!;
|
[Dependency] private readonly ContainerSystem _container = default!;
|
||||||
[Dependency] private readonly NameIdentifierSystem _nameIdentifier = default!;
|
[Dependency] private readonly NameIdentifierSystem _nameIdentifier = default!;
|
||||||
[Dependency] private readonly EntityWhitelistSystem _whitelistSys = default!;
|
[Dependency] private readonly EntityWhitelistSystem _whitelistSys = default!;
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
|
||||||
|
|
||||||
[ValidatePrototypeId<NameIdentifierGroupPrototype>]
|
[ValidatePrototypeId<NameIdentifierGroupPrototype>]
|
||||||
private const string BountyNameIdentifierGroup = "Bounty";
|
private const string BountyNameIdentifierGroup = "Bounty";
|
||||||
@@ -472,7 +471,7 @@ public sealed partial class CargoSystem
|
|||||||
skipped
|
skipped
|
||||||
? CargoBountyHistoryData.BountyResult.Skipped
|
? CargoBountyHistoryData.BountyResult.Skipped
|
||||||
: CargoBountyHistoryData.BountyResult.Completed,
|
: CargoBountyHistoryData.BountyResult.Completed,
|
||||||
_gameTiming.CurTime,
|
_timing.CurTime,
|
||||||
actorName));
|
actorName));
|
||||||
ent.Comp.Bounties.RemoveAt(i);
|
ent.Comp.Bounties.RemoveAt(i);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
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.Interaction;
|
||||||
using Content.Shared.Labels.Components;
|
using Content.Shared.Labels.Components;
|
||||||
using Content.Shared.Paper;
|
using Content.Shared.Paper;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
@@ -23,16 +24,6 @@ namespace Content.Server.Cargo.Systems
|
|||||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||||
[Dependency] private readonly EmagSystem _emag = 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()
|
private void InitializeConsole()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleAddOrderMessage>(OnAddOrderMessage);
|
SubscribeLocalEvent<CargoOrderConsoleComponent, CargoConsoleAddOrderMessage>(OnAddOrderMessage);
|
||||||
@@ -41,9 +32,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
SubscribeLocalEvent<CargoOrderConsoleComponent, BoundUIOpenedEvent>(OnOrderUIOpened);
|
SubscribeLocalEvent<CargoOrderConsoleComponent, BoundUIOpenedEvent>(OnOrderUIOpened);
|
||||||
SubscribeLocalEvent<CargoOrderConsoleComponent, ComponentInit>(OnInit);
|
SubscribeLocalEvent<CargoOrderConsoleComponent, ComponentInit>(OnInit);
|
||||||
SubscribeLocalEvent<CargoOrderConsoleComponent, InteractUsingEvent>(OnInteractUsing);
|
SubscribeLocalEvent<CargoOrderConsoleComponent, InteractUsingEvent>(OnInteractUsing);
|
||||||
SubscribeLocalEvent<CargoOrderConsoleComponent, BankBalanceUpdatedEvent>(OnOrderBalanceUpdated);
|
|
||||||
SubscribeLocalEvent<CargoOrderConsoleComponent, GotEmaggedEvent>(OnEmagged);
|
SubscribeLocalEvent<CargoOrderConsoleComponent, GotEmaggedEvent>(OnEmagged);
|
||||||
Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInteractUsing(EntityUid uid, CargoOrderConsoleComponent component, ref InteractUsingEvent args)
|
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))
|
if (!TryComp(stationUid, out StationBankAccountComponent? bank))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_audio.PlayPvs(component.ConfirmSound, uid);
|
_audio.PlayPvs(ApproveSound, uid);
|
||||||
UpdateBankAccount((stationUid.Value, bank), (int) price);
|
UpdateBankAccount((stationUid.Value, bank), (int) price, CreateAccountDistribution(component.Account, bank));
|
||||||
QueueDel(args.Used);
|
QueueDel(args.Used);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
@@ -73,11 +62,6 @@ namespace Content.Server.Cargo.Systems
|
|||||||
UpdateOrderState(uid, station);
|
UpdateOrderState(uid, station);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Reset()
|
|
||||||
{
|
|
||||||
_timer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEmagged(Entity<CargoOrderConsoleComponent> ent, ref GotEmaggedEvent args)
|
private void OnEmagged(Entity<CargoOrderConsoleComponent> ent, ref GotEmaggedEvent args)
|
||||||
{
|
{
|
||||||
if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
|
if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
|
||||||
@@ -89,31 +73,17 @@ namespace Content.Server.Cargo.Systems
|
|||||||
args.Handled = true;
|
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)
|
|
||||||
{
|
|
||||||
_timer -= Delay;
|
|
||||||
|
|
||||||
var stationQuery = EntityQueryEnumerator<StationBankAccountComponent>();
|
var stationQuery = EntityQueryEnumerator<StationBankAccountComponent>();
|
||||||
while (stationQuery.MoveNext(out var uid, out var bank))
|
while (stationQuery.MoveNext(out var uid, out var bank))
|
||||||
{
|
{
|
||||||
var balanceToAdd = bank.IncreasePerSecond * Delay;
|
if (_timing.CurTime < bank.NextIncomeTime)
|
||||||
UpdateBankAccount((uid, bank), balanceToAdd);
|
continue;
|
||||||
}
|
bank.NextIncomeTime += bank.IncomeDelay;
|
||||||
|
|
||||||
var query = EntityQueryEnumerator<CargoOrderConsoleComponent>();
|
var balanceToAdd = (int) Math.Round(bank.IncreasePerSecond * bank.IncomeDelay.TotalSeconds);
|
||||||
while (query.MoveNext(out var uid, out var _))
|
UpdateBankAccount((uid, bank), balanceToAdd, bank.RevenueDistribution);
|
||||||
{
|
|
||||||
if (!_uiSystem.IsUiOpen(uid, CargoConsoleUiKey.Orders)) continue;
|
|
||||||
|
|
||||||
var station = _station.GetOwningStation(uid);
|
|
||||||
UpdateOrderState(uid, station);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +114,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find our order again. It might have been dispatched or approved already
|
// 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)
|
if (order == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -158,7 +128,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var amount = GetOutstandingOrderCount(orderDatabase);
|
var amount = GetOutstandingOrderCount(orderDatabase, component.Account);
|
||||||
var capacity = orderDatabase.Capacity;
|
var capacity = orderDatabase.Capacity;
|
||||||
|
|
||||||
// Too many orders, avoid them getting spammed in the UI.
|
// 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 cost = order.Price * order.OrderQuantity;
|
||||||
|
var accountBalance = GetBalanceFromAccount((station.Value, bank), component.Account);
|
||||||
|
|
||||||
// Not enough balance
|
// Not enough balance
|
||||||
if (cost > bank.Balance)
|
if (cost > accountBalance)
|
||||||
{
|
{
|
||||||
ConsolePopup(args.Actor, Loc.GetString("cargo-console-insufficient-funds", ("cost", cost)));
|
ConsolePopup(args.Actor, Loc.GetString("cargo-console-insufficient-funds", ("cost", cost)));
|
||||||
PlayDenySound(uid, component);
|
PlayDenySound(uid, component);
|
||||||
@@ -195,7 +166,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
|
|
||||||
if (!ev.Handled)
|
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)
|
if (ev.FulfillmentEntity == null)
|
||||||
{
|
{
|
||||||
@@ -206,7 +177,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
}
|
}
|
||||||
|
|
||||||
order.Approved = true;
|
order.Approved = true;
|
||||||
_audio.PlayPvs(component.ConfirmSound, uid);
|
_audio.PlayPvs(ApproveSound, uid);
|
||||||
|
|
||||||
if (!_emag.CheckFlag(uid, EmagType.Interaction))
|
if (!_emag.CheckFlag(uid, EmagType.Interaction))
|
||||||
{
|
{
|
||||||
@@ -220,20 +191,23 @@ namespace Content.Server.Cargo.Systems
|
|||||||
("approver", order.Approver ?? string.Empty),
|
("approver", order.Approver ?? string.Empty),
|
||||||
("cost", cost));
|
("cost", cost));
|
||||||
_radio.SendRadioMessage(uid, message, component.AnnouncementChannel, uid, escapeMarkup: false);
|
_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)));
|
ConsolePopup(args.Actor, Loc.GetString("cargo-console-trade-station", ("destination", MetaData(ev.FulfillmentEntity.Value).EntityName)));
|
||||||
|
|
||||||
// Log order approval
|
// Log order approval
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
_adminLogger.Add(LogType.Action,
|
||||||
$"{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}");
|
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);
|
orderDatabase.Orders[component.Account].Remove(order);
|
||||||
UpdateBankAccount((station.Value, bank), -cost);
|
UpdateBankAccount((station.Value, bank), -cost, CreateAccountDistribution(component.Account, bank));
|
||||||
UpdateOrders(station.Value);
|
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
|
// No slots at the trade station
|
||||||
_listEnts.Clear();
|
_listEnts.Clear();
|
||||||
@@ -253,7 +227,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
{
|
{
|
||||||
var coordinates = new EntityCoordinates(trade, pad.Transform.LocalPosition);
|
var coordinates = new EntityCoordinates(trade, pad.Transform.LocalPosition);
|
||||||
|
|
||||||
if (FulfillOrder(order, coordinates, orderDatabase.PrinterOutput))
|
if (FulfillOrder(order, account, coordinates, orderDatabase.PrinterOutput))
|
||||||
{
|
{
|
||||||
tradeDestination = trade;
|
tradeDestination = trade;
|
||||||
order.NumDispatched++;
|
order.NumDispatched++;
|
||||||
@@ -288,7 +262,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
if (!TryGetOrderDatabase(station, out var orderDatabase))
|
if (!TryGetOrderDatabase(station, out var orderDatabase))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RemoveOrder(station.Value, args.OrderId, orderDatabase);
|
RemoveOrder(station.Value, component.Account, args.OrderId, orderDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAddOrderMessage(EntityUid uid, CargoOrderConsoleComponent component, CargoConsoleAddOrderMessage args)
|
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));
|
var data = GetOrderData(args, product, GenerateOrderId(orderDatabase));
|
||||||
|
|
||||||
if (!TryAddOrder(stationUid.Value, data, orderDatabase))
|
if (!TryAddOrder(stationUid.Value, component.Account, data, orderDatabase))
|
||||||
{
|
{
|
||||||
PlayDenySound(uid, component);
|
PlayDenySound(uid, component);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log order addition
|
// 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}]");
|
$"{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
|
#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)
|
private void UpdateOrderState(EntityUid consoleUid, EntityUid? station)
|
||||||
{
|
{
|
||||||
if (station == null ||
|
if (!TryComp<CargoOrderConsoleComponent>(consoleUid, out var console))
|
||||||
!TryComp<StationCargoOrderDatabaseComponent>(station, out var orderDatabase) ||
|
return;
|
||||||
!TryComp<StationBankAccountComponent>(station, out var bankAccount)) return;
|
|
||||||
|
if (!TryComp<StationCargoOrderDatabaseComponent>(station, out var orderDatabase))
|
||||||
|
return;
|
||||||
|
|
||||||
if (_uiSystem.HasUi(consoleUid, CargoConsoleUiKey.Orders))
|
if (_uiSystem.HasUi(consoleUid, CargoConsoleUiKey.Orders))
|
||||||
{
|
{
|
||||||
_uiSystem.SetUiState(consoleUid, CargoConsoleUiKey.Orders, new CargoConsoleInterfaceState(
|
_uiSystem.SetUiState(consoleUid,
|
||||||
|
CargoConsoleUiKey.Orders,
|
||||||
|
new CargoConsoleInterfaceState(
|
||||||
MetaData(station.Value).EntityName,
|
MetaData(station.Value).EntityName,
|
||||||
GetOutstandingOrderCount(orderDatabase),
|
GetOutstandingOrderCount(orderDatabase, console.Account),
|
||||||
orderDatabase.Capacity,
|
orderDatabase.Capacity,
|
||||||
bankAccount.Balance,
|
GetNetEntity(station.Value),
|
||||||
orderDatabase.Orders
|
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);
|
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;
|
var amount = 0;
|
||||||
|
|
||||||
foreach (var order in component.Orders)
|
foreach (var order in component.Orders[account])
|
||||||
{
|
{
|
||||||
if (!order.Approved)
|
if (!order.Approved)
|
||||||
continue;
|
continue;
|
||||||
@@ -430,6 +400,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
string description,
|
string description,
|
||||||
string dest,
|
string dest,
|
||||||
StationCargoOrderDatabaseComponent component,
|
StationCargoOrderDatabaseComponent component,
|
||||||
|
ProtoId<CargoAccountPrototype> account,
|
||||||
Entity<StationDataComponent> stationData
|
Entity<StationDataComponent> stationData
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -443,16 +414,17 @@ namespace Content.Server.Cargo.Systems
|
|||||||
order.Approved = true;
|
order.Approved = true;
|
||||||
|
|
||||||
// Log order addition
|
// 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}]");
|
$"AddAndApproveOrder {description} added order [orderId:{order.OrderId}, quantity:{order.OrderQuantity}, product:{order.ProductId}, requester:{order.Requester}, reason:{order.Reason}]");
|
||||||
|
|
||||||
// Add it to the list
|
// 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);
|
UpdateOrders(dbUid);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -464,12 +436,12 @@ namespace Content.Server.Cargo.Systems
|
|||||||
return ++orderDB.NumOrdersCreated;
|
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)
|
if (sequenceIdx != -1)
|
||||||
{
|
{
|
||||||
orderDB.Orders.RemoveAt(sequenceIdx);
|
orderDB.Orders[account].RemoveAt(sequenceIdx);
|
||||||
}
|
}
|
||||||
UpdateOrders(dbUid);
|
UpdateOrders(dbUid);
|
||||||
}
|
}
|
||||||
@@ -482,22 +454,22 @@ namespace Content.Server.Cargo.Systems
|
|||||||
component.Orders.Clear();
|
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)
|
if (orderIdx == -1)
|
||||||
{
|
{
|
||||||
orderOut = null;
|
orderOut = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
orderOut = orderDB.Orders[orderIdx];
|
orderOut = orderDB.Orders[account][orderIdx];
|
||||||
orderOut.NumDispatched++;
|
orderOut.NumDispatched++;
|
||||||
|
|
||||||
if (orderOut.NumDispatched >= orderOut.OrderQuantity)
|
if (orderOut.NumDispatched >= orderOut.OrderQuantity)
|
||||||
{
|
{
|
||||||
// Order is complete. Remove from the queue.
|
// Order is complete. Remove from the queue.
|
||||||
orderDB.Orders.RemoveAt(orderIdx);
|
orderDB.Orders[account].RemoveAt(orderIdx);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -505,18 +477,19 @@ namespace Content.Server.Cargo.Systems
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to fulfill the next outstanding order.
|
/// Tries to fulfill the next outstanding order.
|
||||||
/// </summary>
|
/// </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 false;
|
||||||
|
|
||||||
return FulfillOrder(order, spawn, paperProto);
|
return FulfillOrder(order, account, spawn, paperProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fulfills the specified cargo order and spawns paper attached to it.
|
/// Fulfills the specified cargo order and spawns paper attached to it.
|
||||||
/// </summary>
|
/// </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
|
// Create the item itself
|
||||||
var item = Spawn(order.ProductId, spawn);
|
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));
|
var val = Loc.GetString("cargo-console-paper-print-name", ("orderNumber", order.OrderId));
|
||||||
_metaSystem.SetEntityName(printed, val);
|
_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",
|
"cargo-console-paper-print-text",
|
||||||
("orderNumber", order.OrderId),
|
("orderNumber", order.OrderId),
|
||||||
("itemName", MetaData(item).EntityName),
|
("itemName", MetaData(item).EntityName),
|
||||||
("orderQuantity", order.OrderQuantity),
|
("orderQuantity", order.OrderQuantity),
|
||||||
("requester", order.Requester),
|
("requester", order.Requester),
|
||||||
("reason", order.Reason),
|
("reason", string.IsNullOrWhiteSpace(order.Reason) ? Loc.GetString("cargo-console-paper-reason-default") : order.Reason),
|
||||||
("approver", order.Approver ?? string.Empty)));
|
("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
|
// attempt to attach the label to the item
|
||||||
if (TryComp<PaperLabelComponent>(item, out var label))
|
if (TryComp<PaperLabelComponent>(item, out var label))
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
|
using System.Linq;
|
||||||
using Content.Server.Cargo.Components;
|
using Content.Server.Cargo.Components;
|
||||||
using Content.Shared.Stacks;
|
|
||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
using Content.Shared.Cargo.BUI;
|
using Content.Shared.Cargo.BUI;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
using Content.Shared.Cargo.Events;
|
using Content.Shared.Cargo.Events;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.Cargo.Prototypes;
|
||||||
using Robust.Shared.Map;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Random;
|
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Server.Cargo.Systems;
|
namespace Content.Server.Cargo.Systems;
|
||||||
|
|
||||||
@@ -28,12 +28,11 @@ public sealed partial class CargoSystem
|
|||||||
SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletSellMessage>(OnPalletSale);
|
SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletSellMessage>(OnPalletSale);
|
||||||
SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletAppraiseMessage>(OnPalletAppraise);
|
SubscribeLocalEvent<CargoPalletConsoleComponent, CargoPalletAppraiseMessage>(OnPalletAppraise);
|
||||||
SubscribeLocalEvent<CargoPalletConsoleComponent, BoundUIOpenedEvent>(OnPalletUIOpen);
|
SubscribeLocalEvent<CargoPalletConsoleComponent, BoundUIOpenedEvent>(OnPalletUIOpen);
|
||||||
|
|
||||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Console
|
#region Console
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
private void UpdateCargoShuttleConsoles(EntityUid shuttleUid, CargoShuttleComponent _)
|
private void UpdateCargoShuttleConsoles(EntityUid shuttleUid, CargoShuttleComponent _)
|
||||||
{
|
{
|
||||||
// Update pilot consoles that are already open.
|
// Update pilot consoles that are already open.
|
||||||
@@ -54,15 +53,18 @@ public sealed partial class CargoSystem
|
|||||||
|
|
||||||
private void UpdatePalletConsoleInterface(EntityUid uid)
|
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,
|
_uiSystem.SetUiState(uid,
|
||||||
|
CargoPalletConsoleUiKey.Sale,
|
||||||
new CargoPalletConsoleInterfaceState(0, 0, false));
|
new CargoPalletConsoleInterfaceState(0, 0, false));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GetPalletGoods(gridUid, out var toSell, out var amount);
|
GetPalletGoods(gridUid, out var toSell, out var goods);
|
||||||
_uiSystem.SetUiState(uid, CargoPalletConsoleUiKey.Sale,
|
var totalAmount = goods.Sum(t => t.Item3);
|
||||||
new CargoPalletConsoleInterfaceState((int) amount, toSell.Count, true));
|
_uiSystem.SetUiState(uid,
|
||||||
|
CargoPalletConsoleUiKey.Sale,
|
||||||
|
new CargoPalletConsoleInterfaceState((int) totalAmount, toSell.Count, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPalletUIOpen(EntityUid uid, CargoPalletConsoleComponent component, BoundUIOpenedEvent args)
|
private void OnPalletUIOpen(EntityUid uid, CargoPalletConsoleComponent component, BoundUIOpenedEvent args)
|
||||||
@@ -98,12 +100,16 @@ public sealed partial class CargoSystem
|
|||||||
var shuttleName = orderDatabase?.Shuttle != null ? MetaData(orderDatabase.Shuttle.Value).EntityName : string.Empty;
|
var shuttleName = orderDatabase?.Shuttle != null ? MetaData(orderDatabase.Shuttle.Value).EntityName : string.Empty;
|
||||||
|
|
||||||
if (_uiSystem.HasUi(uid, CargoConsoleUiKey.Shuttle))
|
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"),
|
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,
|
string.IsNullOrEmpty(shuttleName) ? Loc.GetString("cargo-shuttle-console-shuttle-not-found") : shuttleName,
|
||||||
orders
|
orders
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -132,9 +138,10 @@ public sealed partial class CargoSystem
|
|||||||
return orders;
|
return orders;
|
||||||
|
|
||||||
var spaceRemaining = GetCargoSpace(shuttleUid);
|
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)
|
if (order.Approved)
|
||||||
{
|
{
|
||||||
var numToShip = order.OrderQuantity - order.NumDispatched;
|
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
|
// We won't be able to fit the whole order on, so make one
|
||||||
// which represents the space we do have left:
|
// which represents the space we do have left:
|
||||||
var reducedOrder = new CargoOrderData(order.OrderId,
|
var reducedOrder = new CargoOrderData(
|
||||||
order.ProductId, order.ProductName, order.Price, spaceRemaining, order.Requester, order.Reason);
|
order.OrderId,
|
||||||
|
order.ProductId,
|
||||||
|
order.ProductName,
|
||||||
|
order.Price,
|
||||||
|
spaceRemaining,
|
||||||
|
order.Requester,
|
||||||
|
order.Reason);
|
||||||
orders.Add(reducedOrder);
|
orders.Add(reducedOrder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -219,16 +232,13 @@ public sealed partial class CargoSystem
|
|||||||
|
|
||||||
#region Station
|
#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);
|
GetPalletGoods(gridUid, out var toSell, out goods);
|
||||||
|
|
||||||
Log.Debug($"Cargo sold {toSell.Count} entities for {amount}");
|
|
||||||
|
|
||||||
if (toSell.Count == 0)
|
if (toSell.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
var ev = new EntitySoldEvent(toSell);
|
var ev = new EntitySoldEvent(toSell);
|
||||||
RaiseLocalEvent(ref ev);
|
RaiseLocalEvent(ref ev);
|
||||||
|
|
||||||
@@ -240,9 +250,9 @@ public sealed partial class CargoSystem
|
|||||||
return true;
|
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>();
|
toSell = new HashSet<EntityUid>();
|
||||||
|
|
||||||
foreach (var (palletUid, _, _) in GetCargoPallets(gridUid, BuySellType.Sell))
|
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.
|
// Containers should already get the sell price of their children so can skip those.
|
||||||
_setEnts.Clear();
|
_setEnts.Clear();
|
||||||
|
|
||||||
_lookup.GetEntitiesIntersecting(palletUid, _setEnts,
|
_lookup.GetEntitiesIntersecting(
|
||||||
|
palletUid,
|
||||||
|
_setEnts,
|
||||||
LookupFlags.Dynamic | LookupFlags.Sundries);
|
LookupFlags.Dynamic | LookupFlags.Sundries);
|
||||||
|
|
||||||
foreach (var ent in _setEnts)
|
foreach (var ent in _setEnts)
|
||||||
@@ -273,7 +285,7 @@ public sealed partial class CargoSystem
|
|||||||
if (price == 0)
|
if (price == 0)
|
||||||
continue;
|
continue;
|
||||||
toSell.Add(ent);
|
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);
|
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,
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xform.GridUid is not { } gridUid)
|
||||||
|
{
|
||||||
|
_uiSystem.SetUiState(uid,
|
||||||
|
CargoPalletConsoleUiKey.Sale,
|
||||||
new CargoPalletConsoleInterfaceState(0, 0, false));
|
new CargoPalletConsoleInterfaceState(0, 0, false));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SellPallets(gridUid, out var price))
|
if (!SellPallets(gridUid, out var goods))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var stackPrototype = _protoMan.Index<StackPrototype>(component.CashType);
|
var baseDistribution = CreateAccountDistribution(bankAccount.PrimaryAccount, bankAccount, bankAccount.PrimaryCut);
|
||||||
_stack.Spawn((int) price, stackPrototype, xform.Coordinates);
|
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);
|
_audio.PlayPvs(ApproveSound, uid);
|
||||||
UpdatePalletConsoleInterface(uid);
|
UpdatePalletConsoleInterface(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Cargo.Components;
|
using Content.Server.Cargo.Components;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
@@ -40,9 +41,8 @@ public sealed partial class CargoSystem
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// todo cannot be fucking asked to figure out device linking rn but this shouldn't just default to the first port.
|
// 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) ||
|
if (!TryGetLinkedConsole((uid, tele), out var console) ||
|
||||||
sinkComponent.LinkedSources.FirstOrNull() is not { } console ||
|
console.Value.Owner != args.OrderConsole.Owner)
|
||||||
console != args.OrderConsole.Owner)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (var i = 0; i < args.Order.OrderQuantity; i++)
|
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)
|
private void UpdateTelepad(float frameTime)
|
||||||
{
|
{
|
||||||
var query = EntityQueryEnumerator<CargoTelepadComponent>();
|
var query = EntityQueryEnumerator<CargoTelepadComponent, TransformComponent>();
|
||||||
while (query.MoveNext(out var uid, out var comp))
|
while (query.MoveNext(out var uid, out var comp, out var xform))
|
||||||
{
|
{
|
||||||
// Don't EntityQuery for it as it's not required.
|
// Don't EntityQuery for it as it's not required.
|
||||||
TryComp<AppearanceComponent>(uid, out var appearance);
|
TryComp<AppearanceComponent>(uid, out var appearance);
|
||||||
@@ -82,15 +98,14 @@ public sealed partial class CargoSystem
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comp.CurrentOrders.Count == 0)
|
if (comp.CurrentOrders.Count == 0 || !TryGetLinkedConsole((uid, comp), out var console))
|
||||||
{
|
{
|
||||||
comp.Accumulator += comp.Delay;
|
comp.Accumulator += comp.Delay;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xform = Transform(uid);
|
|
||||||
var currentOrder = comp.CurrentOrders.First();
|
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));
|
_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))
|
!TryComp<StationDataComponent>(station, out var data))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!TryGetLinkedConsole(ent, out var console))
|
||||||
|
return;
|
||||||
|
|
||||||
foreach (var order in ent.Comp.CurrentOrders)
|
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.Server.Radio.EntitySystems;
|
||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
using Content.Shared.Containers.ItemSlots;
|
using Content.Shared.Containers.ItemSlots;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Paper;
|
using Content.Shared.Paper;
|
||||||
@@ -65,36 +66,46 @@ public sealed partial class CargoSystem : SharedCargoSystem
|
|||||||
InitializeShuttle();
|
InitializeShuttle();
|
||||||
InitializeTelepad();
|
InitializeTelepad();
|
||||||
InitializeBounty();
|
InitializeBounty();
|
||||||
|
InitializeFunds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
UpdateConsole(frameTime);
|
UpdateConsole();
|
||||||
UpdateTelepad(frameTime);
|
UpdateTelepad(frameTime);
|
||||||
UpdateBounty();
|
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]
|
[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))
|
if (!Resolve(ent, ref ent.Comp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ent.Comp.Balance += balanceAdded;
|
foreach (var (account, percent) in accountDistribution)
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
var station = _station.GetOwningStation(client, xform);
|
var accountBalancedAdded = (int) Math.Round(percent * balanceAdded);
|
||||||
if (station != ent)
|
ent.Comp.Accounts[account] += accountBalancedAdded;
|
||||||
continue;
|
|
||||||
|
|
||||||
comp.Balance = ent.Comp.Balance;
|
|
||||||
Dirty(client, comp);
|
|
||||||
RaiseLocalEvent(client, ref ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.Cargo.Systems;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Server.StationRecords.Systems;
|
using Content.Server.StationRecords.Systems;
|
||||||
|
using Content.Shared.Cargo.Components;
|
||||||
using Content.Shared.Delivery;
|
using Content.Shared.Delivery;
|
||||||
using Content.Shared.FingerprintReader;
|
using Content.Shared.FingerprintReader;
|
||||||
using Content.Shared.Labels.EntitySystems;
|
using Content.Shared.Labels.EntitySystems;
|
||||||
@@ -73,7 +73,10 @@ public sealed partial class DeliverySystem : SharedDeliverySystem
|
|||||||
if (!TryComp<StationBankAccountComponent>(ent.Comp.RecipientStation, out var account))
|
if (!TryComp<StationBankAccountComponent>(ent.Comp.RecipientStation, out var account))
|
||||||
return;
|
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)
|
public override void Update(float frameTime)
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace Content.Server.Stack
|
|||||||
public EntityUid Spawn(int amount, StackPrototype prototype, EntityCoordinates spawnPosition)
|
public EntityUid Spawn(int amount, StackPrototype prototype, EntityCoordinates spawnPosition)
|
||||||
{
|
{
|
||||||
// Set the output result parameter to the new stack entity...
|
// 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);
|
var stack = Comp<StackComponent>(entity);
|
||||||
|
|
||||||
// And finally, set the correct amount!
|
// And finally, set the correct amount!
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Content.Shared.Station;
|
|||||||
using Content.Shared.Station.Components;
|
using Content.Shared.Station.Components;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Server.GameStates;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Collections;
|
using Robust.Shared.Collections;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
@@ -34,6 +35,7 @@ public sealed class StationSystem : EntitySystem
|
|||||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
[Dependency] private readonly MapSystem _map = default!;
|
[Dependency] private readonly MapSystem _map = default!;
|
||||||
|
[Dependency] private readonly PvsOverrideSystem _pvsOverride = default!;
|
||||||
|
|
||||||
private ISawmill _sawmill = default!;
|
private ISawmill _sawmill = default!;
|
||||||
|
|
||||||
@@ -97,7 +99,7 @@ public sealed class StationSystem : EntitySystem
|
|||||||
var metaData = MetaData(uid);
|
var metaData = MetaData(uid);
|
||||||
RaiseLocalEvent(new StationInitializedEvent(uid));
|
RaiseLocalEvent(new StationInitializedEvent(uid));
|
||||||
_sawmill.Info($"Set up station {metaData.EntityName} ({uid}).");
|
_sawmill.Info($"Set up station {metaData.EntityName} ({uid}).");
|
||||||
|
_pvsOverride.AddGlobalOverride(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStationDeleted(EntityUid uid, StationDataComponent component, ComponentShutdown args)
|
private void OnStationDeleted(EntityUid uid, StationDataComponent component, ComponentShutdown args)
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ public sealed partial class CargoGiftsRuleComponent : Component
|
|||||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
public LocId Dest = "cargo-gift-default-dest";
|
public LocId Dest = "cargo-gift-default-dest";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Account the gifts are deposited into
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<CargoAccountPrototype> Account = "Cargo";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cargo that you would like gifted to the station, with the quantity for each
|
/// Cargo that you would like gifted to the station, with the quantity for each
|
||||||
/// Use Ids from cargoProduct Prototypes
|
/// Use Ids from cargoProduct Prototypes
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public sealed class CargoGiftsRule : StationEventSystem<CargoGiftsRuleComponent>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add some presents
|
// 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)
|
while (outstanding < cargoDb.Capacity - component.OrderSpaceToLeave && component.Gifts.Count > 0)
|
||||||
{
|
{
|
||||||
// I wish there was a nice way to pop this
|
// 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.Description),
|
||||||
Loc.GetString(component.Dest),
|
Loc.GetString(component.Dest),
|
||||||
cargoDb,
|
cargoDb,
|
||||||
|
component.Account,
|
||||||
(station.Value, stationData)
|
(station.Value, stationData)
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ public sealed class CargoConsoleInterfaceState : BoundUserInterfaceState
|
|||||||
public string Name;
|
public string Name;
|
||||||
public int Count;
|
public int Count;
|
||||||
public int Capacity;
|
public int Capacity;
|
||||||
public int Balance;
|
public NetEntity Station;
|
||||||
public List<CargoOrderData> Orders;
|
public List<CargoOrderData> Orders;
|
||||||
|
|
||||||
public CargoConsoleInterfaceState(string name, int count, int capacity, int balance, List<CargoOrderData> orders)
|
public CargoConsoleInterfaceState(string name, int count, int capacity, NetEntity station, List<CargoOrderData> orders)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Count = count;
|
Count = count;
|
||||||
Capacity = capacity;
|
Capacity = capacity;
|
||||||
Balance = balance;
|
Station = station;
|
||||||
Orders = orders;
|
Orders = orders;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using Robust.Shared.GameStates;
|
|
||||||
|
|
||||||
namespace Content.Shared.Cargo.Components;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Makes an entity a client of the station's bank account.
|
|
||||||
/// When its balance changes it will have <see cref="BankBalanceUpdatedEvent"/> raised on it.
|
|
||||||
/// Other systems can then use this for logic or to update ui states.
|
|
||||||
/// </summary>
|
|
||||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedCargoSystem))]
|
|
||||||
[AutoGenerateComponentState]
|
|
||||||
public sealed partial class BankClientComponent : Component
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The balance updated for the last station this entity was a part of.
|
|
||||||
/// </summary>
|
|
||||||
[DataField, AutoNetworkedField]
|
|
||||||
public int Balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raised on an entity with <see cref="BankClientComponent"/> when the bank's balance is updated.
|
|
||||||
/// </summary>
|
|
||||||
[ByRefEvent]
|
|
||||||
public readonly record struct BankBalanceUpdatedEvent(EntityUid Station, int Balance);
|
|
||||||
@@ -1,33 +1,121 @@
|
|||||||
|
using Content.Shared.Access;
|
||||||
using Content.Shared.Cargo.Prototypes;
|
using Content.Shared.Cargo.Prototypes;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Content.Shared.Radio;
|
using Content.Shared.Radio;
|
||||||
|
using Content.Shared.Stacks;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
namespace Content.Shared.Cargo.Components;
|
namespace Content.Shared.Cargo.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles sending order requests to cargo. Doesn't handle orders themselves via shuttle or telepads.
|
/// Handles sending order requests to cargo. Doesn't handle orders themselves via shuttle or telepads.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||||
|
[Access(typeof(SharedCargoSystem))]
|
||||||
public sealed partial class CargoOrderConsoleComponent : Component
|
public sealed partial class CargoOrderConsoleComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("soundError")] public SoundSpecifier ErrorSound =
|
/// <summary>
|
||||||
new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_sigh.ogg");
|
/// The account that this console pulls from for ordering.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<CargoAccountPrototype> Account = "Cargo";
|
||||||
|
|
||||||
[DataField("soundConfirm")]
|
[DataField]
|
||||||
public SoundSpecifier ConfirmSound = new SoundPathSpecifier("/Audio/Effects/Cargo/ping.ogg");
|
public SoundSpecifier ErrorSound = new SoundCollectionSpecifier("CargoError");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sound made when <see cref="TransferUnbounded"/> is toggled.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SoundSpecifier ToggleLimitSound = new SoundCollectionSpecifier("CargoToggleLimit");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, account transfers have no limit and a lower cooldown.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool TransferUnbounded;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public float TransferLimit => TransferUnbounded ? 1 : BaseTransferLimit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum percent of total funds that can be transferred or withdrawn in one action.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float BaseTransferLimit = 0.20f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time at which account actions can be performed again.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField]
|
||||||
|
public TimeSpan NextAccountActionTime;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public TimeSpan AccountActionDelay => TransferUnbounded ? UnboundedAccountActionDelay : BaseAccountActionDelay;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum time between account actions when <see cref="TransferUnbounded"/> is false
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan BaseAccountActionDelay = TimeSpan.FromMinutes(1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum time between account actions when <see cref="TransferUnbounded"/> is true
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan UnboundedAccountActionDelay = TimeSpan.FromSeconds(10);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The stack representing cash dispensed on withdrawals.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<StackPrototype> CashType = "Credit";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All of the <see cref="CargoProductPrototype.Group"/>s that are supported.
|
/// All of the <see cref="CargoProductPrototype.Group"/>s that are supported.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
[DataField, AutoNetworkedField]
|
||||||
public List<string> AllowedGroups = new() { "market" };
|
public List<string> AllowedGroups = new() { "market" };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Access needed to toggle the limit on this console.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public HashSet<ProtoId<AccessLevelPrototype>> RemoveLimitAccess = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Radio channel on which order approval announcements are transmitted
|
/// Radio channel on which order approval announcements are transmitted
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
public ProtoId<RadioChannelPrototype> AnnouncementChannel = "Supply";
|
public ProtoId<RadioChannelPrototype> AnnouncementChannel = "Supply";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Secondary radio channel which always receives order announcements.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly ProtoId<RadioChannelPrototype> BaseAnnouncementChannel = "Supply";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Withdraw funds from an account
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class CargoConsoleWithdrawFundsMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public ProtoId<CargoAccountPrototype>? Account;
|
||||||
|
public int Amount;
|
||||||
|
|
||||||
|
public CargoConsoleWithdrawFundsMessage(ProtoId<CargoAccountPrototype>? account, int amount)
|
||||||
|
{
|
||||||
|
Account = account;
|
||||||
|
Amount = amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggle the limit on withdrawals and transfers.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class CargoConsoleToggleLimitMessage : BoundUserInterfaceMessage;
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Cargo.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A console that manipulates the distribution of revenue on the station.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
[Access(typeof(SharedCargoSystem))]
|
||||||
|
public sealed partial class FundingAllocationConsoleComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sound played when the budget distribution is set.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SoundSpecifier SetDistributionSound = new SoundCollectionSpecifier("CargoPing");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class SetFundingAllocationBuiMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public Dictionary<ProtoId<CargoAccountPrototype>, int> Percents;
|
||||||
|
|
||||||
|
public SetFundingAllocationBuiMessage(Dictionary<ProtoId<CargoAccountPrototype>, int> percents)
|
||||||
|
{
|
||||||
|
Percents = percents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class FundingAllocationConsoleBuiState : BoundUserInterfaceState
|
||||||
|
{
|
||||||
|
public NetEntity Station;
|
||||||
|
|
||||||
|
public FundingAllocationConsoleBuiState(NetEntity station)
|
||||||
|
{
|
||||||
|
Station = station;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum FundingAllocationConsoleUiKey : byte
|
||||||
|
{
|
||||||
|
Key
|
||||||
|
}
|
||||||
17
Content.Shared/Cargo/Components/OverrideSellComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Cargo.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes a sellable object portion out its value to a specified department rather than the station default
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class OverrideSellComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The account that will receive the primary funds from this being sold.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ProtoId<CargoAccountPrototype> OverrideAccount;
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
|
namespace Content.Shared.Cargo.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Added to the abstract representation of a station to track its money.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, Access(typeof(SharedCargoSystem)), AutoGenerateComponentPause, AutoGenerateComponentState]
|
||||||
|
public sealed partial class StationBankAccountComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The account that receives funds by default
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public ProtoId<CargoAccountPrototype> PrimaryAccount = "Cargo";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When giving funds to a particular account, the proportion of funds they should receive compared to remaining accounts.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public double PrimaryCut = 0.75;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary corresponding to the money held by each cargo account.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public Dictionary<ProtoId<CargoAccountPrototype>, int> Accounts = new()
|
||||||
|
{
|
||||||
|
{ "Cargo", 2000 },
|
||||||
|
{ "Engineering", 1000 },
|
||||||
|
{ "Medical", 1000 },
|
||||||
|
{ "Science", 1000 },
|
||||||
|
{ "Security", 1000 },
|
||||||
|
{ "Service", 1000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A baseline distribution used for income and dispersing leftovers after sale.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public Dictionary<ProtoId<CargoAccountPrototype>, double> RevenueDistribution = new()
|
||||||
|
{
|
||||||
|
{ "Cargo", 0.00 },
|
||||||
|
{ "Engineering", 0.25 },
|
||||||
|
{ "Medical", 0.30 },
|
||||||
|
{ "Science", 0.15 },
|
||||||
|
{ "Security", 0.20 },
|
||||||
|
{ "Service", 0.10 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much the bank balance goes up per second, every Delay period. Rounded down when multiplied.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public int IncreasePerSecond = 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time at which the station will receive its next deposit of passive income
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
|
||||||
|
public TimeSpan NextIncomeTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much time to wait (in seconds) before increasing bank accounts balance.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan IncomeDelay = TimeSpan.FromSeconds(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Broadcast and raised on station ent whenever its balance is updated.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct BankBalanceUpdatedEvent(EntityUid Station, Dictionary<ProtoId<CargoAccountPrototype>, int> Balance);
|
||||||
39
Content.Shared/Cargo/Prototypes/CargoAccountPrototype.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using Content.Shared.Radio;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Cargo.Prototypes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a prototype for a single account that stores money on StationBankAccountComponent
|
||||||
|
/// </summary>
|
||||||
|
[Prototype]
|
||||||
|
public sealed partial class CargoAccountPrototype : IPrototype
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[IdDataField]
|
||||||
|
public string ID { get; } = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Full IC name of the account.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A shortened code used to refer to the account in UIs
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId Code;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Color corresponding to the account.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public Color Color;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Channel used for announcing transactions.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<RadioChannelPrototype> RadioChannel;
|
||||||
|
}
|
||||||
@@ -1,7 +1,54 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Shared.Cargo.Components;
|
||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Cargo;
|
namespace Content.Shared.Cargo;
|
||||||
|
|
||||||
|
public abstract class SharedCargoSystem : EntitySystem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// For a given station, retrieves the balance in a specific account.
|
||||||
|
/// </summary>
|
||||||
|
public int GetBalanceFromAccount(Entity<StationBankAccountComponent?> station, ProtoId<CargoAccountPrototype> account)
|
||||||
|
{
|
||||||
|
if (!Resolve(station, ref station.Comp))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return station.Comp.Accounts.GetValueOrDefault(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For a station, creates a distribution between one "primary" account and the other accounts.
|
||||||
|
/// The primary account receives the majority cut specified, with the remaining accounts getting cuts
|
||||||
|
/// distributed through the remaining amount, based on <see cref="StationBankAccountComponent.RevenueDistribution"/>
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<ProtoId<CargoAccountPrototype>, double> CreateAccountDistribution(
|
||||||
|
ProtoId<CargoAccountPrototype> primary,
|
||||||
|
StationBankAccountComponent stationBank,
|
||||||
|
double primaryCut = 1.0)
|
||||||
|
{
|
||||||
|
var distribution = new Dictionary<ProtoId<CargoAccountPrototype>, double>
|
||||||
|
{
|
||||||
|
{ primary, primaryCut }
|
||||||
|
};
|
||||||
|
var remaining = 1.0 - primaryCut;
|
||||||
|
|
||||||
|
var allAccountPercentages = new Dictionary<ProtoId<CargoAccountPrototype>, double>(stationBank.RevenueDistribution);
|
||||||
|
allAccountPercentages.Remove(primary);
|
||||||
|
var weightsSum = allAccountPercentages.Values.Sum();
|
||||||
|
|
||||||
|
foreach (var (account, percentage) in allAccountPercentages)
|
||||||
|
{
|
||||||
|
var adjustedPercentage = percentage / weightsSum;
|
||||||
|
|
||||||
|
distribution.Add(account, remaining * adjustedPercentage);
|
||||||
|
}
|
||||||
|
return distribution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[NetSerializable, Serializable]
|
[NetSerializable, Serializable]
|
||||||
public enum CargoConsoleUiKey : byte
|
public enum CargoConsoleUiKey : byte
|
||||||
{
|
{
|
||||||
@@ -17,8 +64,6 @@ public enum CargoPalletConsoleUiKey : byte
|
|||||||
Sale
|
Sale
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class SharedCargoSystem : EntitySystem {}
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum CargoTelepadState : byte
|
public enum CargoTelepadState : byte
|
||||||
{
|
{
|
||||||
|
|||||||
17
Resources/Locale/en-US/cargo/cargo-accounts.ftl
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
cargo-account-cargo-name = Station Supply Budget
|
||||||
|
cargo-account-cargo-code = SUP
|
||||||
|
|
||||||
|
cargo-account-engineering-name = Maintenance Savings
|
||||||
|
cargo-account-engineering-code = ENG
|
||||||
|
|
||||||
|
cargo-account-medical-name = Crew Healthcare Fund
|
||||||
|
cargo-account-medical-code = MED
|
||||||
|
|
||||||
|
cargo-account-science-name = Interstellar Development Funding
|
||||||
|
cargo-account-science-code = RND
|
||||||
|
|
||||||
|
cargo-account-security-name = Station Defense Reserves
|
||||||
|
cargo-account-security-code = SEC
|
||||||
|
|
||||||
|
cargo-account-service-name = Collective Service Holdings
|
||||||
|
cargo-account-service-code = SRV
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
## UI
|
## UI
|
||||||
cargo-console-menu-title = Cargo request console
|
cargo-console-menu-title = Cargo request console
|
||||||
cargo-console-menu-account-name-label = Account name:{" "}
|
cargo-console-menu-account-name-label = Account:{" "}
|
||||||
cargo-console-menu-account-name-none-text = None
|
cargo-console-menu-account-name-none-text = None
|
||||||
|
cargo-console-menu-account-name-format = [bold][color={$color}]{$name}[/color][/bold] [font="Monospace"]\[{$code}\][/font]
|
||||||
cargo-console-menu-shuttle-name-label = Shuttle name:{" "}
|
cargo-console-menu-shuttle-name-label = Shuttle name:{" "}
|
||||||
cargo-console-menu-shuttle-name-none-text = None
|
cargo-console-menu-shuttle-name-none-text = None
|
||||||
cargo-console-menu-points-label = Spesos:{" "}
|
cargo-console-menu-points-label = Balance:{" "}
|
||||||
cargo-console-menu-points-amount = ${$amount}
|
cargo-console-menu-points-amount = ${$amount}
|
||||||
cargo-console-menu-shuttle-status-label = Shuttle status:{" "}
|
cargo-console-menu-shuttle-status-label = Shuttle status:{" "}
|
||||||
cargo-console-menu-shuttle-status-away-text = Away
|
cargo-console-menu-shuttle-status-away-text = Away
|
||||||
@@ -20,6 +21,16 @@ cargo-console-menu-populate-categories-all-text = All
|
|||||||
cargo-console-menu-populate-orders-cargo-order-row-product-name-text = {$productName} (x{$orderAmount}) by {$orderRequester}
|
cargo-console-menu-populate-orders-cargo-order-row-product-name-text = {$productName} (x{$orderAmount}) by {$orderRequester}
|
||||||
cargo-console-menu-cargo-order-row-approve-button = Approve
|
cargo-console-menu-cargo-order-row-approve-button = Approve
|
||||||
cargo-console-menu-cargo-order-row-cancel-button = Cancel
|
cargo-console-menu-cargo-order-row-cancel-button = Cancel
|
||||||
|
cargo-console-menu-tab-title-orders = Orders
|
||||||
|
cargo-console-menu-tab-title-funds = Transfers
|
||||||
|
cargo-console-menu-account-action-transfer-limit = [bold]Transfer Limit:[/bold] ${$limit}
|
||||||
|
cargo-console-menu-account-action-transfer-limit-unlimited-notifier = [color=gold](Unlimited)[/color]
|
||||||
|
cargo-console-menu-account-action-select = [bold]Account Action:[/bold]
|
||||||
|
cargo-console-menu-account-action-amount = [bold]Amount:[/bold] $
|
||||||
|
cargo-console-menu-account-action-button = Transfer
|
||||||
|
cargo-console-menu-toggle-account-lock-button = Toggle Transfer Limit
|
||||||
|
cargo-console-menu-account-action-option-withdraw = Withdraw Cash
|
||||||
|
cargo-console-menu-account-action-option-transfer = Transfer Funds to {$code}
|
||||||
|
|
||||||
# Orders
|
# Orders
|
||||||
cargo-console-order-not-allowed = Access not allowed
|
cargo-console-order-not-allowed = Access not allowed
|
||||||
@@ -31,15 +42,21 @@ cargo-console-insufficient-funds = Insufficient funds (require {$cost})
|
|||||||
cargo-console-unfulfilled = No room to fulfill order
|
cargo-console-unfulfilled = No room to fulfill order
|
||||||
cargo-console-trade-station = Sent to {$destination}
|
cargo-console-trade-station = Sent to {$destination}
|
||||||
cargo-console-unlock-approved-order-broadcast = [bold]{$productName} x{$orderAmount}[/bold], which cost [bold]{$cost}[/bold], was approved by [bold]{$approver}[/bold]
|
cargo-console-unlock-approved-order-broadcast = [bold]{$productName} x{$orderAmount}[/bold], which cost [bold]{$cost}[/bold], was approved by [bold]{$approver}[/bold]
|
||||||
|
cargo-console-fund-withdraw-broadcast = [bold]{$name} withdrew {$amount} spesos from {$name1} \[{$code1}\]
|
||||||
|
cargo-console-fund-transfer-broadcast = [bold]{$name} transferred {$amount} spesos from {$name1} \[{$code1}\] to {$name2} \[{$code2}\][/bold]
|
||||||
|
cargo-console-fund-transfer-user-unknown = Unknown
|
||||||
|
|
||||||
|
cargo-console-paper-reason-default = None
|
||||||
|
cargo-console-paper-approver-default = Self
|
||||||
cargo-console-paper-print-name = Order #{$orderNumber}
|
cargo-console-paper-print-name = Order #{$orderNumber}
|
||||||
cargo-console-paper-print-text =
|
cargo-console-paper-print-text = [head=2]Order #{$orderNumber}[/head]
|
||||||
Order #{$orderNumber}
|
{"[bold]Item:[/bold]"} {$itemName} (x{$orderQuantity})
|
||||||
Item: {$itemName}
|
{"[bold]Requested by:[/bold]"} {$requester}
|
||||||
Quantity: {$orderQuantity}
|
|
||||||
Requested by: {$requester}
|
{"[head=3]Order Information[/head]"}
|
||||||
Reason: {$reason}
|
{"[bold]Payer[/bold]:"} {$account} [font="Monospace"]\[{$accountcode}\][/font]
|
||||||
Approved by: {$approver}
|
{"[bold]Approved by:[/bold]"} {$approver}
|
||||||
|
{"[bold]Reason:[/bold]"} {$reason}
|
||||||
|
|
||||||
# Cargo shuttle console
|
# Cargo shuttle console
|
||||||
cargo-shuttle-console-menu-title = Cargo shuttle console
|
cargo-shuttle-console-menu-title = Cargo shuttle console
|
||||||
@@ -47,3 +64,17 @@ cargo-shuttle-console-station-unknown = Unknown
|
|||||||
cargo-shuttle-console-shuttle-not-found = Not found
|
cargo-shuttle-console-shuttle-not-found = Not found
|
||||||
cargo-shuttle-console-organics = Detected organic lifeforms on the shuttle
|
cargo-shuttle-console-organics = Detected organic lifeforms on the shuttle
|
||||||
cargo-no-shuttle = No cargo shuttle found!
|
cargo-no-shuttle = No cargo shuttle found!
|
||||||
|
|
||||||
|
# Funding allocation console
|
||||||
|
cargo-funding-alloc-console-menu-title = Funding Allocation Console
|
||||||
|
cargo-funding-alloc-console-label-account = [bold]Account[/bold]
|
||||||
|
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-button-save = Save Changes
|
||||||
|
cargo-funding-alloc-console-label-save-fail = [bold]Revenue Divisions Invalid![/bold] [color=red]({$pos ->
|
||||||
|
[1] +
|
||||||
|
*[-1] -
|
||||||
|
}{$val}%)[/color]
|
||||||
|
|||||||
49
Resources/Prototypes/Catalog/Cargo/cargo_lockbox.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
- type: cargoProduct
|
||||||
|
id: CrateLockBoxEngineering
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Storage/Crates/lockbox.rsi
|
||||||
|
state: icon
|
||||||
|
product: CrateLockBoxEngineering
|
||||||
|
cost: 100
|
||||||
|
category: cargoproduct-category-name-engineering
|
||||||
|
group: market
|
||||||
|
|
||||||
|
- type: cargoProduct
|
||||||
|
id: CrateLockBoxMedical
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Storage/Crates/lockbox.rsi
|
||||||
|
state: icon
|
||||||
|
product: CrateLockBoxMedical
|
||||||
|
cost: 100
|
||||||
|
category: cargoproduct-category-name-medical
|
||||||
|
group: market
|
||||||
|
|
||||||
|
- type: cargoProduct
|
||||||
|
id: CrateLockBoxScience
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Storage/Crates/lockbox.rsi
|
||||||
|
state: icon
|
||||||
|
product: CrateLockBoxScience
|
||||||
|
cost: 100
|
||||||
|
category: cargoproduct-category-name-science
|
||||||
|
group: market
|
||||||
|
|
||||||
|
- type: cargoProduct
|
||||||
|
id: CrateLockBoxSecurity
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Storage/Crates/lockbox.rsi
|
||||||
|
state: icon
|
||||||
|
product: CrateLockBoxSecurity
|
||||||
|
cost: 100
|
||||||
|
category: cargoproduct-category-name-security
|
||||||
|
group: market
|
||||||
|
|
||||||
|
- type: cargoProduct
|
||||||
|
id: CrateLockBoxService
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Storage/Crates/lockbox.rsi
|
||||||
|
state: icon
|
||||||
|
product: CrateLockBoxService
|
||||||
|
cost: 100
|
||||||
|
category: cargoproduct-category-name-service
|
||||||
|
group: market
|
||||||
@@ -130,6 +130,8 @@
|
|||||||
- id: DoorRemoteService
|
- id: DoorRemoteService
|
||||||
- id: HoPIDCard
|
- id: HoPIDCard
|
||||||
- id: IDComputerCircuitboard
|
- id: IDComputerCircuitboard
|
||||||
|
- id: FundingAllocationComputerCircuitboard
|
||||||
|
- id: CargoRequestServiceComputerCircuitboard
|
||||||
- id: RubberStampApproved
|
- id: RubberStampApproved
|
||||||
- id: RubberStampDenied
|
- id: RubberStampDenied
|
||||||
- id: RubberStampHop
|
- id: RubberStampHop
|
||||||
@@ -160,6 +162,7 @@
|
|||||||
- id: ClothingHandsGlovesColorYellow
|
- id: ClothingHandsGlovesColorYellow
|
||||||
- id: ClothingHeadsetAltEngineering
|
- id: ClothingHeadsetAltEngineering
|
||||||
- id: DoorRemoteEngineering
|
- id: DoorRemoteEngineering
|
||||||
|
- id: CargoRequestEngineeringComputerCircuitboard
|
||||||
- id: RCD
|
- id: RCD
|
||||||
- id: RCDAmmo
|
- id: RCDAmmo
|
||||||
- id: RubberStampCE
|
- id: RubberStampCE
|
||||||
@@ -218,6 +221,7 @@
|
|||||||
- id: HandheldCrewMonitor
|
- id: HandheldCrewMonitor
|
||||||
- id: Hypospray
|
- id: Hypospray
|
||||||
- id: MedicalTechFabCircuitboard
|
- id: MedicalTechFabCircuitboard
|
||||||
|
- id: CargoRequestMedicalComputerCircuitboard
|
||||||
- id: MedkitFilled
|
- id: MedkitFilled
|
||||||
- id: RubberStampCMO
|
- id: RubberStampCMO
|
||||||
- id: MedTekCartridge
|
- id: MedTekCartridge
|
||||||
@@ -271,6 +275,7 @@
|
|||||||
- id: HandTeleporter
|
- id: HandTeleporter
|
||||||
- id: ProtolatheMachineCircuitboard
|
- id: ProtolatheMachineCircuitboard
|
||||||
- id: ResearchComputerCircuitboard
|
- id: ResearchComputerCircuitboard
|
||||||
|
- id: CargoRequestScienceComputerCircuitboard
|
||||||
- id: RubberStampRd
|
- id: RubberStampRd
|
||||||
|
|
||||||
# Hardsuit table, used for suit storage as well
|
# Hardsuit table, used for suit storage as well
|
||||||
@@ -328,6 +333,7 @@
|
|||||||
- id: HoloprojectorSecurity
|
- id: HoloprojectorSecurity
|
||||||
- id: RubberStampHos
|
- id: RubberStampHos
|
||||||
- id: SecurityTechFabCircuitboard
|
- id: SecurityTechFabCircuitboard
|
||||||
|
- id: CargoRequestSecurityComputerCircuitboard
|
||||||
- id: WeaponDisabler
|
- id: WeaponDisabler
|
||||||
- id: WantedListCartridge
|
- id: WantedListCartridge
|
||||||
- id: DrinkHosFlask
|
- id: DrinkHosFlask
|
||||||
|
|||||||
42
Resources/Prototypes/Catalog/cargo_accounts.yml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
- type: cargoAccount
|
||||||
|
id: Cargo
|
||||||
|
name: cargo-account-cargo-name
|
||||||
|
code: cargo-account-cargo-code
|
||||||
|
color: "#b48b57"
|
||||||
|
radioChannel: Supply
|
||||||
|
|
||||||
|
- type: cargoAccount
|
||||||
|
id: Engineering
|
||||||
|
name: cargo-account-engineering-name
|
||||||
|
code: cargo-account-engineering-code
|
||||||
|
color: "#ff733c"
|
||||||
|
radioChannel: Engineering
|
||||||
|
|
||||||
|
- type: cargoAccount
|
||||||
|
id: Medical
|
||||||
|
name: cargo-account-medical-name
|
||||||
|
code: cargo-account-medical-code
|
||||||
|
color: "#57b8f0"
|
||||||
|
radioChannel: Medical
|
||||||
|
|
||||||
|
- type: cargoAccount
|
||||||
|
id: Science
|
||||||
|
name: cargo-account-science-name
|
||||||
|
code: cargo-account-science-code
|
||||||
|
color: "#cd7ccd"
|
||||||
|
radioChannel: Science
|
||||||
|
|
||||||
|
- type: cargoAccount
|
||||||
|
id: Security
|
||||||
|
name: cargo-account-security-name
|
||||||
|
code: cargo-account-security-code
|
||||||
|
color: "#ff4242"
|
||||||
|
radioChannel: Security
|
||||||
|
|
||||||
|
- type: cargoAccount
|
||||||
|
id: Service
|
||||||
|
name: cargo-account-service-name
|
||||||
|
code: cargo-account-service-code
|
||||||
|
color: "#539c00"
|
||||||
|
radioChannel: Service
|
||||||
|
|
||||||
@@ -77,7 +77,6 @@
|
|||||||
- type: RadarConsole
|
- type: RadarConsole
|
||||||
followEntity: true
|
followEntity: true
|
||||||
- type: CargoOrderConsole
|
- type: CargoOrderConsole
|
||||||
- type: BankClient
|
|
||||||
- type: CrewMonitoringConsole
|
- type: CrewMonitoringConsole
|
||||||
- type: GeneralStationRecordConsole
|
- type: GeneralStationRecordConsole
|
||||||
canDeleteEntries: true
|
canDeleteEntries: true
|
||||||
|
|||||||
@@ -97,6 +97,84 @@
|
|||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 750
|
price: 750
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerCircuitboard
|
||||||
|
id: CargoRequestEngineeringComputerCircuitboard
|
||||||
|
name: engineering request computer board
|
||||||
|
description: A computer printed circuit board for an engineering request computer.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: cpu_engineering
|
||||||
|
- type: ComputerBoard
|
||||||
|
prototype: ComputerCargoOrdersEngineering
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 750
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerCircuitboard
|
||||||
|
id: CargoRequestMedicalComputerCircuitboard
|
||||||
|
name: medical request computer board
|
||||||
|
description: A computer printed circuit board for a medical request computer.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: cpu_medical
|
||||||
|
- type: ComputerBoard
|
||||||
|
prototype: ComputerCargoOrdersMedical
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 750
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerCircuitboard
|
||||||
|
id: CargoRequestScienceComputerCircuitboard
|
||||||
|
name: science request computer board
|
||||||
|
description: A computer printed circuit board for a science request computer.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: cpu_science
|
||||||
|
- type: ComputerBoard
|
||||||
|
prototype: ComputerCargoOrdersScience
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 750
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerCircuitboard
|
||||||
|
id: CargoRequestSecurityComputerCircuitboard
|
||||||
|
name: security request computer board
|
||||||
|
description: A computer printed circuit board for a security request computer.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: cpu_security
|
||||||
|
- type: ComputerBoard
|
||||||
|
prototype: ComputerCargoOrdersSecurity
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 750
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerCircuitboard
|
||||||
|
id: CargoRequestServiceComputerCircuitboard
|
||||||
|
name: service request computer board
|
||||||
|
description: A computer printed circuit board for a service request computer.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: cpu_service
|
||||||
|
- type: ComputerBoard
|
||||||
|
prototype: ComputerCargoOrdersService
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 750
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerCircuitboard
|
||||||
|
id: FundingAllocationComputerCircuitboard
|
||||||
|
name: funding allocation computer board
|
||||||
|
description: A computer printed circuit board for a funding allocation card console.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: cpu_command
|
||||||
|
- type: ComputerBoard
|
||||||
|
prototype: ComputerFundingAllocation
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 750
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputerCircuitboard
|
parent: BaseComputerCircuitboard
|
||||||
id: CargoSaleComputerCircuitboard
|
id: CargoSaleComputerCircuitboard
|
||||||
|
|||||||
@@ -599,7 +599,7 @@
|
|||||||
tags:
|
tags:
|
||||||
- Write
|
- Write
|
||||||
- type: CargoOrderConsole
|
- type: CargoOrderConsole
|
||||||
- type: BankClient
|
removeLimitAccess: [ "Quartermaster" ]
|
||||||
- type: ActivatableUI
|
- type: ActivatableUI
|
||||||
verbText: qm-clipboard-computer-verb-text
|
verbText: qm-clipboard-computer-verb-text
|
||||||
key: enum.CargoConsoleUiKey.Orders
|
key: enum.CargoConsoleUiKey.Orders
|
||||||
|
|||||||
@@ -10,6 +10,13 @@
|
|||||||
components:
|
components:
|
||||||
- type: StationBankAccount
|
- type: StationBankAccount
|
||||||
- type: StationCargoOrderDatabase
|
- type: StationCargoOrderDatabase
|
||||||
|
orders:
|
||||||
|
Cargo: [ ]
|
||||||
|
Engineering: [ ]
|
||||||
|
Medical: [ ]
|
||||||
|
Science: [ ]
|
||||||
|
Security: [ ]
|
||||||
|
Service: [ ]
|
||||||
- type: StationCargoBountyDatabase
|
- type: StationCargoBountyDatabase
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
@@ -906,11 +906,11 @@
|
|||||||
- map: ["computerLayerScreen"]
|
- map: ["computerLayerScreen"]
|
||||||
state: request
|
state: request
|
||||||
- map: ["computerLayerKeys"]
|
- map: ["computerLayerKeys"]
|
||||||
state: tech_key
|
state: generic_keys
|
||||||
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
state: generic_panel_open
|
state: generic_panel_open
|
||||||
- type: CargoOrderConsole
|
- type: CargoOrderConsole
|
||||||
- type: BankClient
|
removeLimitAccess: [ "Quartermaster" ]
|
||||||
- type: ActiveRadio
|
- type: ActiveRadio
|
||||||
channels:
|
channels:
|
||||||
- Supply
|
- Supply
|
||||||
@@ -943,6 +943,167 @@
|
|||||||
guides:
|
guides:
|
||||||
- Cargo
|
- Cargo
|
||||||
|
|
||||||
|
# Request console variants.
|
||||||
|
- type: entity
|
||||||
|
id: ComputerCargoOrdersEngineering
|
||||||
|
parent: ComputerCargoOrders
|
||||||
|
name: engineering request computer
|
||||||
|
description: Used by the engineering department to order supplies.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- map: ["computerLayerBody"]
|
||||||
|
state: computer
|
||||||
|
- map: ["computerLayerKeyboard"]
|
||||||
|
state: generic_keyboard
|
||||||
|
- map: ["computerLayerScreen"]
|
||||||
|
state: request-eng
|
||||||
|
- map: ["computerLayerKeys"]
|
||||||
|
state: generic_keys
|
||||||
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
|
state: generic_panel_open
|
||||||
|
- type: CargoOrderConsole
|
||||||
|
account: Engineering
|
||||||
|
announcementChannel: Engineering
|
||||||
|
removeLimitAccess: [ "ChiefEngineer" ]
|
||||||
|
- type: ActiveRadio
|
||||||
|
channels:
|
||||||
|
- Engineering
|
||||||
|
- type: Computer
|
||||||
|
board: CargoRequestEngineeringComputerCircuitboard
|
||||||
|
- type: PointLight
|
||||||
|
color: "#c9c042"
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Engineering"]]
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: ComputerCargoOrdersMedical
|
||||||
|
parent: ComputerCargoOrders
|
||||||
|
name: medical request computer
|
||||||
|
description: Used by the medical department to order supplies.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- map: ["computerLayerBody"]
|
||||||
|
state: computer
|
||||||
|
- map: ["computerLayerKeyboard"]
|
||||||
|
state: generic_keyboard
|
||||||
|
- map: ["computerLayerScreen"]
|
||||||
|
state: request-med
|
||||||
|
- map: ["computerLayerKeys"]
|
||||||
|
state: generic_keys
|
||||||
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
|
state: generic_panel_open
|
||||||
|
- type: CargoOrderConsole
|
||||||
|
account: Medical
|
||||||
|
announcementChannel: Medical
|
||||||
|
removeLimitAccess: [ "ChiefMedicalOfficer" ]
|
||||||
|
- type: ActiveRadio
|
||||||
|
channels:
|
||||||
|
- Medical
|
||||||
|
- type: Computer
|
||||||
|
board: CargoRequestMedicalComputerCircuitboard
|
||||||
|
- type: PointLight
|
||||||
|
color: "#41e0fc"
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Medical"]]
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: ComputerCargoOrdersScience
|
||||||
|
parent: ComputerCargoOrders
|
||||||
|
name: science request computer
|
||||||
|
description: Used by the science department to order supplies.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- map: ["computerLayerBody"]
|
||||||
|
state: computer
|
||||||
|
- map: ["computerLayerKeyboard"]
|
||||||
|
state: generic_keyboard
|
||||||
|
- map: ["computerLayerScreen"]
|
||||||
|
state: request-sci
|
||||||
|
- map: ["computerLayerKeys"]
|
||||||
|
state: generic_keys
|
||||||
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
|
state: generic_panel_open
|
||||||
|
- type: CargoOrderConsole
|
||||||
|
account: Science
|
||||||
|
announcementChannel: Science
|
||||||
|
removeLimitAccess: [ "ResearchDirector" ]
|
||||||
|
- type: ActiveRadio
|
||||||
|
channels:
|
||||||
|
- Science
|
||||||
|
- type: Computer
|
||||||
|
board: CargoRequestScienceComputerCircuitboard
|
||||||
|
- type: PointLight
|
||||||
|
color: "#b53ca1"
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Research"]]
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: ComputerCargoOrdersSecurity
|
||||||
|
parent: ComputerCargoOrders
|
||||||
|
name: security request computer
|
||||||
|
description: Used by the security department to order supplies.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- map: ["computerLayerBody"]
|
||||||
|
state: computer
|
||||||
|
- map: ["computerLayerKeyboard"]
|
||||||
|
state: generic_keyboard
|
||||||
|
- map: ["computerLayerScreen"]
|
||||||
|
state: request-sec
|
||||||
|
- map: ["computerLayerKeys"]
|
||||||
|
state: generic_keys
|
||||||
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
|
state: generic_panel_open
|
||||||
|
- type: CargoOrderConsole
|
||||||
|
account: Security
|
||||||
|
announcementChannel: Security
|
||||||
|
removeLimitAccess: [ "HeadOfSecurity" ]
|
||||||
|
- type: ActiveRadio
|
||||||
|
channels:
|
||||||
|
- Security
|
||||||
|
- type: Computer
|
||||||
|
board: CargoRequestSecurityComputerCircuitboard
|
||||||
|
- type: PointLight
|
||||||
|
color: "#d11d00"
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Security"]]
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: ComputerCargoOrdersService
|
||||||
|
parent: ComputerCargoOrders
|
||||||
|
name: service request computer
|
||||||
|
description: Used by the service department to order supplies.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- map: ["computerLayerBody"]
|
||||||
|
state: computer
|
||||||
|
- map: ["computerLayerKeyboard"]
|
||||||
|
state: generic_keyboard
|
||||||
|
- map: ["computerLayerScreen"]
|
||||||
|
state: request-srv
|
||||||
|
- map: ["computerLayerKeys"]
|
||||||
|
state: generic_keys
|
||||||
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
|
state: generic_panel_open
|
||||||
|
- type: CargoOrderConsole
|
||||||
|
account: Service
|
||||||
|
announcementChannel: Service
|
||||||
|
removeLimitAccess: [ "HeadOfPersonnel" ]
|
||||||
|
- type: ActiveRadio
|
||||||
|
channels:
|
||||||
|
- Service
|
||||||
|
- type: Computer
|
||||||
|
board: CargoRequestServiceComputerCircuitboard
|
||||||
|
- type: PointLight
|
||||||
|
color: "#afe837"
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Service"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ComputerCargoBounty
|
id: ComputerCargoBounty
|
||||||
parent: BaseComputerAiAccess
|
parent: BaseComputerAiAccess
|
||||||
@@ -983,6 +1144,43 @@
|
|||||||
- CargoBounties
|
- CargoBounties
|
||||||
- Cargo
|
- Cargo
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerAiAccess
|
||||||
|
id: ComputerFundingAllocation
|
||||||
|
name: funding allocation computer
|
||||||
|
description: Terminal for controlling the distribution of funds and pay to departments.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- map: ["computerLayerBody"]
|
||||||
|
state: computer
|
||||||
|
- map: ["computerLayerKeyboard"]
|
||||||
|
state: generic_keyboard
|
||||||
|
- map: ["computerLayerScreen"]
|
||||||
|
state: allocate # ALLOCATION !!!
|
||||||
|
- map: ["computerLayerKeys"]
|
||||||
|
state: generic_keys
|
||||||
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
|
state: generic_panel_open
|
||||||
|
- type: FundingAllocationConsole
|
||||||
|
- type: ActivatableUI
|
||||||
|
key: enum.FundingAllocationConsoleUiKey.Key
|
||||||
|
- type: ActivatableUIRequiresAccess
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["HeadOfPersonnel"]]
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
enum.FundingAllocationConsoleUiKey.Key:
|
||||||
|
type: FundingAllocationConsoleBoundUserInterface
|
||||||
|
enum.WiresUiKey.Key:
|
||||||
|
type: WiresBoundUserInterface
|
||||||
|
- type: Computer
|
||||||
|
board: FundingAllocationComputerCircuitboard
|
||||||
|
- type: PointLight
|
||||||
|
radius: 1.5
|
||||||
|
energy: 1.6
|
||||||
|
color: "#3c5eb5"
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputerAiAccess
|
parent: BaseComputerAiAccess
|
||||||
id: ComputerCloningConsole
|
id: ComputerCloningConsole
|
||||||
@@ -1182,9 +1380,9 @@
|
|||||||
- map: ["computerLayerKeyboard"]
|
- map: ["computerLayerKeyboard"]
|
||||||
state: generic_keyboard
|
state: generic_keyboard
|
||||||
- map: ["computerLayerScreen"]
|
- map: ["computerLayerScreen"]
|
||||||
state: request
|
state: transfer
|
||||||
- map: ["computerLayerKeys"]
|
- map: ["computerLayerKeys"]
|
||||||
state: tech_key
|
state: generic_keys
|
||||||
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
state: generic_panel_open
|
state: generic_panel_open
|
||||||
- type: Anchorable
|
- type: Anchorable
|
||||||
|
|||||||
@@ -426,6 +426,194 @@
|
|||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 75
|
price: 75
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: CrateBaseLockBox
|
||||||
|
parent: CrateBaseSecure
|
||||||
|
name: lock box
|
||||||
|
description: "A secure lock box. Funds from its sale will be distributed back to the department. Just remember: Cargo always takes a cut."
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Structures/Storage/Crates/lockbox.rsi
|
||||||
|
- type: GenericVisualizer
|
||||||
|
visuals:
|
||||||
|
enum.PaperLabelVisuals.HasLabel:
|
||||||
|
enum.PaperLabelVisuals.Layer:
|
||||||
|
True: { visible: true }
|
||||||
|
False: { visible: false }
|
||||||
|
enum.PaperLabelVisuals.LabelType:
|
||||||
|
enum.PaperLabelVisuals.Layer:
|
||||||
|
Paper: { state: paper }
|
||||||
|
Bounty: { state: bounty }
|
||||||
|
CaptainsPaper: { state: captains_paper }
|
||||||
|
Invoice: { state: invoice }
|
||||||
|
enum.StorageVisuals.Open:
|
||||||
|
lid_overlay:
|
||||||
|
True: { visible: false }
|
||||||
|
False: { visible: true }
|
||||||
|
- type: OverrideSell
|
||||||
|
- type: Fixtures
|
||||||
|
fixtures:
|
||||||
|
fix1:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeAabb
|
||||||
|
bounds: "-0.3,-0.4,0.3,0.19"
|
||||||
|
density: 50
|
||||||
|
mask:
|
||||||
|
- CrateMask #this is so they can go under plastic flaps
|
||||||
|
layer:
|
||||||
|
- MachineLayer
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: CrateLockBoxEngineering
|
||||||
|
parent: CrateBaseLockBox
|
||||||
|
name: engineering lock box
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- state: base
|
||||||
|
- state: overlay
|
||||||
|
color: "#ad8c27"
|
||||||
|
- state: closed
|
||||||
|
map: ["enum.StorageVisualLayers.Door"]
|
||||||
|
- state: overlay-closed
|
||||||
|
color: "#ad8c27"
|
||||||
|
map: [ lid_overlay ]
|
||||||
|
- state: welded
|
||||||
|
visible: false
|
||||||
|
map: ["enum.WeldableLayers.BaseWelded"]
|
||||||
|
- state: locked
|
||||||
|
map: ["enum.LockVisualLayers.Lock"]
|
||||||
|
shader: unshaded
|
||||||
|
- state: paper
|
||||||
|
sprite: Structures/Storage/Crates/labels.rsi
|
||||||
|
offset: "-0.46875,0.03125"
|
||||||
|
map: ["enum.PaperLabelVisuals.Layer"]
|
||||||
|
- type: OverrideSell
|
||||||
|
overrideAccount: Engineering
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Engineering"]]
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: CrateLockBoxMedical
|
||||||
|
parent: CrateBaseLockBox
|
||||||
|
name: medical lock box
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- state: base
|
||||||
|
- state: overlay
|
||||||
|
color: "#92c7e8"
|
||||||
|
- state: closed
|
||||||
|
map: ["enum.StorageVisualLayers.Door"]
|
||||||
|
- state: overlay-closed
|
||||||
|
color: "#92c7e8"
|
||||||
|
map: [ lid_overlay ]
|
||||||
|
- state: welded
|
||||||
|
visible: false
|
||||||
|
map: ["enum.WeldableLayers.BaseWelded"]
|
||||||
|
- state: locked
|
||||||
|
map: ["enum.LockVisualLayers.Lock"]
|
||||||
|
shader: unshaded
|
||||||
|
- state: paper
|
||||||
|
sprite: Structures/Storage/Crates/labels.rsi
|
||||||
|
offset: "-0.46875,0.03125"
|
||||||
|
map: ["enum.PaperLabelVisuals.Layer"]
|
||||||
|
- type: OverrideSell
|
||||||
|
overrideAccount: Medical
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Medical"]]
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: CrateLockBoxScience
|
||||||
|
parent: CrateBaseLockBox
|
||||||
|
name: science lock box
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- state: base
|
||||||
|
- state: overlay
|
||||||
|
color: "#ba4bf0"
|
||||||
|
- state: closed
|
||||||
|
map: ["enum.StorageVisualLayers.Door"]
|
||||||
|
- state: overlay-closed
|
||||||
|
color: "#ba4bf0"
|
||||||
|
map: [ lid_overlay ]
|
||||||
|
- state: welded
|
||||||
|
visible: false
|
||||||
|
map: ["enum.WeldableLayers.BaseWelded"]
|
||||||
|
- state: locked
|
||||||
|
map: ["enum.LockVisualLayers.Lock"]
|
||||||
|
shader: unshaded
|
||||||
|
- state: paper
|
||||||
|
sprite: Structures/Storage/Crates/labels.rsi
|
||||||
|
offset: "-0.46875,0.03125"
|
||||||
|
map: ["enum.PaperLabelVisuals.Layer"]
|
||||||
|
- type: OverrideSell
|
||||||
|
overrideAccount: Science
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Research"]]
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: CrateLockBoxSecurity
|
||||||
|
parent: CrateBaseLockBox
|
||||||
|
name: security lock box
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- state: base
|
||||||
|
- state: overlay
|
||||||
|
color: "#c12d30"
|
||||||
|
- state: closed
|
||||||
|
map: ["enum.StorageVisualLayers.Door"]
|
||||||
|
- state: overlay-closed
|
||||||
|
color: "#c12d30"
|
||||||
|
map: [ lid_overlay ]
|
||||||
|
- state: welded
|
||||||
|
visible: false
|
||||||
|
map: ["enum.WeldableLayers.BaseWelded"]
|
||||||
|
- state: locked
|
||||||
|
map: ["enum.LockVisualLayers.Lock"]
|
||||||
|
shader: unshaded
|
||||||
|
- state: paper
|
||||||
|
sprite: Structures/Storage/Crates/labels.rsi
|
||||||
|
offset: "-0.46875,0.03125"
|
||||||
|
map: ["enum.PaperLabelVisuals.Layer"]
|
||||||
|
- type: OverrideSell
|
||||||
|
overrideAccount: Security
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Security"]]
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: CrateLockBoxService
|
||||||
|
parent: CrateBaseLockBox
|
||||||
|
name: service lock box
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- state: base
|
||||||
|
- state: overlay
|
||||||
|
color: "#53b723"
|
||||||
|
- state: closed
|
||||||
|
map: ["enum.StorageVisualLayers.Door"]
|
||||||
|
- state: overlay-closed
|
||||||
|
color: "#53b723"
|
||||||
|
map: [ lid_overlay ]
|
||||||
|
- state: welded
|
||||||
|
visible: false
|
||||||
|
map: ["enum.WeldableLayers.BaseWelded"]
|
||||||
|
- state: locked
|
||||||
|
map: ["enum.LockVisualLayers.Lock"]
|
||||||
|
shader: unshaded
|
||||||
|
- state: paper
|
||||||
|
sprite: Structures/Storage/Crates/labels.rsi
|
||||||
|
offset: "-0.46875,0.03125"
|
||||||
|
map: ["enum.PaperLabelVisuals.Layer"]
|
||||||
|
- type: OverrideSell
|
||||||
|
overrideAccount: Service
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Service"]]
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: CrateGeneric
|
parent: CrateGeneric
|
||||||
id: CratePirate
|
id: CratePirate
|
||||||
|
|||||||
14
Resources/Prototypes/SoundCollections/machines.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
- type: soundCollection
|
||||||
|
id: CargoPing
|
||||||
|
files:
|
||||||
|
- /Audio/Effects/Cargo/ping.ogg
|
||||||
|
|
||||||
|
- type: soundCollection
|
||||||
|
id: CargoError
|
||||||
|
files:
|
||||||
|
- /Audio/Effects/Cargo/buzz_sigh.ogg
|
||||||
|
|
||||||
|
- type: soundCollection
|
||||||
|
id: CargoToggleLimit
|
||||||
|
files:
|
||||||
|
- /Audio/Machines/quickbeep.ogg
|
||||||
|
After Width: | Height: | Size: 971 B |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"license": "CC-BY-SA-3.0",
|
"license": "CC-BY-SA-3.0",
|
||||||
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/bd6873fd4dd6a61d7e46f1d75cd4d90f64c40894. comm_syndie made by Veritius, based on comm. generic_panel_open made by Errant, commit https://github.com/space-wizards/space-station-14/pull/32273, comms_wizard and wizard_key by ScarKy0",
|
"copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/bd6873fd4dd6a61d7e46f1d75cd4d90f64c40894. comm_syndie made by Veritius, based on comm. generic_panel_open made by Errant, commit https://github.com/space-wizards/space-station-14/pull/32273, comms_wizard and wizard_key by ScarKy0, request- variants transfer made by EmoGarbage404 (github)",
|
||||||
"size": {
|
"size": {
|
||||||
"x": 32,
|
"x": 32,
|
||||||
"y": 32
|
"y": 32
|
||||||
@@ -131,6 +131,32 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "allocate",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "area_atmos",
|
"name": "area_atmos",
|
||||||
"directions": 4,
|
"directions": 4,
|
||||||
@@ -1452,6 +1478,196 @@
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "request-eng",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request-med",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request-sci",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request-sec",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "request-srv",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3,
|
||||||
|
0.3
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "robot",
|
"name": "robot",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
@@ -1654,6 +1870,64 @@
|
|||||||
"name": "telesci_key_off",
|
"name": "telesci_key_off",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "transfer",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "turbinecomp",
|
"name": "turbinecomp",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 361 B |
|
After Width: | Height: | Size: 187 B |
|
After Width: | Height: | Size: 370 B |
|
After Width: | Height: | Size: 144 B |
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Created by EmoGarbage404 (github) for Space Station 14.",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "base"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "closed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "overlay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "overlay-closed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "open"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "welded"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "locked"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unlocked"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sparking",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 240 B |
|
After Width: | Height: | Size: 155 B |
|
After Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 221 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 274 B |