Salvage Job Board (#37549)
* Salvage Job Board * More development * Small boy * Computer yaml (partial) * UI * Rank unlock logic * Job label printing * appraisal tool integration * Jobs * add board to QM locker * boom! * command desc * mild rewording * ackh, mein pr ist brohken
This commit is contained in:
@@ -138,6 +138,11 @@ namespace Content.Client.Cargo.BUI
|
|||||||
|
|
||||||
AccountName = cState.Name;
|
AccountName = cState.Name;
|
||||||
|
|
||||||
|
if (_menu == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_menu.ProductCatalogue = cState.Products;
|
||||||
|
|
||||||
_menu?.UpdateStation(station);
|
_menu?.UpdateStation(station);
|
||||||
Populate(cState.Orders);
|
Populate(cState.Orders);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ namespace Content.Client.Cargo.UI
|
|||||||
private readonly List<string> _categoryStrings = new();
|
private readonly List<string> _categoryStrings = new();
|
||||||
private string? _category;
|
private string? _category;
|
||||||
|
|
||||||
|
public List<ProtoId<CargoProductPrototype>> ProductCatalogue = new();
|
||||||
|
|
||||||
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);
|
||||||
@@ -113,14 +115,16 @@ namespace Content.Client.Cargo.UI
|
|||||||
Categories.SelectId(id);
|
Categories.SelectId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<CargoProductPrototype> ProductPrototypes
|
private IEnumerable<CargoProductPrototype> ProductPrototypes
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var allowedGroups = _entityManager.GetComponentOrNull<CargoOrderConsoleComponent>(_owner)?.AllowedGroups;
|
var allowedGroups = _entityManager.GetComponentOrNull<CargoOrderConsoleComponent>(_owner)?.AllowedGroups;
|
||||||
|
|
||||||
foreach (var cargoPrototype in _protoManager.EnumeratePrototypes<CargoProductPrototype>())
|
foreach (var cargoPrototypeId in ProductCatalogue)
|
||||||
{
|
{
|
||||||
|
var cargoPrototype = _protoManager.Index(cargoPrototypeId);
|
||||||
|
|
||||||
if (!allowedGroups?.Contains(cargoPrototype.Group) ?? false)
|
if (!allowedGroups?.Contains(cargoPrototype.Group) ?? false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
29
Content.Client/Salvage/UI/JobEntry.xaml
Normal file
29
Content.Client/Salvage/UI/JobEntry.xaml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<BoxContainer xmlns="https://spacestation14.io"
|
||||||
|
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||||
|
Margin="10 10 10 0"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Visible="True">
|
||||||
|
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||||
|
<BoxContainer HorizontalExpand="True" Orientation="Vertical" MaxWidth="380">
|
||||||
|
<RichTextLabel Name="NameLabel" StyleClasses="LabelKeyText"/>
|
||||||
|
<customControls:HSeparator Margin="0 0 0 5"/>
|
||||||
|
<RichTextLabel Name="DescriptionLabel" HorizontalExpand="True"/>
|
||||||
|
<Control MinHeight="10"/>
|
||||||
|
<RichTextLabel Name="ManifestLabel"/>
|
||||||
|
<Control MinHeight="10"/>
|
||||||
|
<RichTextLabel Name="RewardLabel" VerticalExpand="True" VerticalAlignment="Bottom"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer HorizontalExpand="True" VerticalExpand="True" VerticalAlignment="Center">
|
||||||
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True" HorizontalAlignment="Center">
|
||||||
|
<TextureRect Name="IconRect" MinSize="64 64" HorizontalAlignment="Center"/>
|
||||||
|
<Control MinHeight="20"/>
|
||||||
|
<Button Name="PrintButton"
|
||||||
|
Text="{Loc 'bounty-console-label-button-text'}"
|
||||||
|
HorizontalExpand="False"
|
||||||
|
HorizontalAlignment="Center"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</PanelContainer>
|
||||||
|
</BoxContainer>
|
||||||
44
Content.Client/Salvage/UI/JobEntry.xaml.cs
Normal file
44
Content.Client/Salvage/UI/JobEntry.xaml.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Content.Client.Message;
|
||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
|
||||||
|
namespace Content.Client.Salvage.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class JobEntry : BoxContainer
|
||||||
|
{
|
||||||
|
public Action? OnLabelButtonPressed;
|
||||||
|
|
||||||
|
public JobEntry(CargoBountyPrototype job, IEntityManager entMan)
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
|
NameLabel.SetMarkup(Loc.GetString($"salv-job-board-name-{job.ID}"));
|
||||||
|
|
||||||
|
var items = new List<string>();
|
||||||
|
foreach (var entry in job.Entries)
|
||||||
|
{
|
||||||
|
items.Add(Loc.GetString("bounty-console-manifest-entry",
|
||||||
|
("amount", entry.Amount),
|
||||||
|
("item", Loc.GetString(entry.Name))));
|
||||||
|
}
|
||||||
|
ManifestLabel.SetMarkup(Loc.GetString("job-board-ui-label-items", ("item", string.Join(", ", items))));
|
||||||
|
RewardLabel.SetMarkup(Loc.GetString("bounty-console-reward-label", ("reward", job.Reward)));
|
||||||
|
DescriptionLabel.SetMarkup(Loc.GetString(job.Description));
|
||||||
|
|
||||||
|
if (job.Sprite != null)
|
||||||
|
{
|
||||||
|
var texture = entMan.System<SpriteSystem>().Frame0(job.Sprite);
|
||||||
|
|
||||||
|
// Make sure the actual size of the control is the same regardless of the texture size.
|
||||||
|
IconRect.TextureScale = Vector2.One * (3f / (texture.Size.X / 32f));
|
||||||
|
IconRect.Texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintButton.OnPressed += _ => OnLabelButtonPressed?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using Content.Shared.Cargo.Components;
|
||||||
|
using Content.Shared.Salvage.JobBoard;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
|
||||||
|
namespace Content.Client.Salvage.UI;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class SalvageJobBoardBoundUserInterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
||||||
|
{
|
||||||
|
[ViewVariables]
|
||||||
|
private SalvageJobBoardMenu? _menu;
|
||||||
|
|
||||||
|
protected override void Open()
|
||||||
|
{
|
||||||
|
base.Open();
|
||||||
|
|
||||||
|
_menu = this.CreateWindow<SalvageJobBoardMenu>();
|
||||||
|
|
||||||
|
_menu.OnLabelButtonPressed += id =>
|
||||||
|
{
|
||||||
|
SendMessage(new JobBoardPrintLabelMessage(id));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateState(BoundUserInterfaceState message)
|
||||||
|
{
|
||||||
|
base.UpdateState(message);
|
||||||
|
|
||||||
|
if (message is not SalvageJobBoardConsoleState state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_menu?.Update(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
Content.Client/Salvage/UI/SalvageJobBoardMenu.xaml
Normal file
45
Content.Client/Salvage/UI/SalvageJobBoardMenu.xaml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||||
|
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
|
Title="{Loc 'job-board-ui-window-title'}"
|
||||||
|
SetSize="550 550"
|
||||||
|
Resizable="False">
|
||||||
|
<BoxContainer Orientation="Vertical"
|
||||||
|
VerticalExpand="True"
|
||||||
|
HorizontalExpand="True">
|
||||||
|
<BoxContainer Orientation="Horizontal" Margin="20 10 20 0">
|
||||||
|
<ProgressBar Name="RankProgressBar" HorizontalExpand="True" MinValue="0" MaxValue="1">
|
||||||
|
<ProgressBar.ForegroundStyleBoxOverride>
|
||||||
|
<gfx:StyleBoxFlat BackgroundColor="#FFFF00"/>
|
||||||
|
</ProgressBar.ForegroundStyleBoxOverride>
|
||||||
|
</ProgressBar>
|
||||||
|
<Control MinWidth="20"/>
|
||||||
|
<RichTextLabel Text="{Loc 'job-board-ui-label-rank'}" Margin="0 0 5 0"/>
|
||||||
|
<RichTextLabel Text="{Loc 'salvage-job-rank-title-0'}" Name="RankLabel"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<PanelContainer VerticalExpand="True" HorizontalExpand="True" Margin="10">
|
||||||
|
<PanelContainer.PanelOverride>
|
||||||
|
<gfx:StyleBoxFlat BackgroundColor="#1B1B1E" />
|
||||||
|
</PanelContainer.PanelOverride>
|
||||||
|
<ScrollContainer HScrollEnabled="False"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="True">
|
||||||
|
<BoxContainer Name="CurrentJobContainer"
|
||||||
|
Orientation="Vertical"
|
||||||
|
VerticalExpand="True"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Margin="0 0 0 10"/>
|
||||||
|
</ScrollContainer>
|
||||||
|
</PanelContainer>
|
||||||
|
<!-- Footer -->
|
||||||
|
<BoxContainer Orientation="Vertical">
|
||||||
|
<PanelContainer StyleClasses="LowDivider" />
|
||||||
|
<BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
|
||||||
|
<Label Text="{Loc 'bounty-console-flavor-right'}" StyleClasses="WindowFooterText"
|
||||||
|
HorizontalAlignment="Right" HorizontalExpand="True" Margin="0 0 5 0" />
|
||||||
|
<TextureRect StyleClasses="NTLogoDark" Stretch="KeepAspectCentered"
|
||||||
|
VerticalAlignment="Center" HorizontalAlignment="Right" SetSize="19 19"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</controls:FancyWindow>
|
||||||
38
Content.Client/Salvage/UI/SalvageJobBoardMenu.xaml.cs
Normal file
38
Content.Client/Salvage/UI/SalvageJobBoardMenu.xaml.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using Content.Client.Message;
|
||||||
|
using Content.Client.UserInterface.Controls;
|
||||||
|
using Content.Shared.Salvage.JobBoard;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client.Salvage.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class SalvageJobBoardMenu : FancyWindow
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
|
public Action<string>? OnLabelButtonPressed;
|
||||||
|
|
||||||
|
public SalvageJobBoardMenu()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(SalvageJobBoardConsoleState state)
|
||||||
|
{
|
||||||
|
RankLabel.SetMarkup(Loc.GetString(state.Title));
|
||||||
|
RankProgressBar.Value = state.Progression;
|
||||||
|
|
||||||
|
CurrentJobContainer.Children.Clear();
|
||||||
|
foreach (var job in state.AvailableJobs)
|
||||||
|
{
|
||||||
|
var entry = new JobEntry(_prototypeManager.Index(job), _entityManager);
|
||||||
|
entry.OnLabelButtonPressed += () => OnLabelButtonPressed?.Invoke(job);
|
||||||
|
|
||||||
|
CurrentJobContainer.AddChild(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
namespace Content.Server.Cargo.Components;
|
namespace Content.Server.Cargo.Components;
|
||||||
@@ -41,6 +43,12 @@ public sealed partial class StationCargoBountyDatabaseComponent : Component
|
|||||||
[DataField]
|
[DataField]
|
||||||
public HashSet<string> CheckedBounties = new();
|
public HashSet<string> CheckedBounties = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The group that bounties are pulled from.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<CargoBountyGroupPrototype> Group = "StationBounty";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time at which players will be able to skip the next bounty.
|
/// The time at which players will be able to skip the next bounty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -31,6 +31,16 @@ public sealed partial class StationCargoOrderDatabaseComponent : Component
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public int NumOrdersCreated;
|
public int NumOrdersCreated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An all encompassing determiner of what markets can be ordered from.
|
||||||
|
/// Not every console can order from every market, but a console can't order from a market not on this list.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public List<ProtoId<CargoMarketPrototype>> Markets = new()
|
||||||
|
{
|
||||||
|
"market",
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: Can probably dump this
|
// TODO: Can probably dump this
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The cargo shuttle assigned to this station.
|
/// The cargo shuttle assigned to this station.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using Content.Shared.Whitelist;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.Containers;
|
using Robust.Server.Containers;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
@@ -292,6 +293,13 @@ public sealed partial class CargoSystem
|
|||||||
return IsBountyComplete(container, proto.Entries);
|
return IsBountyComplete(container, proto.Entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsBountyComplete(EntityUid container, ProtoId<CargoBountyPrototype> prototypeId)
|
||||||
|
{
|
||||||
|
var prototype = _protoMan.Index(prototypeId);
|
||||||
|
|
||||||
|
return IsBountyComplete(container, prototype.Entries);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsBountyComplete(EntityUid container, CargoBountyPrototype prototype)
|
public bool IsBountyComplete(EntityUid container, CargoBountyPrototype prototype)
|
||||||
{
|
{
|
||||||
return IsBountyComplete(container, prototype.Entries);
|
return IsBountyComplete(container, prototype.Entries);
|
||||||
@@ -392,7 +400,9 @@ public sealed partial class CargoSystem
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// todo: consider making the cargo bounties weighted.
|
// todo: consider making the cargo bounties weighted.
|
||||||
var allBounties = _protoMan.EnumeratePrototypes<CargoBountyPrototype>().ToList();
|
var allBounties = _protoMan.EnumeratePrototypes<CargoBountyPrototype>()
|
||||||
|
.Where(p => p.Group == component.Group)
|
||||||
|
.ToList();
|
||||||
var filteredBounties = new List<CargoBountyPrototype>();
|
var filteredBounties = new List<CargoBountyPrototype>();
|
||||||
foreach (var proto in allBounties)
|
foreach (var proto in allBounties)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.Cargo.Components;
|
using Content.Server.Cargo.Components;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
@@ -372,7 +373,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!component.AllowedGroups.Contains(product.Group))
|
if (!GetAvailableProducts((uid, component)).Contains(args.CargoProductId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (component.SlipPrinter)
|
if (component.SlipPrinter)
|
||||||
@@ -421,7 +422,8 @@ namespace Content.Server.Cargo.Systems
|
|||||||
GetOutstandingOrderCount(orderDatabase, console.Account),
|
GetOutstandingOrderCount(orderDatabase, console.Account),
|
||||||
orderDatabase.Capacity,
|
orderDatabase.Capacity,
|
||||||
GetNetEntity(station.Value),
|
GetNetEntity(station.Value),
|
||||||
orderDatabase.Orders[console.Account]
|
orderDatabase.Orders[console.Account],
|
||||||
|
GetAvailableProducts((consoleUid, console))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -617,6 +619,29 @@ namespace Content.Server.Cargo.Systems
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ProtoId<CargoProductPrototype>> GetAvailableProducts(Entity<CargoOrderConsoleComponent> ent)
|
||||||
|
{
|
||||||
|
if (_station.GetOwningStation(ent) is not { } station ||
|
||||||
|
!TryComp<StationCargoOrderDatabaseComponent>(station, out var db))
|
||||||
|
{
|
||||||
|
return new List<ProtoId<CargoProductPrototype>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var products = new List<ProtoId<CargoProductPrototype>>();
|
||||||
|
|
||||||
|
// Note that a market must be both on the station and on the console to be available.
|
||||||
|
var markets = ent.Comp.AllowedGroups.Intersect(db.Markets).ToList();
|
||||||
|
foreach (var product in _protoMan.EnumeratePrototypes<CargoProductPrototype>())
|
||||||
|
{
|
||||||
|
if (!markets.Contains(product.Group))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
products.Add(product.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return products;
|
||||||
|
}
|
||||||
|
|
||||||
#region Station
|
#region Station
|
||||||
|
|
||||||
private bool TryGetOrderDatabase([NotNullWhen(true)] EntityUid? stationUid, [MaybeNullWhen(false)] out StationCargoOrderDatabaseComponent dbComp)
|
private bool TryGetOrderDatabase([NotNullWhen(true)] EntityUid? stationUid, [MaybeNullWhen(false)] out StationCargoOrderDatabaseComponent dbComp)
|
||||||
|
|||||||
@@ -131,14 +131,14 @@ public sealed partial class CargoSystem
|
|||||||
|
|
||||||
#region Station
|
#region Station
|
||||||
|
|
||||||
private bool SellPallets(EntityUid gridUid, out HashSet<(EntityUid, OverrideSellComponent?, double)> goods)
|
private bool SellPallets(EntityUid gridUid, EntityUid station, out HashSet<(EntityUid, OverrideSellComponent?, double)> goods)
|
||||||
{
|
{
|
||||||
GetPalletGoods(gridUid, out var toSell, out goods);
|
GetPalletGoods(gridUid, out var toSell, out goods);
|
||||||
|
|
||||||
if (toSell.Count == 0)
|
if (toSell.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var ev = new EntitySoldEvent(toSell);
|
var ev = new EntitySoldEvent(toSell, station);
|
||||||
RaiseLocalEvent(ref ev);
|
RaiseLocalEvent(ref ev);
|
||||||
|
|
||||||
foreach (var ent in toSell)
|
foreach (var ent in toSell)
|
||||||
@@ -230,7 +230,7 @@ public sealed partial class CargoSystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SellPallets(gridUid, out var goods))
|
if (!SellPallets(gridUid, station, out var goods))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var baseDistribution = CreateAccountDistribution((station, bankAccount));
|
var baseDistribution = CreateAccountDistribution((station, bankAccount));
|
||||||
@@ -267,4 +267,4 @@ public sealed partial class CargoSystem
|
|||||||
/// deleted but after the price has been calculated.
|
/// deleted but after the price has been calculated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public readonly record struct EntitySoldEvent(HashSet<EntityUid> Sold);
|
public readonly record struct EntitySoldEvent(HashSet<EntityUid> Sold, EntityUid Station);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
|
using Content.Server.Salvage.JobBoard;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Timing;
|
using Content.Shared.Timing;
|
||||||
@@ -13,6 +14,7 @@ public sealed class PriceGunSystem : SharedPriceGunSystem
|
|||||||
[Dependency] private readonly PricingSystem _pricingSystem = default!;
|
[Dependency] private readonly PricingSystem _pricingSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly CargoSystem _bountySystem = default!;
|
[Dependency] private readonly CargoSystem _bountySystem = default!;
|
||||||
|
[Dependency] private readonly SalvageJobBoardSystem _salvageJobBoard = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
|
||||||
protected override bool GetPriceOrBounty(Entity<PriceGunComponent> entity, EntityUid target, EntityUid user)
|
protected override bool GetPriceOrBounty(Entity<PriceGunComponent> entity, EntityUid target, EntityUid user)
|
||||||
@@ -24,6 +26,10 @@ public sealed class PriceGunSystem : SharedPriceGunSystem
|
|||||||
{
|
{
|
||||||
_popupSystem.PopupEntity(Loc.GetString("price-gun-bounty-complete"), user, user);
|
_popupSystem.PopupEntity(Loc.GetString("price-gun-bounty-complete"), user, user);
|
||||||
}
|
}
|
||||||
|
else if (_salvageJobBoard.FulfillsSalvageJob(target, null, out _))
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("price-gun-salvjob-complete"), user, user);
|
||||||
|
}
|
||||||
else // Otherwise appraise the price
|
else // Otherwise appraise the price
|
||||||
{
|
{
|
||||||
var price = _pricingSystem.GetPrice(target);
|
var price = _pricingSystem.GetPrice(target);
|
||||||
|
|||||||
22
Content.Server/Salvage/JobBoard/JobBoardCommands.cs
Normal file
22
Content.Server/Salvage/JobBoard/JobBoardCommands.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Content.Server.Administration;
|
||||||
|
using Content.Shared.Administration;
|
||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Toolshed;
|
||||||
|
|
||||||
|
namespace Content.Server.Salvage.JobBoard;
|
||||||
|
|
||||||
|
[ToolshedCommand, AdminCommand(AdminFlags.Debug)]
|
||||||
|
public sealed class JobBoardCommand : ToolshedCommand
|
||||||
|
{
|
||||||
|
/// <summary> Completes a bounty automatically. </summary>
|
||||||
|
[CommandImplementation("completeJob")]
|
||||||
|
public void CompleteJob([PipedArgument] EntityUid station, ProtoId<CargoBountyPrototype> job)
|
||||||
|
{
|
||||||
|
if (!TryComp<SalvageJobsDataComponent>(station, out var salvageJobData))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sys = EntityManager.System<SalvageJobBoardSystem>();
|
||||||
|
sys.TryCompleteSalvageJob((station, salvageJobData), job);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Content.Server/Salvage/JobBoard/JobBoardLabelComponent.cs
Normal file
17
Content.Server/Salvage/JobBoard/JobBoardLabelComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.Salvage.JobBoard;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marks a label for a bounty for a given salvage job board prototype.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class JobBoardLabelComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The bounty corresponding to this label.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<CargoBountyPrototype>? JobId;
|
||||||
|
}
|
||||||
294
Content.Server/Salvage/JobBoard/SalvageJobBoardSystem.cs
Normal file
294
Content.Server/Salvage/JobBoard/SalvageJobBoardSystem.cs
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Cargo.Components;
|
||||||
|
using Content.Server.Cargo.Systems;
|
||||||
|
using Content.Server.Radio.EntitySystems;
|
||||||
|
using Content.Server.Station.Systems;
|
||||||
|
using Content.Shared.Cargo.Components;
|
||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Content.Shared.Labels.EntitySystems;
|
||||||
|
using Content.Shared.Paper;
|
||||||
|
using Content.Shared.Radio;
|
||||||
|
using Content.Shared.Salvage.JobBoard;
|
||||||
|
using Robust.Server.Audio;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Salvage.JobBoard;
|
||||||
|
|
||||||
|
public sealed class SalvageJobBoardSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly AudioSystem _audio = default!;
|
||||||
|
[Dependency] private readonly CargoSystem _cargo = default!;
|
||||||
|
[Dependency] private readonly LabelSystem _label = default!;
|
||||||
|
[Dependency] private readonly PaperSystem _paper = default!;
|
||||||
|
[Dependency] private readonly RadioSystem _radio = default!;
|
||||||
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
|
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Radio channel that unlock messages are broadcast on.
|
||||||
|
/// </summary>
|
||||||
|
private static readonly ProtoId<RadioChannelPrototype> UnlockChannel = "Supply";
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
|
||||||
|
SubscribeLocalEvent<SalvageJobBoardConsoleComponent, BoundUIOpenedEvent>(OnBUIOpened);
|
||||||
|
Subs.BuiEvents<SalvageJobBoardConsoleComponent>(SalvageJobBoardUiKey.Key,
|
||||||
|
subs =>
|
||||||
|
{
|
||||||
|
subs.Event<JobBoardPrintLabelMessage>(OnPrintLabelMessage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSold(ref EntitySoldEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp<SalvageJobsDataComponent>(args.Station, out var salvageJobsData))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var sold in args.Sold)
|
||||||
|
{
|
||||||
|
if (!FulfillsSalvageJob(sold, (args.Station, salvageJobsData), out var jobId))
|
||||||
|
return;
|
||||||
|
TryCompleteSalvageJob((args.Station, salvageJobsData), jobId.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the jobs that the station can currently access.
|
||||||
|
/// </summary>
|
||||||
|
public List<ProtoId<CargoBountyPrototype>> GetAvailableJobs(Entity<SalvageJobsDataComponent> ent)
|
||||||
|
{
|
||||||
|
var outJobs = new List<ProtoId<CargoBountyPrototype>>();
|
||||||
|
var availableGroups = new HashSet<ProtoId<CargoBountyGroupPrototype>>();
|
||||||
|
|
||||||
|
var completedCount = ent.Comp.CompletedJobs.Count;
|
||||||
|
foreach (var (thresholds, rank) in ent.Comp.RankThresholds)
|
||||||
|
{
|
||||||
|
if (completedCount < thresholds)
|
||||||
|
continue;
|
||||||
|
if (rank.BountyGroup == null)
|
||||||
|
continue;
|
||||||
|
availableGroups.Add(rank.BountyGroup.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var bounty in _prototypeManager.EnumeratePrototypes<CargoBountyPrototype>())
|
||||||
|
{
|
||||||
|
if (ent.Comp.CompletedJobs.Contains(bounty))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (availableGroups.Contains(bounty.Group))
|
||||||
|
outJobs.Add(bounty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return outJobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the "progression" of a rank, expressed as on the range [0, 1]
|
||||||
|
/// </summary>
|
||||||
|
public float GetRankProgression(Entity<SalvageJobsDataComponent> ent)
|
||||||
|
{
|
||||||
|
// Need to have at least two of these.
|
||||||
|
if (ent.Comp.RankThresholds.Count <= 1)
|
||||||
|
return 1;
|
||||||
|
var completedCount = ent.Comp.CompletedJobs.Count;
|
||||||
|
|
||||||
|
for (var i = ent.Comp.RankThresholds.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var low = ent.Comp.RankThresholds.Keys.ElementAt(i);
|
||||||
|
|
||||||
|
if (completedCount < low)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// don't worry abooouuuuut it (it'll be O K !)
|
||||||
|
var high = i != ent.Comp.RankThresholds.Count - 1
|
||||||
|
? ent.Comp.RankThresholds.Keys.ElementAt(i + 1)
|
||||||
|
: _prototypeManager.EnumeratePrototypes<CargoBountyPrototype>()
|
||||||
|
.Count(p => ent.Comp.RankThresholds.Values
|
||||||
|
.Select(r => r.BountyGroup)
|
||||||
|
.Contains(p.Group));
|
||||||
|
|
||||||
|
return (completedCount - low) / (float)(high - low);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the current station is the max rank
|
||||||
|
/// </summary>
|
||||||
|
public bool IsMaxRank(Entity<SalvageJobsDataComponent> ent)
|
||||||
|
{
|
||||||
|
return GetAvailableJobs(ent).Count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current rank of the station
|
||||||
|
/// </summary>
|
||||||
|
public SalvageRankDatum GetRank(Entity<SalvageJobsDataComponent> ent)
|
||||||
|
{
|
||||||
|
if (IsMaxRank(ent))
|
||||||
|
return ent.Comp.MaxRank;
|
||||||
|
var completedCount = ent.Comp.CompletedJobs.Count;
|
||||||
|
|
||||||
|
foreach (var (threshold, rank) in ent.Comp.RankThresholds.Reverse())
|
||||||
|
{
|
||||||
|
if (completedCount < threshold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return rank;
|
||||||
|
}
|
||||||
|
// base case
|
||||||
|
return ent.Comp.RankThresholds[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ent"></param>
|
||||||
|
/// <param name="job"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool TryCompleteSalvageJob(Entity<SalvageJobsDataComponent> ent, ProtoId<CargoBountyPrototype> job)
|
||||||
|
{
|
||||||
|
if (!GetAvailableJobs(ent).Contains(job))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var jobProto = _prototypeManager.Index(job);
|
||||||
|
|
||||||
|
var oldRank = GetRank(ent);
|
||||||
|
|
||||||
|
ent.Comp.CompletedJobs.Add(job);
|
||||||
|
|
||||||
|
var newRank = GetRank(ent);
|
||||||
|
|
||||||
|
// Add reward
|
||||||
|
if (TryComp<StationBankAccountComponent>(ent, out var stationBankAccount))
|
||||||
|
{
|
||||||
|
_cargo.UpdateBankAccount(
|
||||||
|
(ent.Owner, stationBankAccount),
|
||||||
|
jobProto.Reward,
|
||||||
|
_cargo.CreateAccountDistribution((ent, stationBankAccount)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We ranked up!
|
||||||
|
if (oldRank != newRank)
|
||||||
|
{
|
||||||
|
// We need to find a computer to send the message from.
|
||||||
|
var computerQuery = EntityQueryEnumerator<SalvageJobBoardConsoleComponent>();
|
||||||
|
while (computerQuery.MoveNext(out var uid, out _))
|
||||||
|
{
|
||||||
|
var message = Loc.GetString("job-board-radio-announce", ("rank", FormattedMessage.RemoveMarkupPermissive(Loc.GetString(newRank.Title))));
|
||||||
|
_radio.SendRadioMessage(uid, message, UnlockChannel, uid, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newRank.UnlockedMarket is { } market &&
|
||||||
|
TryComp<StationCargoOrderDatabaseComponent>(ent, out var stationCargoOrder))
|
||||||
|
{
|
||||||
|
stationCargoOrder.Markets.Add(market);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var enumerator = EntityQueryEnumerator<SalvageJobBoardConsoleComponent>();
|
||||||
|
while (enumerator.MoveNext(out var consoleUid, out var console))
|
||||||
|
{
|
||||||
|
UpdateUi((consoleUid, console), ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a given entity fulfills a bounty for the station.
|
||||||
|
/// </summary>
|
||||||
|
public bool FulfillsSalvageJob(EntityUid uid, Entity<SalvageJobsDataComponent>? station, [NotNullWhen(true)] out ProtoId<CargoBountyPrototype>? job)
|
||||||
|
{
|
||||||
|
job = null;
|
||||||
|
|
||||||
|
if (!_label.TryGetLabel<JobBoardLabelComponent>(uid, out var labelEnt))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (labelEnt.Value.Comp.JobId is not { } jobId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
job = jobId;
|
||||||
|
|
||||||
|
if (station is null)
|
||||||
|
{
|
||||||
|
if (_station.GetOwningStation(uid) is not { } stationUid ||
|
||||||
|
!TryComp<SalvageJobsDataComponent>(stationUid, out var stationComp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
station = (stationUid, stationComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetAvailableJobs((station.Value, station.Value.Comp)).Contains(job.Value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
if (!_cargo.IsBountyComplete(uid, job))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBUIOpened(Entity<SalvageJobBoardConsoleComponent> ent, ref BoundUIOpenedEvent args)
|
||||||
|
{
|
||||||
|
if (args.UiKey is not SalvageJobBoardUiKey.Key)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_station.GetOwningStation(ent.Owner) is not { } station ||
|
||||||
|
!TryComp<SalvageJobsDataComponent>(station, out var jobData))
|
||||||
|
return;
|
||||||
|
|
||||||
|
UpdateUi(ent, (station, jobData));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPrintLabelMessage(Entity<SalvageJobBoardConsoleComponent> ent, ref JobBoardPrintLabelMessage args)
|
||||||
|
{
|
||||||
|
if (_timing.CurTime < ent.Comp.NextPrintTime)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_station.GetOwningStation(ent) is not { } station ||
|
||||||
|
!TryComp<SalvageJobsDataComponent>(station, out var jobsData))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_prototypeManager.TryIndex<CargoBountyPrototype>(args.JobId, out var job))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!GetAvailableJobs((station, jobsData)).Contains(args.JobId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_audio.PlayPvs(ent.Comp.PrintSound, ent);
|
||||||
|
var label = SpawnAtPosition(ent.Comp.LabelEntity, Transform(ent).Coordinates);
|
||||||
|
EnsureComp<JobBoardLabelComponent>(label).JobId = job.ID;
|
||||||
|
|
||||||
|
var target = new List<string>();
|
||||||
|
foreach (var entry in job.Entries)
|
||||||
|
{
|
||||||
|
target.Add(Loc.GetString("bounty-console-manifest-entry",
|
||||||
|
("amount", entry.Amount),
|
||||||
|
("item", Loc.GetString(entry.Name))));
|
||||||
|
}
|
||||||
|
_paper.SetContent(label, Loc.GetString("job-board-label-text", ("target", string.Join(',', target)), ("reward", job.Reward)));
|
||||||
|
|
||||||
|
ent.Comp.NextPrintTime = _timing.CurTime + ent.Comp.PrintDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateUi(Entity<SalvageJobBoardConsoleComponent> ent, Entity<SalvageJobsDataComponent> stationEnt)
|
||||||
|
{
|
||||||
|
var state = new SalvageJobBoardConsoleState(
|
||||||
|
GetRank(stationEnt).Title,
|
||||||
|
GetRankProgression(stationEnt),
|
||||||
|
GetAvailableJobs(stationEnt));
|
||||||
|
|
||||||
|
_ui.SetUiState(ent.Owner, SalvageJobBoardUiKey.Key, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
61
Content.Server/Salvage/JobBoard/SalvageJobsDataComponent.cs
Normal file
61
Content.Server/Salvage/JobBoard/SalvageJobsDataComponent.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.Salvage.JobBoard;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// holds information for a station relating to the salvage job board
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
[Access(typeof(SalvageJobBoardSystem))]
|
||||||
|
public sealed partial class SalvageJobsDataComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary relating the number of completed jobs needed to the different ranks.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SortedDictionary<int, SalvageRankDatum> RankThresholds = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The rank given when all salvage jobs are complete.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SalvageRankDatum MaxRank;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of all completed jobs in order.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public List<ProtoId<CargoBountyPrototype>> CompletedJobs = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Account where rewards are deposited.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<CargoAccountPrototype> RewardAccount = "Cargo";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds information about salvage job ranks
|
||||||
|
/// </summary>
|
||||||
|
[DataDefinition]
|
||||||
|
public partial record struct SalvageRankDatum
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The title displayed when this rank is reached
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId Title;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The bounties associated with this rank.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<CargoBountyGroupPrototype>? BountyGroup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The market that is unlocked when you reach this rank
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<CargoMarketPrototype>? UnlockedMarket;
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Cargo.BUI;
|
namespace Content.Shared.Cargo.BUI;
|
||||||
@@ -10,13 +12,15 @@ public sealed class CargoConsoleInterfaceState : BoundUserInterfaceState
|
|||||||
public int Capacity;
|
public int Capacity;
|
||||||
public NetEntity Station;
|
public NetEntity Station;
|
||||||
public List<CargoOrderData> Orders;
|
public List<CargoOrderData> Orders;
|
||||||
|
public List<ProtoId<CargoProductPrototype>> Products;
|
||||||
|
|
||||||
public CargoConsoleInterfaceState(string name, int count, int capacity, NetEntity station, List<CargoOrderData> orders)
|
public CargoConsoleInterfaceState(string name, int count, int capacity, NetEntity station, List<CargoOrderData> orders, List<ProtoId<CargoProductPrototype>> products)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Count = count;
|
Count = count;
|
||||||
Capacity = capacity;
|
Capacity = capacity;
|
||||||
Station = station;
|
Station = station;
|
||||||
Orders = orders;
|
Orders = orders;
|
||||||
|
Products = products;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,13 @@ public sealed partial class CargoOrderConsoleComponent : Component
|
|||||||
/// 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, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public List<ProtoId<CargoMarketPrototype>> AllowedGroups = new() { "market" };
|
public List<ProtoId<CargoMarketPrototype>> AllowedGroups = new()
|
||||||
|
{
|
||||||
|
"market",
|
||||||
|
"SalvageJobReward2",
|
||||||
|
"SalvageJobReward3",
|
||||||
|
"SalvageJobRewardMAX",
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Access needed to toggle the limit on this console.
|
/// Access needed to toggle the limit on this console.
|
||||||
|
|||||||
14
Content.Shared/Cargo/Prototypes/CargoBountyGroupPrototype.cs
Normal file
14
Content.Shared/Cargo/Prototypes/CargoBountyGroupPrototype.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Cargo.Prototypes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to categorize bounties for different purposes
|
||||||
|
/// </summary>
|
||||||
|
[Prototype]
|
||||||
|
public sealed partial class CargoBountyGroupPrototype : IPrototype
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[IdDataField]
|
||||||
|
public string ID { get; private set; } = default!;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared.Cargo.Prototypes;
|
namespace Content.Shared.Cargo.Prototypes;
|
||||||
|
|
||||||
@@ -39,6 +40,18 @@ public sealed partial class CargoBountyPrototype : IPrototype
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public string IdPrefix = "NT";
|
public string IdPrefix = "NT";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A group used for categorizing this bounty.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<CargoBountyGroupPrototype> Group = "StationBounty";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional sprite representing this bounty.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SpriteSpecifier? Sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataDefinition, Serializable, NetSerializable]
|
[DataDefinition, Serializable, NetSerializable]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Shared.Containers.ItemSlots;
|
using Content.Shared.Containers.ItemSlots;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Labels.Components;
|
using Content.Shared.Labels.Components;
|
||||||
@@ -141,4 +142,23 @@ public sealed partial class LabelSystem : EntitySystem
|
|||||||
if (TryComp<PaperLabelTypeComponent>(slot.Item, out var type))
|
if (TryComp<PaperLabelTypeComponent>(slot.Item, out var type))
|
||||||
_appearance.SetData(ent, PaperLabelVisuals.LabelType, type.PaperType, ent.Comp2);
|
_appearance.SetData(ent, PaperLabelVisuals.LabelType, type.PaperType, ent.Comp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a label with the specified component from the default label slot.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryGetLabel<T>(Entity<PaperLabelComponent?> ent, [NotNullWhen(true)] out Entity<T>? label) where T : Component
|
||||||
|
{
|
||||||
|
label = null;
|
||||||
|
if (!Resolve(ent, ref ent.Comp, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ent.Comp.LabelSlot.Item is not { } labelEnt)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryComp<T>(labelEnt, out var labelComp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
label = (labelEnt, labelComp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,6 +281,12 @@ public sealed class PaperSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetContent(EntityUid entity, string content)
|
||||||
|
{
|
||||||
|
if (!TryComp<PaperComponent>(entity, out var paper))
|
||||||
|
return;
|
||||||
|
SetContent((entity, paper), content);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetContent(Entity<PaperComponent> entity, string content)
|
public void SetContent(Entity<PaperComponent> entity, string content)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
|
namespace Content.Shared.Salvage.JobBoard;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to view the job board ui
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
public sealed partial class SalvageJobBoardConsoleComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A label that this computer can print out.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId LabelEntity = "PaperSalvageJobLabel";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sound made when printing occurs
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SoundSpecifier PrintSound = new SoundPathSpecifier("/Audio/Machines/printer.ogg");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time at which the console will be able to print a label again.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||||
|
public TimeSpan NextPrintTime = TimeSpan.Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time between prints.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan PrintDelay = TimeSpan.FromSeconds(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class SalvageJobBoardConsoleState : BoundUserInterfaceState
|
||||||
|
{
|
||||||
|
public string Title;
|
||||||
|
public float Progression;
|
||||||
|
|
||||||
|
public List<ProtoId<CargoBountyPrototype>> AvailableJobs;
|
||||||
|
|
||||||
|
public SalvageJobBoardConsoleState(string title, float progression, List<ProtoId<CargoBountyPrototype>> availableJobs)
|
||||||
|
{
|
||||||
|
Title = title;
|
||||||
|
Progression = progression;
|
||||||
|
AvailableJobs = availableJobs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class JobBoardPrintLabelMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public string JobId;
|
||||||
|
|
||||||
|
public JobBoardPrintLabelMessage(string jobId)
|
||||||
|
{
|
||||||
|
JobId = jobId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum SalvageJobBoardUiKey : byte
|
||||||
|
{
|
||||||
|
Key
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ bounty-item-clown-shoes = Clown shoes
|
|||||||
bounty-item-corn = Ear of corn
|
bounty-item-corn = Ear of corn
|
||||||
bounty-item-crayon = Crayon
|
bounty-item-crayon = Crayon
|
||||||
bounty-item-cuban-carp = Cuban carp
|
bounty-item-cuban-carp = Cuban carp
|
||||||
|
bounty-item-diamond = Diamond
|
||||||
bounty-item-donk-pocket = Donk-pocket
|
bounty-item-donk-pocket = Donk-pocket
|
||||||
bounty-item-donut = Donut
|
bounty-item-donut = Donut
|
||||||
bounty-item-figurine = Action figure
|
bounty-item-figurine = Action figure
|
||||||
@@ -25,6 +26,11 @@ bounty-item-lime = Lime
|
|||||||
bounty-item-lung = Lung
|
bounty-item-lung = Lung
|
||||||
bounty-item-monkey-cube = Monkey cube
|
bounty-item-monkey-cube = Monkey cube
|
||||||
bounty-item-mouse = Dead mouse
|
bounty-item-mouse = Dead mouse
|
||||||
|
bounty-item-ore-bananium = Bananium ore
|
||||||
|
bounty-item-ore-gold = Gold ore
|
||||||
|
bounty-item-ore-plasma = Plasma ore
|
||||||
|
bounty-item-ore-silver = Silver ore
|
||||||
|
bounty-item-ore-uranium = Uranium ore
|
||||||
bounty-item-pancake = Pancake
|
bounty-item-pancake = Pancake
|
||||||
bounty-item-pen = Pen
|
bounty-item-pen = Pen
|
||||||
bounty-item-percussion = Percussion instrument
|
bounty-item-percussion = Percussion instrument
|
||||||
@@ -32,6 +38,7 @@ bounty-item-pie = Pie
|
|||||||
bounty-item-prison-uniform = Prison uniform
|
bounty-item-prison-uniform = Prison uniform
|
||||||
bounty-item-radio = Radio or Headset
|
bounty-item-radio = Radio or Headset
|
||||||
bounty-item-research-disk = Research disk
|
bounty-item-research-disk = Research disk
|
||||||
|
bounty-item-scrap = Scrap
|
||||||
bounty-item-shiv = Shiv
|
bounty-item-shiv = Shiv
|
||||||
bounty-item-soap = Soap
|
bounty-item-soap = Soap
|
||||||
bounty-item-soup = Soup
|
bounty-item-soup = Soup
|
||||||
@@ -139,8 +146,4 @@ bounty-description-wine = The new librarian and the Quartermaster are falling he
|
|||||||
bounty-description-cotton-boll = A massive swarm of mothroaches ate all the paper and cloth on the station. Send us some cotton to help keep our winged crewmembers fed.
|
bounty-description-cotton-boll = A massive swarm of mothroaches ate all the paper and cloth on the station. Send us some cotton to help keep our winged crewmembers fed.
|
||||||
bounty-description-microwave-machine-board = Mr. Giggles thought it'd be funny to stick forks in all the kitchen microwaves. Help us replace them before the chefs start making clown burgers.
|
bounty-description-microwave-machine-board = Mr. Giggles thought it'd be funny to stick forks in all the kitchen microwaves. Help us replace them before the chefs start making clown burgers.
|
||||||
bounty-description-flashes = GREETINGS \[Station] WE REQUIRE 6 FLASHES DUE TO A NORMAL \[TrainingExercise] WITH SECURITY. EVERYTHING IS \[Normal].
|
bounty-description-flashes = GREETINGS \[Station] WE REQUIRE 6 FLASHES DUE TO A NORMAL \[TrainingExercise] WITH SECURITY. EVERYTHING IS \[Normal].
|
||||||
bounty-description-tooth-space-carp = Some lads from "down unda" need some teeth to make their traditional apparel. Send them a few from some space carp.
|
|
||||||
bounty-description-tooth-sharkminnow = The chef is claiming that the teeth of sharkminnows are some kind of high-quality knife. I don't know what they're on about, but they want a set. Send it to them.
|
|
||||||
bounty-description-ring = On this EXTRAORDINARY day there will be a wedding between the Gelts, but Mr. Gelt has lost the rings, send a pair of rings.
|
bounty-description-ring = On this EXTRAORDINARY day there will be a wedding between the Gelts, but Mr. Gelt has lost the rings, send a pair of rings.
|
||||||
bounty-description-remains = TWO. HIVELORD REMAINS, please.
|
|
||||||
bounty-description-plates = Our club is interested in trophies of majestic creatures such as the Goliath: send a couple of plates. The reward will come quickly.
|
|
||||||
|
|||||||
@@ -2,3 +2,4 @@
|
|||||||
price-gun-verb-text = Appraisal
|
price-gun-verb-text = Appraisal
|
||||||
price-gun-verb-message = Appraise {THE($object)}.
|
price-gun-verb-message = Appraise {THE($object)}.
|
||||||
price-gun-bounty-complete = The device confirms that the bounty contained within is completed.
|
price-gun-bounty-complete = The device confirms that the bounty contained within is completed.
|
||||||
|
price-gun-salvjob-complete = The device confirms that the salvage job contained within is completed.
|
||||||
|
|||||||
@@ -94,3 +94,5 @@ command-description-xenoartifact-averageResearch =
|
|||||||
Calculates amount of research points average generated xeno artifact will output when fully activated.
|
Calculates amount of research points average generated xeno artifact will output when fully activated.
|
||||||
command-description-xenoartifact-unlockAllNodes =
|
command-description-xenoartifact-unlockAllNodes =
|
||||||
Unlocks all nodes of artifact.
|
Unlocks all nodes of artifact.
|
||||||
|
command-description-jobboard-completeJob =
|
||||||
|
Completes a given salvage job board job for the station.
|
||||||
|
|||||||
47
Resources/Locale/en-US/salvage/job-board.ftl
Normal file
47
Resources/Locale/en-US/salvage/job-board.ftl
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
salvage-job-rank-title-0 = [color=gray]Scavenger[/color]
|
||||||
|
salvage-job-rank-title-1 = [color=white]Scrapper[/color]
|
||||||
|
salvage-job-rank-title-2 = [color=yellow]Specialist[/color]
|
||||||
|
salvage-job-rank-title-MAX = [color=gold]Supreme Salvager[/color]
|
||||||
|
|
||||||
|
job-board-radio-announce = Salvager rank increased to [bold]{$rank}[/bold]! New orders can be purchased from Cargo.
|
||||||
|
|
||||||
|
job-board-ui-window-title = Job Board
|
||||||
|
job-board-ui-label-rank = [bold]Rank:[/bold]
|
||||||
|
job-board-ui-label-items = Target: [color=red]{$item}[/color]
|
||||||
|
|
||||||
|
job-board-label-text = [head=2]Salvage Job Shipment[/head]
|
||||||
|
{"[italic]For use only on official off-station salvage shipments.[/italic]"}
|
||||||
|
|
||||||
|
{"[bold]Target:[/bold]"} {$target}
|
||||||
|
{"[bold]Reward:[/bold]"} ${$reward}
|
||||||
|
|
||||||
|
|
||||||
|
{"[italic]Shipments are subject to inspection by the Donk corporation[/italic]"}
|
||||||
|
|
||||||
|
salv-job-board-name-BountyTeethSpaceCarp = Space Carp
|
||||||
|
salv-job-board-name-BountySalvageScrap = Deep-Space Debris
|
||||||
|
salv-job-board-name-BountySalvageOreGold = Gold (Ore)
|
||||||
|
salv-job-board-name-BountySalvageOreSilver = Silver (Ore)
|
||||||
|
|
||||||
|
salv-job-board-name-BountySalvageOreUranium = Uranium (Ore)
|
||||||
|
salv-job-board-name-BountySalvageOrePlasma = Plasma (Ore)
|
||||||
|
salv-job-board-name-BountySalvageOreBananium = Bananium (Ore)
|
||||||
|
salv-job-board-name-BountyTeethSharkminnow = Sharkminnow
|
||||||
|
|
||||||
|
salv-job-board-name-BountyGoliathPlates = Goliath
|
||||||
|
salv-job-board-name-BountyHivelordRemains = Hivelord
|
||||||
|
salv-job-board-name-BountySalvageDiamond = Diamond
|
||||||
|
|
||||||
|
bounty-description-tooth-space-carp = We need you to get a sample of some space carp teeth. You can find these guys on all kinds of salvage debris. Just be careful about their bite.
|
||||||
|
bounty-description-salvage-scrap = We are researching the effects of deep space on station materials, and we need some samples. Find some old junk off of debris and bring it to us.
|
||||||
|
bounty-description-salvage-ore-gold = We are engaging in an experimental new electronics manufacturing process. Deliver us a large sum of unrefined gold ore. It can come from any source.
|
||||||
|
bounty-description-salvage-ore-silver = We are studying the material effects of silver based on the refining methods. Send us a large amount of unrefined silver ore. It can come from any source.
|
||||||
|
|
||||||
|
bounty-description-tooth-sharkminnow = We need you to get a sample of some Sharkminnow teeth. These guys are a fair bit nastier than the smaller carp you're familiar with. Take care to not let them bite you: they'll suck out your blood and heal.
|
||||||
|
bounty-description-salvage-ore-plasma = We need a shipment of plasma ore to send over to the research station. Please provide us with some so that we can continue our testing. It can come from any source.
|
||||||
|
bounty-description-salvage-ore-uranium = We need a sample of uranium ore for our ongoing experiments on nuclear devices. Be aware that while the uranium does glow slightly, it will probably not harm you. It can come from any source.
|
||||||
|
bounty-description-salvage-ore-bananium = We have an ongoing project to decode the mystifying clown genomic sequence. We believe a sample of raw bananium will help us achieve this. Note that this only comes from the rarest of deep-space asteroids.
|
||||||
|
|
||||||
|
bounty-description-remains = We need you to get a sample of a few Hivelord cores. Be aware that Hivelords can replicate infinitely if the core is not destroyed. Take care not to get overwhelmed.
|
||||||
|
bounty-description-plates = We need you to get a couple sheets of Goliath hide. These guys are pretty slow, but be careful about the tentacles: they'll grab you and pull you to the ground. You don't want to know what happens next.
|
||||||
|
bounty-description-diamond = We need you to acquire a few diamonds for some advanced fabrication. These can either be found in the mining asteroid nearby or cut out of the basilisk creature. Whichever way you want to do it, get us some.
|
||||||
@@ -749,50 +749,6 @@
|
|||||||
components:
|
components:
|
||||||
- Flash
|
- Flash
|
||||||
|
|
||||||
- type: cargoBounty
|
|
||||||
id: BountyTeethSpaceCarp
|
|
||||||
reward: 7500
|
|
||||||
description: bounty-description-tooth-space-carp
|
|
||||||
entries:
|
|
||||||
- name: bounty-item-tooth-space-carp
|
|
||||||
amount: 8
|
|
||||||
whitelist:
|
|
||||||
tags:
|
|
||||||
- ToothSpaceCarp
|
|
||||||
|
|
||||||
- type: cargoBounty
|
|
||||||
id: BountyTeethSharkminnow
|
|
||||||
reward: 15000
|
|
||||||
description: bounty-description-tooth-sharkminnow
|
|
||||||
entries:
|
|
||||||
- name: bounty-item-tooth-sharkminnow
|
|
||||||
amount: 5
|
|
||||||
whitelist:
|
|
||||||
tags:
|
|
||||||
- ToothSharkminnow
|
|
||||||
|
|
||||||
- type: cargoBounty
|
|
||||||
id: BountyPlates
|
|
||||||
reward: 20000
|
|
||||||
description: bounty-description-plates
|
|
||||||
entries:
|
|
||||||
- name: bounty-item-plates
|
|
||||||
amount: 4
|
|
||||||
whitelist:
|
|
||||||
tags:
|
|
||||||
- GoliathPlate
|
|
||||||
|
|
||||||
- type: cargoBounty
|
|
||||||
id: BountyRemains
|
|
||||||
reward: 15000
|
|
||||||
description: bounty-description-remains
|
|
||||||
entries:
|
|
||||||
- name: bounty-item-remains
|
|
||||||
amount: 2
|
|
||||||
whitelist:
|
|
||||||
tags:
|
|
||||||
- HivelordRemains
|
|
||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyRing
|
id: BountyRing
|
||||||
reward: 12500
|
reward: 12500
|
||||||
|
|||||||
11
Resources/Prototypes/Catalog/Bounties/groups.yml
Normal file
11
Resources/Prototypes/Catalog/Bounties/groups.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
- type: cargoBountyGroup
|
||||||
|
id: StationBounty
|
||||||
|
|
||||||
|
- type: cargoBountyGroup
|
||||||
|
id: SalvageJobTier1
|
||||||
|
|
||||||
|
- type: cargoBountyGroup
|
||||||
|
id: SalvageJobTier2
|
||||||
|
|
||||||
|
- type: cargoBountyGroup
|
||||||
|
id: SalvageJobTier3
|
||||||
173
Resources/Prototypes/Catalog/Bounties/salvage_jobs.yml
Normal file
173
Resources/Prototypes/Catalog/Bounties/salvage_jobs.yml
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
# NOTE: if you add any bounties to this, you need to go to Resources/Prototypes/Entities/Stations/base.yml and adjust the thresholds on BaseStationSalvageJobs.
|
||||||
|
# If you don't do this, you won't raise the limit for completing a given rank and may throw off some balance.
|
||||||
|
|
||||||
|
# Tier 1
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountyTeethSpaceCarp
|
||||||
|
reward: 7500
|
||||||
|
description: bounty-description-tooth-space-carp
|
||||||
|
group: SalvageJobTier1
|
||||||
|
sprite:
|
||||||
|
sprite: Mobs/Aliens/Carps/space.rsi
|
||||||
|
state: icon
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-tooth-space-carp
|
||||||
|
amount: 10
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- ToothSpaceCarp
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountySalvageScrap
|
||||||
|
reward: 7500
|
||||||
|
description: bounty-description-salvage-scrap
|
||||||
|
group: SalvageJobTier1
|
||||||
|
sprite:
|
||||||
|
sprite: Objects/Materials/Scrap/generic.rsi
|
||||||
|
state: metal-1
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-scrap
|
||||||
|
amount: 15
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- SalvageScrap
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountySalvageOreGold
|
||||||
|
reward: 7500
|
||||||
|
description: bounty-description-salvage-ore-gold
|
||||||
|
group: SalvageJobTier1
|
||||||
|
sprite:
|
||||||
|
sprite: Objects/Materials/ore.rsi
|
||||||
|
state: gold
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-ore-gold
|
||||||
|
amount: 90
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- OreGold
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountySalvageOreSilver
|
||||||
|
reward: 7500
|
||||||
|
description: bounty-description-salvage-ore-silver
|
||||||
|
group: SalvageJobTier1
|
||||||
|
sprite:
|
||||||
|
sprite: Objects/Materials/ore.rsi
|
||||||
|
state: silver
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-ore-silver
|
||||||
|
amount: 90
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- OreSilver
|
||||||
|
|
||||||
|
# Tier 2
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountyTeethSharkminnow
|
||||||
|
reward: 12500
|
||||||
|
description: bounty-description-tooth-sharkminnow
|
||||||
|
group: SalvageJobTier2
|
||||||
|
sprite:
|
||||||
|
sprite: Mobs/Aliens/Carps/sharkminnow.rsi
|
||||||
|
state: icon
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-tooth-sharkminnow
|
||||||
|
amount: 3
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- ToothSharkminnow
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountySalvageOrePlasma
|
||||||
|
reward: 12500
|
||||||
|
description: bounty-description-salvage-ore-plasma
|
||||||
|
group: SalvageJobTier2
|
||||||
|
sprite:
|
||||||
|
sprite: Objects/Materials/ore.rsi
|
||||||
|
state: plasma
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-ore-plasma
|
||||||
|
amount: 45
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- OrePlasma
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountySalvageOreUranium
|
||||||
|
reward: 12500
|
||||||
|
description: bounty-description-salvage-ore-uranium
|
||||||
|
group: SalvageJobTier2
|
||||||
|
sprite:
|
||||||
|
sprite: Objects/Materials/ore.rsi
|
||||||
|
state: uranium
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-ore-uranium
|
||||||
|
amount: 45
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- OreUranium
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountySalvageOreBananium
|
||||||
|
reward: 12500
|
||||||
|
description: bounty-description-salvage-ore-bananium
|
||||||
|
group: SalvageJobTier2
|
||||||
|
sprite:
|
||||||
|
sprite: Objects/Materials/ore.rsi
|
||||||
|
state: bananium
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-ore-bananium
|
||||||
|
amount: 30
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- OreBananium
|
||||||
|
|
||||||
|
# Tier 3
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountyGoliathPlates
|
||||||
|
reward: 20000
|
||||||
|
description: bounty-description-plates
|
||||||
|
group: SalvageJobTier3
|
||||||
|
sprite:
|
||||||
|
sprite: Mobs/Aliens/Asteroid/goliath.rsi
|
||||||
|
state: goliath
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-plates
|
||||||
|
amount: 6
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- GoliathPlate
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountyHivelordRemains
|
||||||
|
reward: 20000
|
||||||
|
description: bounty-description-remains
|
||||||
|
group: SalvageJobTier3
|
||||||
|
sprite:
|
||||||
|
sprite: Mobs/Aliens/Asteroid/hivelord.rsi
|
||||||
|
state: hivelord
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-remains
|
||||||
|
amount: 3
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- HivelordRemains
|
||||||
|
|
||||||
|
- type: cargoBounty
|
||||||
|
id: BountySalvageDiamond
|
||||||
|
reward: 20000
|
||||||
|
description: bounty-description-diamond
|
||||||
|
group: SalvageJobTier3
|
||||||
|
sprite:
|
||||||
|
sprite: Objects/Materials/materials.rsi
|
||||||
|
state: diamond
|
||||||
|
entries:
|
||||||
|
- name: bounty-item-diamond
|
||||||
|
amount: 3
|
||||||
|
whitelist:
|
||||||
|
tags:
|
||||||
|
- Diamond
|
||||||
@@ -1,2 +1,11 @@
|
|||||||
- type: cargoMarket
|
- type: cargoMarket
|
||||||
id: market
|
id: market
|
||||||
|
|
||||||
|
- type: cargoMarket
|
||||||
|
id: SalvageJobReward2
|
||||||
|
|
||||||
|
- type: cargoMarket
|
||||||
|
id: SalvageJobReward3
|
||||||
|
|
||||||
|
- type: cargoMarket
|
||||||
|
id: SalvageJobRewardMAX
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
- id: CargoSaleComputerCircuitboard
|
- id: CargoSaleComputerCircuitboard
|
||||||
- id: CargoShuttleConsoleCircuitboard
|
- id: CargoShuttleConsoleCircuitboard
|
||||||
- id: SalvageMagnetMachineCircuitboard
|
- id: SalvageMagnetMachineCircuitboard
|
||||||
|
- id: SalvageJobBoardComputerCircuitboard
|
||||||
- id: CigPackGreen
|
- id: CigPackGreen
|
||||||
prob: 0.50
|
prob: 0.50
|
||||||
- id: ClothingHeadsetAltCargo
|
- id: ClothingHeadsetAltCargo
|
||||||
|
|||||||
@@ -243,8 +243,7 @@
|
|||||||
- id: FoodMeatFish
|
- id: FoodMeatFish
|
||||||
amount: 4
|
amount: 4
|
||||||
- id: MaterialToothSharkminnow1
|
- id: MaterialToothSharkminnow1
|
||||||
amount: 1
|
amount: 3
|
||||||
maxAmount: 3
|
|
||||||
- type: MeleeWeapon
|
- type: MeleeWeapon
|
||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
|
|||||||
@@ -198,6 +198,17 @@
|
|||||||
prototype: ComputerCargoBounty
|
prototype: ComputerCargoBounty
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerCircuitboard
|
||||||
|
id: SalvageJobBoardComputerCircuitboard
|
||||||
|
name: salvage job board computer board
|
||||||
|
description: A computer printed circuit board for a salvage job board computer.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: cpu_supply
|
||||||
|
- type: ComputerBoard
|
||||||
|
prototype: ComputerSalvageJobBoard
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseComputerCircuitboard
|
parent: BaseComputerCircuitboard
|
||||||
id: SalvageExpeditionsComputerCircuitboard
|
id: SalvageExpeditionsComputerCircuitboard
|
||||||
|
|||||||
@@ -389,6 +389,10 @@
|
|||||||
- type: PhysicalComposition
|
- type: PhysicalComposition
|
||||||
materialComposition:
|
materialComposition:
|
||||||
Diamond: 100
|
Diamond: 100
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- RawMaterial
|
||||||
|
- Diamond
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: MaterialDiamond
|
parent: MaterialDiamond
|
||||||
|
|||||||
@@ -48,6 +48,10 @@
|
|||||||
Quantity: 10
|
Quantity: 10
|
||||||
- type: Item
|
- type: Item
|
||||||
heldPrefix: gold
|
heldPrefix: gold
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Ore
|
||||||
|
- OreGold
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: GoldOre
|
parent: GoldOre
|
||||||
@@ -152,6 +156,10 @@
|
|||||||
Quantity: 10
|
Quantity: 10
|
||||||
- type: Item
|
- type: Item
|
||||||
heldPrefix: plasma
|
heldPrefix: plasma
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Ore
|
||||||
|
- OrePlasma
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: PlasmaOre
|
parent: PlasmaOre
|
||||||
@@ -185,6 +193,10 @@
|
|||||||
Quantity: 10
|
Quantity: 10
|
||||||
- type: Item
|
- type: Item
|
||||||
heldPrefix: silver
|
heldPrefix: silver
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Ore
|
||||||
|
- OreSilver
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: SilverOre
|
parent: SilverOre
|
||||||
@@ -259,6 +271,10 @@
|
|||||||
canReact: false
|
canReact: false
|
||||||
- type: Item
|
- type: Item
|
||||||
heldPrefix: uranium
|
heldPrefix: uranium
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Ore
|
||||||
|
- OreUranium
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: UraniumOre
|
parent: UraniumOre
|
||||||
@@ -301,6 +317,10 @@
|
|||||||
Quantity: 5
|
Quantity: 5
|
||||||
- type: Item
|
- type: Item
|
||||||
heldPrefix: bananium
|
heldPrefix: bananium
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Ore
|
||||||
|
- OreBananium
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BananiumOre
|
parent: BananiumOre
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Recyclable
|
- Recyclable
|
||||||
|
- SalvageScrap
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseStructure
|
parent: BaseStructure
|
||||||
|
|||||||
@@ -253,6 +253,41 @@
|
|||||||
- CargoBounties
|
- CargoBounties
|
||||||
- Cargo
|
- Cargo
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: PaperSalvageJobLabel
|
||||||
|
parent: PaperCargoInvoice
|
||||||
|
name: salvage job shipment label
|
||||||
|
description: A paper label designating a crate as containing a shipment to fulfill a salvage job. Selling a crate with this will fulfill the job.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- state: paper
|
||||||
|
color: "#f7e574"
|
||||||
|
- state: paper_words
|
||||||
|
map: ["enum.PaperVisualLayers.Writing"]
|
||||||
|
color: "#f7e574"
|
||||||
|
visible: false
|
||||||
|
- state: paper_stamp-generic
|
||||||
|
map: ["enum.PaperVisualLayers.Stamp"]
|
||||||
|
visible: false
|
||||||
|
- type: PaperLabelType
|
||||||
|
paperType: Bounty
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Document
|
||||||
|
- Trash
|
||||||
|
- Paper
|
||||||
|
- type: PaperVisuals
|
||||||
|
backgroundImagePath: "/Textures/Interface/Paper/paper_background_default.svg.96dpi.png"
|
||||||
|
contentImagePath: "/Textures/Interface/Paper/paper_content_lined.svg.96dpi.png"
|
||||||
|
backgroundModulate: "#f7e574"
|
||||||
|
contentImageModulate: "#f7e574"
|
||||||
|
backgroundPatchMargin: 16.0, 16.0, 16.0, 16.0
|
||||||
|
contentMargin: 16.0, 16.0, 16.0, 16.0
|
||||||
|
- type: JobBoardLabel
|
||||||
|
- type: StaticPrice #infinitely printable
|
||||||
|
price: 0
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: character sheet
|
name: character sheet
|
||||||
parent: Paper
|
parent: Paper
|
||||||
|
|||||||
@@ -144,6 +144,27 @@
|
|||||||
components:
|
components:
|
||||||
- type: SalvageMagnetData
|
- type: SalvageMagnetData
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: BaseStationSalvageJobs
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: SalvageJobsData
|
||||||
|
rankThresholds:
|
||||||
|
0:
|
||||||
|
title: salvage-job-rank-title-0
|
||||||
|
bountyGroup: SalvageJobTier1
|
||||||
|
3:
|
||||||
|
title: salvage-job-rank-title-1
|
||||||
|
bountyGroup: SalvageJobTier2
|
||||||
|
unlockedMarket: SalvageJobReward2
|
||||||
|
6:
|
||||||
|
title: salvage-job-rank-title-2
|
||||||
|
bountyGroup: SalvageJobTier3
|
||||||
|
unlockedMarket: SalvageJobReward3
|
||||||
|
maxRank:
|
||||||
|
title: salvage-job-rank-title-MAX
|
||||||
|
unlockedMarket: SalvageJobRewardMAX
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: BaseStationSiliconLawCrewsimov
|
id: BaseStationSiliconLawCrewsimov
|
||||||
abstract: true
|
abstract: true
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
- BaseStationAlertLevels
|
- BaseStationAlertLevels
|
||||||
- BaseStationMagnet
|
- BaseStationMagnet
|
||||||
- BaseStationExpeditions
|
- BaseStationExpeditions
|
||||||
|
- BaseStationSalvageJobs
|
||||||
- BaseStationSiliconLawCrewsimov
|
- BaseStationSiliconLawCrewsimov
|
||||||
- BaseStationAllEventsEligible
|
- BaseStationAllEventsEligible
|
||||||
- BaseStationNanotrasen
|
- BaseStationNanotrasen
|
||||||
|
|||||||
@@ -1202,6 +1202,42 @@
|
|||||||
guides:
|
guides:
|
||||||
- Cloning
|
- Cloning
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseComputerAiAccess
|
||||||
|
id: ComputerSalvageJobBoard
|
||||||
|
name: salvage job board
|
||||||
|
description: Console for accessing salvage jobs, if you're tough enough.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- map: ["computerLayerBody"]
|
||||||
|
state: computer
|
||||||
|
- map: ["computerLayerKeyboard"]
|
||||||
|
state: generic_keyboard
|
||||||
|
- map: ["computerLayerScreen"]
|
||||||
|
state: salvjob # givin em a salvjob like hawk tuah
|
||||||
|
- map: ["computerLayerKeys"]
|
||||||
|
state: generic_keys
|
||||||
|
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
|
||||||
|
state: generic_panel_open
|
||||||
|
- type: SalvageJobBoardConsole
|
||||||
|
- type: ActivatableUI
|
||||||
|
key: enum.SalvageJobBoardUiKey.Key
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
enum.SalvageJobBoardUiKey.Key:
|
||||||
|
type: SalvageJobBoardBoundUserInterface
|
||||||
|
enum.WiresUiKey.Key:
|
||||||
|
type: WiresBoundUserInterface
|
||||||
|
- type: ActiveRadio
|
||||||
|
channels: [ Supply ]
|
||||||
|
- type: Computer
|
||||||
|
board: SalvageJobBoardComputerCircuitboard
|
||||||
|
- type: PointLight
|
||||||
|
radius: 1.5
|
||||||
|
energy: 1.6
|
||||||
|
color: "#b89f25"
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ComputerSalvageExpedition
|
id: ComputerSalvageExpedition
|
||||||
parent: BaseComputerAiAccess
|
parent: BaseComputerAiAccess
|
||||||
|
|||||||
@@ -443,6 +443,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: Diagonal
|
id: Diagonal
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: Diamond
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: Dice
|
id: Dice
|
||||||
|
|
||||||
@@ -985,6 +988,21 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: Ore
|
id: Ore
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: OreBananium
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: OreGold
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: OrePlasma
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: OreSilver
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: OreUranium
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: Packet
|
id: Packet
|
||||||
|
|
||||||
@@ -1163,6 +1181,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: SalvageExperiment
|
id: SalvageExperiment
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: SalvageScrap
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: Scarf
|
id: Scarf
|
||||||
|
|
||||||
|
|||||||
@@ -1672,6 +1672,44 @@
|
|||||||
"name": "robot",
|
"name": "robot",
|
||||||
"directions": 4
|
"directions": 4
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "salvjob",
|
||||||
|
"directions": 4,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "security",
|
"name": "security",
|
||||||
"directions": 4,
|
"directions": 4,
|
||||||
|
|||||||
BIN
Resources/Textures/Structures/Machines/computers.rsi/salvjob.png
Normal file
BIN
Resources/Textures/Structures/Machines/computers.rsi/salvjob.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Reference in New Issue
Block a user