Chill bounties + fixes (#23411)
* Chill bounties + fixes * localize * fix arbitage
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
using Content.Client.Cargo.UI;
|
using Content.Client.Cargo.UI;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Client.Cargo.BUI;
|
namespace Content.Client.Cargo.BUI;
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,13 @@
|
|||||||
HorizontalExpand="True">
|
HorizontalExpand="True">
|
||||||
<BoxContainer Orientation="Horizontal">
|
<BoxContainer Orientation="Horizontal">
|
||||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||||
<RichTextLabel Name="TimeLabel"/>
|
|
||||||
<RichTextLabel Name="RewardLabel"/>
|
<RichTextLabel Name="RewardLabel"/>
|
||||||
<RichTextLabel Name="ManifestLabel"/>
|
<RichTextLabel Name="ManifestLabel"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<Control MinWidth="10"/>
|
<Control MinWidth="10"/>
|
||||||
<BoxContainer Orientation="Vertical" MinWidth="120">
|
<BoxContainer Orientation="Vertical" MinWidth="120">
|
||||||
<Button Name="PrintButton" Text="{Loc 'bounty-console-label-button-text'}" HorizontalExpand="False" HorizontalAlignment="Right"/>
|
<Button Name="PrintButton" Text="{Loc 'bounty-console-label-button-text'}" HorizontalExpand="False" HorizontalAlignment="Right"/>
|
||||||
<Label Name="IdLabel" HorizontalAlignment="Right" Margin="0 0 5 0"/>
|
<RichTextLabel Name="IdLabel" HorizontalAlignment="Right" Margin="0 0 5 0"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
<customControls:HSeparator Margin="5 10 5 10"/>
|
<customControls:HSeparator Margin="5 10 5 10"/>
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ public sealed partial class BountyEntry : BoxContainer
|
|||||||
if (!_prototype.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var bountyPrototype))
|
if (!_prototype.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var bountyPrototype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EndTime = bounty.EndTime;
|
|
||||||
|
|
||||||
var items = new List<string>();
|
var items = new List<string>();
|
||||||
foreach (var entry in bountyPrototype.Entries)
|
foreach (var entry in bountyPrototype.Entries)
|
||||||
{
|
{
|
||||||
@@ -39,16 +37,8 @@ public sealed partial class BountyEntry : BoxContainer
|
|||||||
ManifestLabel.SetMarkup(Loc.GetString("bounty-console-manifest-label", ("item", string.Join(", ", items))));
|
ManifestLabel.SetMarkup(Loc.GetString("bounty-console-manifest-label", ("item", string.Join(", ", items))));
|
||||||
RewardLabel.SetMarkup(Loc.GetString("bounty-console-reward-label", ("reward", bountyPrototype.Reward)));
|
RewardLabel.SetMarkup(Loc.GetString("bounty-console-reward-label", ("reward", bountyPrototype.Reward)));
|
||||||
DescriptionLabel.SetMarkup(Loc.GetString("bounty-console-description-label", ("description", Loc.GetString(bountyPrototype.Description))));
|
DescriptionLabel.SetMarkup(Loc.GetString("bounty-console-description-label", ("description", Loc.GetString(bountyPrototype.Description))));
|
||||||
IdLabel.Text = Loc.GetString("bounty-console-id-label", ("id", bounty.Id));
|
IdLabel.SetMarkup(Loc.GetString("bounty-console-id-label", ("id", bounty.Id)));
|
||||||
|
|
||||||
PrintButton.OnPressed += _ => OnButtonPressed?.Invoke();
|
PrintButton.OnPressed += _ => OnButtonPressed?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void FrameUpdate(FrameEventArgs args)
|
|
||||||
{
|
|
||||||
base.FrameUpdate(args);
|
|
||||||
|
|
||||||
var remaining = TimeSpan.FromSeconds(Math.Max((EndTime - _timing.CurTime).TotalSeconds, 0));
|
|
||||||
TimeLabel.SetMarkup(Loc.GetString("bounty-console-time-label", ("time", remaining.ToString("mm':'ss"))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Content.Client.Cargo.UI;
|
|||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public sealed partial class CargoBountyMenu : FancyWindow
|
public sealed partial class CargoBountyMenu : FancyWindow
|
||||||
{
|
{
|
||||||
public Action<int>? OnLabelButtonPressed;
|
public Action<string>? OnLabelButtonPressed;
|
||||||
|
|
||||||
public CargoBountyMenu()
|
public CargoBountyMenu()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public sealed class CargoTest
|
|||||||
foreach (var bounty in bounties)
|
foreach (var bounty in bounties)
|
||||||
{
|
{
|
||||||
if (cargo.IsBountyComplete(ent, bounty))
|
if (cargo.IsBountyComplete(ent, bounty))
|
||||||
Assert.That(proto.PointCost, Is.GreaterThan(bounty.Reward), $"Found arbitrage on {bounty.ID} cargo bounty! Product {proto.ID} costs {proto.PointCost} but fulfills bounty {bounty.ID} with reward {bounty.Reward}!");
|
Assert.That(proto.PointCost, Is.GreaterThanOrEqualTo(bounty.Reward), $"Found arbitrage on {bounty.ID} cargo bounty! Product {proto.ID} costs {proto.PointCost} but fulfills bounty {bounty.ID} with reward {bounty.Reward}!");
|
||||||
}
|
}
|
||||||
|
|
||||||
entManager.DeleteEntity(ent);
|
entManager.DeleteEntity(ent);
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ public sealed partial class CargoBountyLabelComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID for the bounty this label corresponds to.
|
/// The ID for the bounty this label corresponds to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("id"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
public int Id;
|
public string Id = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to prevent recursion in calculating the price.
|
/// Used to prevent recursion in calculating the price.
|
||||||
|
|||||||
@@ -11,37 +11,25 @@ public sealed partial class StationCargoBountyDatabaseComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum amount of bounties a station can have.
|
/// Maximum amount of bounties a station can have.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("maxBounties"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
public int MaxBounties = 3;
|
public int MaxBounties = 5;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of all the bounties currently active for a station.
|
/// A list of all the bounties currently active for a station.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("bounties"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
public List<CargoBountyData> Bounties = new();
|
public List<CargoBountyData> Bounties = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to determine unique order IDs
|
/// Used to determine unique order IDs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("totalBounties")]
|
[DataField]
|
||||||
public int TotalBounties;
|
public int TotalBounties;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The minimum amount of time the bounty lasts before being removed.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("minBountyTime"), ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public float MinBountyTime = 600f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum amount of time the bounty lasts before being removed.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("maxBountyTime"), ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public float MaxBountyTime = 905f;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of bounty IDs that have been checked this tick.
|
/// A list of bounty IDs that have been checked this tick.
|
||||||
/// Used to prevent multiplying bounty prices.
|
/// Used to prevent multiplying bounty prices.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public HashSet<int> CheckedBounties = new();
|
public HashSet<string> CheckedBounties = new();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,16 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Cargo.Components;
|
using Content.Server.Cargo.Components;
|
||||||
using Content.Server.Labels;
|
using Content.Server.Labels;
|
||||||
|
using Content.Server.NameIdentifier;
|
||||||
using Content.Server.Paper;
|
using Content.Server.Paper;
|
||||||
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 Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.NameIdentifier;
|
||||||
|
using Content.Shared.Stacks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.Containers;
|
using Robust.Server.Containers;
|
||||||
using Robust.Shared.Collections;
|
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
@@ -19,6 +21,14 @@ namespace Content.Server.Cargo.Systems;
|
|||||||
public sealed partial class CargoSystem
|
public sealed partial class CargoSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly ContainerSystem _container = default!;
|
[Dependency] private readonly ContainerSystem _container = default!;
|
||||||
|
[Dependency] private readonly NameIdentifierSystem _nameIdentifier = default!;
|
||||||
|
|
||||||
|
[ValidatePrototypeId<NameIdentifierGroupPrototype>]
|
||||||
|
private const string BountyNameIdentifierGroup = "Bounty";
|
||||||
|
|
||||||
|
private EntityQuery<StackComponent> _stackQuery;
|
||||||
|
private EntityQuery<ContainerManagerComponent> _containerQuery;
|
||||||
|
private EntityQuery<CargoBountyLabelComponent> _bountyLabelQuery;
|
||||||
|
|
||||||
private void InitializeBounty()
|
private void InitializeBounty()
|
||||||
{
|
{
|
||||||
@@ -27,6 +37,10 @@ public sealed partial class CargoSystem
|
|||||||
SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
|
SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
|
||||||
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
|
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
|
||||||
SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
|
||||||
|
|
||||||
|
_stackQuery = GetEntityQuery<StackComponent>();
|
||||||
|
_containerQuery = GetEntityQuery<ContainerManagerComponent>();
|
||||||
|
_bountyLabelQuery = GetEntityQuery<CargoBountyLabelComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBountyConsoleOpened(EntityUid uid, CargoBountyConsoleComponent component, BoundUIOpenedEvent args)
|
private void OnBountyConsoleOpened(EntityUid uid, CargoBountyConsoleComponent component, BoundUIOpenedEvent args)
|
||||||
@@ -98,7 +112,7 @@ public sealed partial class CargoSystem
|
|||||||
if (!TryGetBountyFromId(station, component.Id, out var bounty, database))
|
if (!TryGetBountyFromId(station, component.Id, out var bounty, database))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_protoMan.TryIndex<CargoBountyPrototype>(bounty.Value.Bounty, out var bountyPrototype) ||
|
if (!_protoMan.TryIndex(bounty.Value.Bounty, out var bountyPrototype) ||
|
||||||
!IsBountyComplete(container.Owner, bountyPrototype))
|
!IsBountyComplete(container.Owner, bountyPrototype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -112,25 +126,15 @@ public sealed partial class CargoSystem
|
|||||||
|
|
||||||
private void OnSold(ref EntitySoldEvent args)
|
private void OnSold(ref EntitySoldEvent args)
|
||||||
{
|
{
|
||||||
var containerQuery = GetEntityQuery<ContainerManagerComponent>();
|
|
||||||
var labelQuery = GetEntityQuery<CargoBountyLabelComponent>();
|
|
||||||
foreach (var sold in args.Sold)
|
foreach (var sold in args.Sold)
|
||||||
{
|
{
|
||||||
if (!containerQuery.TryGetComponent(sold, out var containerMan))
|
if (!TryGetBountyLabel(sold, out _, out var component))
|
||||||
continue;
|
|
||||||
|
|
||||||
// make sure this label was actually applied to a crate.
|
|
||||||
if (!_container.TryGetContainer(sold, LabelSystem.ContainerName, out var container, containerMan))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (container.ContainedEntities.FirstOrNull() is not { } label ||
|
|
||||||
!labelQuery.TryGetComponent(label, out var component))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!TryGetBountyFromId(args.Station, component.Id, out var bounty))
|
if (!TryGetBountyFromId(args.Station, component.Id, out var bounty))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!IsBountyComplete(container.Owner, bounty.Value))
|
if (!IsBountyComplete(sold, bounty.Value))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TryRemoveBounty(args.Station, bounty.Value);
|
TryRemoveBounty(args.Station, bounty.Value);
|
||||||
@@ -139,6 +143,28 @@ public sealed partial class CargoSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryGetBountyLabel(EntityUid uid,
|
||||||
|
[NotNullWhen(true)] out EntityUid? labelEnt,
|
||||||
|
[NotNullWhen(true)] out CargoBountyLabelComponent? labelComp)
|
||||||
|
{
|
||||||
|
labelEnt = null;
|
||||||
|
labelComp = null;
|
||||||
|
if (!_containerQuery.TryGetComponent(uid, out var containerMan))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// make sure this label was actually applied to a crate.
|
||||||
|
if (!_container.TryGetContainer(uid, LabelSystem.ContainerName, out var container, containerMan))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (container.ContainedEntities.FirstOrNull() is not { } label ||
|
||||||
|
!_bountyLabelQuery.TryGetComponent(label, out var component))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
labelEnt = label;
|
||||||
|
labelComp = component;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnMapInit(EntityUid uid, StationCargoBountyDatabaseComponent component, MapInitEvent args)
|
private void OnMapInit(EntityUid uid, StationCargoBountyDatabaseComponent component, MapInitEvent args)
|
||||||
{
|
{
|
||||||
FillBountyDatabase(uid, component);
|
FillBountyDatabase(uid, component);
|
||||||
@@ -161,12 +187,53 @@ public sealed partial class CargoSystem
|
|||||||
UpdateBountyConsoles();
|
UpdateBountyConsoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RerollBountyDatabase(Entity<StationCargoBountyDatabaseComponent?> entity)
|
||||||
|
{
|
||||||
|
if (!Resolve(entity, ref entity.Comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
entity.Comp.Bounties.Clear();
|
||||||
|
FillBountyDatabase(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsBountyComplete(EntityUid container, EntityUid? station, out HashSet<EntityUid> bountyEntities)
|
||||||
|
{
|
||||||
|
if (!TryGetBountyLabel(container, out _, out var component))
|
||||||
|
{
|
||||||
|
bountyEntities = new();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
station ??= _station.GetOwningStation(container);
|
||||||
|
if (station == null)
|
||||||
|
{
|
||||||
|
bountyEntities = new();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryGetBountyFromId(station.Value, component.Id, out var bounty))
|
||||||
|
{
|
||||||
|
bountyEntities = new();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsBountyComplete(container, bounty.Value, out bountyEntities);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsBountyComplete(EntityUid container, CargoBountyData data)
|
public bool IsBountyComplete(EntityUid container, CargoBountyData data)
|
||||||
{
|
{
|
||||||
if (!_protoMan.TryIndex<CargoBountyPrototype>(data.Bounty, out var proto))
|
return IsBountyComplete(container, data, out _);
|
||||||
return false;
|
}
|
||||||
|
|
||||||
return IsBountyComplete(container, proto.Entries);
|
public bool IsBountyComplete(EntityUid container, CargoBountyData data, out HashSet<EntityUid> bountyEntities)
|
||||||
|
{
|
||||||
|
if (!_protoMan.TryIndex(data.Bounty, out var proto))
|
||||||
|
{
|
||||||
|
bountyEntities = new();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsBountyComplete(container, proto.Entries, out bountyEntities);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsBountyComplete(EntityUid container, string id)
|
public bool IsBountyComplete(EntityUid container, string id)
|
||||||
@@ -184,26 +251,18 @@ public sealed partial class CargoSystem
|
|||||||
|
|
||||||
public bool IsBountyComplete(EntityUid container, IEnumerable<CargoBountyItemEntry> entries)
|
public bool IsBountyComplete(EntityUid container, IEnumerable<CargoBountyItemEntry> entries)
|
||||||
{
|
{
|
||||||
var contained = new HashSet<EntityUid>();
|
return IsBountyComplete(container, entries, out _);
|
||||||
if (TryComp<ContainerManagerComponent>(container, out var containers))
|
|
||||||
{
|
|
||||||
foreach (var con in containers.Containers.Values)
|
|
||||||
{
|
|
||||||
if (con.ID == LabelSystem.ContainerName)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (var ent in con.ContainedEntities)
|
|
||||||
{
|
|
||||||
contained.Add(ent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return IsBountyComplete(contained, entries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsBountyComplete(HashSet<EntityUid> entities, IEnumerable<CargoBountyItemEntry> entries)
|
public bool IsBountyComplete(EntityUid container, IEnumerable<CargoBountyItemEntry> entries, out HashSet<EntityUid> bountyEntities)
|
||||||
{
|
{
|
||||||
|
return IsBountyComplete(GetBountyEntities(container), entries, out bountyEntities);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsBountyComplete(HashSet<EntityUid> entities, IEnumerable<CargoBountyItemEntry> entries, out HashSet<EntityUid> bountyEntities)
|
||||||
|
{
|
||||||
|
bountyEntities = new();
|
||||||
|
|
||||||
foreach (var entry in entries)
|
foreach (var entry in entries)
|
||||||
{
|
{
|
||||||
var count = 0;
|
var count = 0;
|
||||||
@@ -215,7 +274,8 @@ public sealed partial class CargoSystem
|
|||||||
{
|
{
|
||||||
if (!entry.Whitelist.IsValid(entity, EntityManager))
|
if (!entry.Whitelist.IsValid(entity, EntityManager))
|
||||||
continue;
|
continue;
|
||||||
count++;
|
|
||||||
|
count += _stackQuery.CompOrNull(entity)?.Count ?? 1;
|
||||||
temp.Add(entity);
|
temp.Add(entity);
|
||||||
|
|
||||||
if (count >= entry.Amount)
|
if (count >= entry.Amount)
|
||||||
@@ -228,17 +288,58 @@ public sealed partial class CargoSystem
|
|||||||
foreach (var ent in temp)
|
foreach (var ent in temp)
|
||||||
{
|
{
|
||||||
entities.Remove(ent);
|
entities.Remove(ent);
|
||||||
|
bountyEntities.Add(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HashSet<EntityUid> GetBountyEntities(EntityUid uid)
|
||||||
|
{
|
||||||
|
var entities = new HashSet<EntityUid>
|
||||||
|
{
|
||||||
|
uid
|
||||||
|
};
|
||||||
|
if (!TryComp<ContainerManagerComponent>(uid, out var containers))
|
||||||
|
return entities;
|
||||||
|
|
||||||
|
foreach (var container in containers.Containers.Values)
|
||||||
|
{
|
||||||
|
foreach (var ent in container.ContainedEntities)
|
||||||
|
{
|
||||||
|
if (_bountyLabelQuery.HasComponent(ent))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var children = GetBountyEntities(ent);
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
entities.Add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool TryAddBounty(EntityUid uid, StationCargoBountyDatabaseComponent? component = null)
|
public bool TryAddBounty(EntityUid uid, StationCargoBountyDatabaseComponent? component = null)
|
||||||
{
|
{
|
||||||
|
if (!Resolve(uid, ref component))
|
||||||
|
return false;
|
||||||
|
|
||||||
// todo: consider making the cargo bounties weighted.
|
// todo: consider making the cargo bounties weighted.
|
||||||
var bounty = _random.Pick(_protoMan.EnumeratePrototypes<CargoBountyPrototype>().ToList());
|
var allBounties = _protoMan.EnumeratePrototypes<CargoBountyPrototype>().ToList();
|
||||||
|
var filteredBounties = new List<CargoBountyPrototype>();
|
||||||
|
foreach (var proto in allBounties)
|
||||||
|
{
|
||||||
|
if (component.Bounties.Any(b => b.Bounty == proto.ID))
|
||||||
|
continue;
|
||||||
|
filteredBounties.Add(proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pool = filteredBounties.Count == 0 ? allBounties : filteredBounties;
|
||||||
|
var bounty = _random.Pick(pool);
|
||||||
return TryAddBounty(uid, bounty, component);
|
return TryAddBounty(uid, bounty, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,17 +362,15 @@ public sealed partial class CargoSystem
|
|||||||
if (component.Bounties.Count >= component.MaxBounties)
|
if (component.Bounties.Count >= component.MaxBounties)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var duration = MathF.Round(_random.NextFloat(component.MinBountyTime, component.MaxBountyTime) / 15) * 15;
|
_nameIdentifier.GenerateUniqueName(uid, BountyNameIdentifierGroup, out var randomVal);
|
||||||
var endTime = _timing.CurTime + TimeSpan.FromSeconds(duration);
|
component.Bounties.Add(new CargoBountyData(bounty, randomVal));
|
||||||
|
|
||||||
component.Bounties.Add(new CargoBountyData(component.TotalBounties, bounty.ID, endTime));
|
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"Added bounty \"{bounty.ID}\" (id:{component.TotalBounties}) to station {ToPrettyString(uid)}");
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"Added bounty \"{bounty.ID}\" (id:{component.TotalBounties}) to station {ToPrettyString(uid)}");
|
||||||
component.TotalBounties++;
|
component.TotalBounties++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool TryRemoveBounty(EntityUid uid, int dataId, StationCargoBountyDatabaseComponent? component = null)
|
public bool TryRemoveBounty(EntityUid uid, string dataId, StationCargoBountyDatabaseComponent? component = null)
|
||||||
{
|
{
|
||||||
if (!TryGetBountyFromId(uid, dataId, out var data, component))
|
if (!TryGetBountyFromId(uid, dataId, out var data, component))
|
||||||
return false;
|
return false;
|
||||||
@@ -298,7 +397,7 @@ public sealed partial class CargoSystem
|
|||||||
|
|
||||||
public bool TryGetBountyFromId(
|
public bool TryGetBountyFromId(
|
||||||
EntityUid uid,
|
EntityUid uid,
|
||||||
int id,
|
string id,
|
||||||
[NotNullWhen(true)] out CargoBountyData? bounty,
|
[NotNullWhen(true)] out CargoBountyData? bounty,
|
||||||
StationCargoBountyDatabaseComponent? component = null)
|
StationCargoBountyDatabaseComponent? component = null)
|
||||||
{
|
{
|
||||||
@@ -333,17 +432,9 @@ public sealed partial class CargoSystem
|
|||||||
private void UpdateBounty()
|
private void UpdateBounty()
|
||||||
{
|
{
|
||||||
var query = EntityQueryEnumerator<StationCargoBountyDatabaseComponent>();
|
var query = EntityQueryEnumerator<StationCargoBountyDatabaseComponent>();
|
||||||
while (query.MoveNext(out var uid, out var bountyDatabase))
|
while (query.MoveNext(out var bountyDatabase))
|
||||||
{
|
{
|
||||||
bountyDatabase.CheckedBounties.Clear();
|
bountyDatabase.CheckedBounties.Clear();
|
||||||
var bounties = new ValueList<CargoBountyData>(bountyDatabase.Bounties);
|
|
||||||
foreach (var bounty in bounties)
|
|
||||||
{
|
|
||||||
if (_timing.CurTime < bounty.EndTime)
|
|
||||||
continue;
|
|
||||||
TryRemoveBounty(uid, bounty, bountyDatabase);
|
|
||||||
FillBountyDatabase(uid, bountyDatabase);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,10 +288,15 @@ public sealed partial class CargoSystem
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var complete = IsBountyComplete(uid, (EntityUid?) null, out var bountyEntities);
|
||||||
|
|
||||||
// Recursively check for mobs at any point.
|
// Recursively check for mobs at any point.
|
||||||
var children = xform.ChildEnumerator;
|
var children = xform.ChildEnumerator;
|
||||||
while (children.MoveNext(out var child))
|
while (children.MoveNext(out var child))
|
||||||
{
|
{
|
||||||
|
if (complete && bountyEntities.Contains(child))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!CanSell(child, _xformQuery.GetComponent(child)))
|
if (!CanSell(child, _xformQuery.GetComponent(child)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ using Content.Shared.Containers.ItemSlots;
|
|||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
|||||||
@@ -46,6 +46,15 @@ public sealed class NameIdentifierSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a new unique name/suffix for a given entity and adds it to <see cref="CurrentIds"/>
|
||||||
|
/// but does not set the entity's name.
|
||||||
|
/// </summary>
|
||||||
|
public string GenerateUniqueName(EntityUid uid, ProtoId<NameIdentifierGroupPrototype> proto, out int randomVal)
|
||||||
|
{
|
||||||
|
return GenerateUniqueName(uid, _prototypeManager.Index(proto), out randomVal);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a new unique name/suffix for a given entity and adds it to <see cref="CurrentIds"/>
|
/// Generates a new unique name/suffix for a given entity and adds it to <see cref="CurrentIds"/>
|
||||||
/// but does not set the entity's name.
|
/// but does not set the entity's name.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
|
using Content.Server.Cargo.Systems;
|
||||||
using Content.Server.Station.Components;
|
using Content.Server.Station.Components;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
@@ -15,6 +16,7 @@ namespace Content.Server.Station.Commands;
|
|||||||
public sealed class StationsCommand : ToolshedCommand
|
public sealed class StationsCommand : ToolshedCommand
|
||||||
{
|
{
|
||||||
private StationSystem? _station;
|
private StationSystem? _station;
|
||||||
|
private CargoSystem? _cargo;
|
||||||
|
|
||||||
[CommandImplementation("list")]
|
[CommandImplementation("list")]
|
||||||
public IEnumerable<EntityUid> List()
|
public IEnumerable<EntityUid> List()
|
||||||
@@ -111,6 +113,15 @@ public sealed class StationsCommand : ToolshedCommand
|
|||||||
|
|
||||||
_station.RenameStation(input, name.Evaluate(ctx)!);
|
_station.RenameStation(input, name.Evaluate(ctx)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandImplementation("rerollBounties")]
|
||||||
|
public void RerollBounties([CommandInvocationContext] IInvocationContext ctx,
|
||||||
|
[PipedArgument] EntityUid input)
|
||||||
|
{
|
||||||
|
_cargo ??= GetSys<CargoSystem>();
|
||||||
|
|
||||||
|
_cargo.RerollBountyDatabase(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record struct OnlyOneStationsError : IConError
|
public record struct OnlyOneStationsError : IConError
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using Content.Shared.Cargo.Prototypes;
|
using Content.Shared.Cargo.Prototypes;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
|
||||||
|
|
||||||
namespace Content.Shared.Cargo;
|
namespace Content.Shared.Cargo;
|
||||||
|
|
||||||
@@ -9,28 +8,24 @@ namespace Content.Shared.Cargo;
|
|||||||
/// A data structure for storing currently available bounties.
|
/// A data structure for storing currently available bounties.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataDefinition, NetSerializable, Serializable]
|
[DataDefinition, NetSerializable, Serializable]
|
||||||
public readonly partial record struct CargoBountyData(int Id, string Bounty, TimeSpan EndTime)
|
public readonly partial record struct CargoBountyData
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A numeric id used to identify the bounty
|
/// A unique id used to identify the bounty
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("id"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
public int Id { get; init; } = Id;
|
public string Id { get; init; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The prototype containing information about the bounty.
|
/// The prototype containing information about the bounty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("bounty", customTypeSerializer: typeof(PrototypeIdSerializer<CargoBountyPrototype>), required:true)]
|
[DataField(required: true)]
|
||||||
public string Bounty { get; init; } = Bounty;
|
public ProtoId<CargoBountyPrototype> Bounty { get; init; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
public CargoBountyData(CargoBountyPrototype bounty, int uniqueIdentifier)
|
||||||
/// The time at which the bounty is closed and no longer is available.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("endTime", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
|
||||||
public TimeSpan EndTime { get; init; } = EndTime;
|
|
||||||
|
|
||||||
public CargoBountyData() : this(default, string.Empty, default)
|
|
||||||
{
|
{
|
||||||
|
Bounty = bounty.ID;
|
||||||
|
Id = $"{bounty.IdPrefix}{uniqueIdentifier:D3}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ public sealed class CargoBountyConsoleState : BoundUserInterfaceState
|
|||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class BountyPrintLabelMessage : BoundUserInterfaceMessage
|
public sealed class BountyPrintLabelMessage : BoundUserInterfaceMessage
|
||||||
{
|
{
|
||||||
public int BountyId;
|
public string BountyId;
|
||||||
|
|
||||||
public BountyPrintLabelMessage(int bountyId)
|
public BountyPrintLabelMessage(string bountyId)
|
||||||
{
|
{
|
||||||
BountyId = bountyId;
|
BountyId = bountyId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Content.Shared.Cargo.Prototypes;
|
|||||||
/// that must be sold together in a labeled container in order
|
/// that must be sold together in a labeled container in order
|
||||||
/// to receive a monetary reward.
|
/// to receive a monetary reward.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Prototype("cargoBounty"), Serializable, NetSerializable]
|
[Prototype, Serializable, NetSerializable]
|
||||||
public sealed partial class CargoBountyPrototype : IPrototype
|
public sealed partial class CargoBountyPrototype : IPrototype
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -19,20 +19,26 @@ public sealed partial class CargoBountyPrototype : IPrototype
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The monetary reward for completing the bounty
|
/// The monetary reward for completing the bounty
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("reward", required: true)]
|
[DataField(required: true)]
|
||||||
public int Reward;
|
public int Reward;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A description for flava purposes.
|
/// A description for flava purposes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("description")]
|
[DataField]
|
||||||
public string Description = string.Empty;
|
public LocId Description = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entries that must be satisfied for the cargo bounty to be complete.
|
/// The entries that must be satisfied for the cargo bounty to be complete.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("entries", required: true)]
|
[DataField( required: true)]
|
||||||
public List<CargoBountyItemEntry> Entries = new();
|
public List<CargoBountyItemEntry> Entries = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A prefix appended to the beginning of a bounty's ID.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public string IdPrefix = "NT";
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataDefinition, Serializable, NetSerializable]
|
[DataDefinition, Serializable, NetSerializable]
|
||||||
@@ -41,7 +47,7 @@ public readonly partial record struct CargoBountyItemEntry()
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A whitelist for determining what items satisfy the entry.
|
/// A whitelist for determining what items satisfy the entry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("whitelist", required: true)]
|
[DataField(required: true)]
|
||||||
public EntityWhitelist Whitelist { get; init; } = default!;
|
public EntityWhitelist Whitelist { get; init; } = default!;
|
||||||
|
|
||||||
// todo: implement some kind of simple generic condition system
|
// todo: implement some kind of simple generic condition system
|
||||||
@@ -49,12 +55,12 @@ public readonly partial record struct CargoBountyItemEntry()
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// How much of the item must be present to satisfy the entry
|
/// How much of the item must be present to satisfy the entry
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("amount")]
|
[DataField]
|
||||||
public int Amount { get; init; } = 1;
|
public int Amount { get; init; } = 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A player-facing name for the item.
|
/// A player-facing name for the item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("name")]
|
[DataField]
|
||||||
public string Name { get; init; } = string.Empty;
|
public LocId Name { get; init; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ bounty-item-pen = Pen
|
|||||||
bounty-item-percussion = Percussion instrument
|
bounty-item-percussion = Percussion instrument
|
||||||
bounty-item-pie = Pie
|
bounty-item-pie = Pie
|
||||||
bounty-item-prison-uniform = Prison uniform
|
bounty-item-prison-uniform = Prison uniform
|
||||||
bounty-item-radio = Radio
|
bounty-item-radio = Radio or Headset
|
||||||
bounty-item-research-disk = Research disk
|
bounty-item-research-disk = Research disk
|
||||||
bounty-item-shiv = Shiv
|
bounty-item-shiv = Shiv
|
||||||
bounty-item-soap = Soap
|
bounty-item-soap = Soap
|
||||||
@@ -96,9 +96,9 @@ bounty-description-trash = Recently a group of janitors have run out of trash to
|
|||||||
bounty-description-anomaly-core = Suddenly we've run out of anomaly cores, including inert nuclei. Send us any anomaly cores so that we can continue to observe their final decay process.
|
bounty-description-anomaly-core = Suddenly we've run out of anomaly cores, including inert nuclei. Send us any anomaly cores so that we can continue to observe their final decay process.
|
||||||
bounty-description-borg-module = Scientists at the neighboring station have only studied Borg production, not module production. They are stuck in the research process and need references to work from. Send any Borg modules to inspire your colleagues.
|
bounty-description-borg-module = Scientists at the neighboring station have only studied Borg production, not module production. They are stuck in the research process and need references to work from. Send any Borg modules to inspire your colleagues.
|
||||||
bounty-description-artifact-fragment = Scientists at a nearby station are requesting artifact fragments for microxenoarchaeology studies. Ordinary artifacts are too large for their micro research platforms. Send some of the artifact fragments your sector is rich in.
|
bounty-description-artifact-fragment = Scientists at a nearby station are requesting artifact fragments for microxenoarchaeology studies. Ordinary artifacts are too large for their micro research platforms. Send some of the artifact fragments your sector is rich in.
|
||||||
bounty-description-organs = Arachnid settlement orders a large supply of organs. The official reason is "a thorough study of the similarities and differences of the humanoid races."
|
bounty-description-organs = Arachnid settlement orders a large supply of organs. The official reason is "a thorough study of the similarities and differences of the humanoid races."
|
||||||
bounty-description-labeler = Due to a bureaucratic error, our sorting center almost sent hundreds of crates of carrots to the Unathi settlement. We urgently need additional labelers to restore order in the warehouse as a matter of urgency.
|
bounty-description-labeler = Due to a bureaucratic error, our sorting center almost sent hundreds of crates of carrots to the Unathi settlement. We urgently need additional labelers to restore order in the warehouse as a matter of urgency.
|
||||||
bounty-description-warm-cloth = The Unath construction crew freezes and is unable to restore power to their station. They need to be sent a set of any clothing to protect them from the cold.
|
bounty-description-warm-cloth = The Unath construction crew freezes and is unable to restore power to their station. They need to be sent a set of any clothing to protect them from the cold.
|
||||||
bounty-description-battery = As the Arachnid settlement prepares for a solar flare, they are requesting a large shipment of power batteries. We're sending out a request for delivery.
|
bounty-description-battery = As the Arachnid settlement prepares for a solar flare, they are requesting a large shipment of power batteries. We're sending out a request for delivery.
|
||||||
bounty-description-lasergun = The Salvage Caravan requests a large shipment of laser weapons to mop up a hive of xenomorphs.
|
bounty-description-lasergun = The Salvage Caravan requests a large shipment of laser weapons to mop up a hive of xenomorphs.
|
||||||
bounty-description-food = After the rat king invasion, a neighboring unathi station was left completely without food. A large meat food shipment is needed.
|
bounty-description-food = After the rat king invasion, a neighboring unathi station was left completely without food. A large meat food shipment is needed.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
bounty-console-label-button-text = Print label
|
bounty-console-label-button-text = Print label
|
||||||
bounty-console-time-label = Time: [color=orange]{$time}[/color]
|
bounty-console-time-label = Time: [color=orange]{$time}[/color]
|
||||||
bounty-console-reward-label = Reward: [color=limegreen]${$reward}[/color]
|
bounty-console-reward-label = Reward: [color=limegreen]${$reward}[/color]
|
||||||
bounty-console-manifest-label = Manifest: [color=gray]{$item}[/color]
|
bounty-console-manifest-label = Manifest: [color=orange]{$item}[/color]
|
||||||
bounty-console-manifest-entry =
|
bounty-console-manifest-entry =
|
||||||
{ $amount ->
|
{ $amount ->
|
||||||
[1] {$item}
|
[1] {$item}
|
||||||
@@ -14,5 +14,5 @@ bounty-console-id-label = ID#{$id}
|
|||||||
bounty-console-flavor-left = Bounties sourced from local unscrupulous dealers.
|
bounty-console-flavor-left = Bounties sourced from local unscrupulous dealers.
|
||||||
bounty-console-flavor-right = v1.4
|
bounty-console-flavor-right = v1.4
|
||||||
|
|
||||||
bounty-manifest-header = Official cargo bounty manifest (ID#{$id})
|
bounty-manifest-header = [font size=14][bold]Official cargo bounty manifest[/bold] (ID#{$id})[/font]
|
||||||
bounty-manifest-list-start = Item manifest:
|
bounty-manifest-list-start = Item manifest:
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ command-description-stations-rename =
|
|||||||
Renames the given station.
|
Renames the given station.
|
||||||
command-description-stations-largestgrid =
|
command-description-stations-largestgrid =
|
||||||
Returns the largest grid the given station has, if any.
|
Returns the largest grid the given station has, if any.
|
||||||
|
command-description-stations-rerollBounties =
|
||||||
|
Clears all the current bounties for the station and gets a new selection.
|
||||||
command-description-stationevent-lsprob =
|
command-description-stationevent-lsprob =
|
||||||
Lists the probability of different station events occuring out of the entire pool.
|
Lists the probability of different station events occuring out of the entire pool.
|
||||||
command-description-stationevent-lsprobtime =
|
command-description-stationevent-lsprobtime =
|
||||||
|
|||||||
@@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyBaseballBat
|
id: BountyBaseballBat
|
||||||
reward: 8000
|
reward: 4000
|
||||||
description: bounty-description-baseball-bat
|
description: bounty-description-baseball-bat
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-baseball-bat
|
- name: bounty-item-baseball-bat
|
||||||
amount: 5
|
amount: 5
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyBoxHug
|
id: BountyBoxHug
|
||||||
reward: 6000
|
reward: 3000
|
||||||
description: bounty-description-box-hugs
|
description: bounty-description-box-hugs
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-box-hugs
|
- name: bounty-item-box-hugs
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyBrain
|
id: BountyBrain
|
||||||
reward: 25000
|
reward: 12500
|
||||||
description: bounty-description-brain
|
description: bounty-description-brain
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-brain
|
- name: bounty-item-brain
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyBread
|
id: BountyBread
|
||||||
reward: 4000
|
reward: 2000
|
||||||
description: bounty-description-bread
|
description: bounty-description-bread
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-bread
|
- name: bounty-item-bread
|
||||||
@@ -55,8 +56,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyBriefcase
|
id: BountyBriefcase
|
||||||
reward: 15000
|
reward: 7500
|
||||||
description: bounty-description-briefcase
|
description: bounty-description-briefcase
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-briefcase
|
- name: bounty-item-briefcase
|
||||||
amount: 5
|
amount: 5
|
||||||
@@ -66,8 +68,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyCarrot
|
id: BountyCarrot
|
||||||
reward: 15000
|
reward: 7500
|
||||||
description: bounty-description-carrot
|
description: bounty-description-carrot
|
||||||
|
idPrefix: SS15-
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-carrot
|
- name: bounty-item-carrot
|
||||||
amount: 10
|
amount: 10
|
||||||
@@ -77,7 +80,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyCarrotFries
|
id: BountyCarrotFries
|
||||||
reward: 14000
|
reward: 7000
|
||||||
description: bounty-description-carrot-fries
|
description: bounty-description-carrot-fries
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-carrot-fries
|
- name: bounty-item-carrot-fries
|
||||||
@@ -88,8 +91,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyCarp
|
id: BountyCarp
|
||||||
reward: 25000
|
reward: 12500
|
||||||
description: bounty-description-carp
|
description: bounty-description-carp
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-carp
|
- name: bounty-item-carp
|
||||||
amount: 1
|
amount: 1
|
||||||
@@ -115,7 +119,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyCorn
|
id: BountyCorn
|
||||||
reward: 20000
|
reward: 10000
|
||||||
description: bounty-description-corn
|
description: bounty-description-corn
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-corn
|
- name: bounty-item-corn
|
||||||
@@ -126,7 +130,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyCrayon
|
id: BountyCrayon
|
||||||
reward: 8000
|
reward: 4000
|
||||||
description: bounty-description-crayon
|
description: bounty-description-crayon
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-crayon
|
- name: bounty-item-crayon
|
||||||
@@ -137,8 +141,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyCubanCarp
|
id: BountyCubanCarp
|
||||||
reward: 32000
|
reward: 16000
|
||||||
description: bounty-description-cuban-carp
|
description: bounty-description-cuban-carp
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-cuban-carp
|
- name: bounty-item-cuban-carp
|
||||||
amount: 1
|
amount: 1
|
||||||
@@ -148,8 +153,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyDonkPocket
|
id: BountyDonkPocket
|
||||||
reward: 12000
|
reward: 6000
|
||||||
description: bounty-description-donk-pocket
|
description: bounty-description-donk-pocket
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-donk-pocket
|
- name: bounty-item-donk-pocket
|
||||||
amount: 12
|
amount: 12
|
||||||
@@ -159,8 +165,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyDonut
|
id: BountyDonut
|
||||||
reward: 12000
|
reward: 6000
|
||||||
description: bounty-description-donut
|
description: bounty-description-donut
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-donut
|
- name: bounty-item-donut
|
||||||
amount: 10
|
amount: 10
|
||||||
@@ -170,7 +177,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyFigurine
|
id: BountyFigurine
|
||||||
reward: 16000
|
reward: 8000
|
||||||
description: bounty-description-figurine
|
description: bounty-description-figurine
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-figurine
|
- name: bounty-item-figurine
|
||||||
@@ -179,21 +186,11 @@
|
|||||||
tags:
|
tags:
|
||||||
- Figurine
|
- Figurine
|
||||||
|
|
||||||
- type: cargoBounty
|
|
||||||
id: BountyFleshMonster
|
|
||||||
reward: 30000
|
|
||||||
description: bounty-description-flesh-monster
|
|
||||||
entries:
|
|
||||||
- name: bounty-item-flesh-monster
|
|
||||||
amount: 3
|
|
||||||
whitelist:
|
|
||||||
tags:
|
|
||||||
- Flesh
|
|
||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyFlower
|
id: BountyFlower
|
||||||
reward: 4000
|
reward: 2000
|
||||||
description: bounty-description-flower
|
description: bounty-description-flower
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-flower
|
- name: bounty-item-flower
|
||||||
amount: 3
|
amount: 3
|
||||||
@@ -203,7 +200,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyGalaxyThistle
|
id: BountyGalaxyThistle
|
||||||
reward: 24000
|
reward: 12000
|
||||||
description: bounty-description-galaxythistle
|
description: bounty-description-galaxythistle
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-galaxythistle
|
- name: bounty-item-galaxythistle
|
||||||
@@ -214,8 +211,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyHandcuffs
|
id: BountyHandcuffs
|
||||||
reward: 4000
|
reward: 1000
|
||||||
description: bounty-description-handcuffs
|
description: bounty-description-handcuffs
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-handcuffs
|
- name: bounty-item-handcuffs
|
||||||
amount: 5
|
amount: 5
|
||||||
@@ -236,7 +234,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyKnife
|
id: BountyKnife
|
||||||
reward: 12000
|
reward: 6000
|
||||||
description: bounty-description-knife
|
description: bounty-description-knife
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-knife
|
- name: bounty-item-knife
|
||||||
@@ -247,7 +245,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyLemon
|
id: BountyLemon
|
||||||
reward: 20000
|
reward: 10000
|
||||||
description: bounty-description-lemon
|
description: bounty-description-lemon
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-lemon
|
- name: bounty-item-lemon
|
||||||
@@ -258,8 +256,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyLime
|
id: BountyLime
|
||||||
reward: 20000
|
reward: 10000
|
||||||
description: bounty-description-lime
|
description: bounty-description-lime
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-lime
|
- name: bounty-item-lime
|
||||||
amount: 7
|
amount: 7
|
||||||
@@ -269,7 +268,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyLung
|
id: BountyLung
|
||||||
reward: 35000
|
reward: 2000
|
||||||
description: bounty-description-lung
|
description: bounty-description-lung
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-lung
|
- name: bounty-item-lung
|
||||||
@@ -280,8 +279,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyMonkeyCube
|
id: BountyMonkeyCube
|
||||||
reward: 8000
|
reward: 2000
|
||||||
description: bounty-description-monkey-cube
|
description: bounty-description-monkey-cube
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-monkey-cube
|
- name: bounty-item-monkey-cube
|
||||||
amount: 3
|
amount: 3
|
||||||
@@ -293,6 +293,7 @@
|
|||||||
id: BountyMouse
|
id: BountyMouse
|
||||||
reward: 2400
|
reward: 2400
|
||||||
description: bounty-description-mouse
|
description: bounty-description-mouse
|
||||||
|
idPrefix: SS13-
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-mouse
|
- name: bounty-item-mouse
|
||||||
amount: 5
|
amount: 5
|
||||||
@@ -302,7 +303,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyPancake
|
id: BountyPancake
|
||||||
reward: 20000
|
reward: 10000
|
||||||
description: bounty-description-pancake
|
description: bounty-description-pancake
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-pancake
|
- name: bounty-item-pancake
|
||||||
@@ -317,14 +318,14 @@
|
|||||||
description: bounty-description-pen
|
description: bounty-description-pen
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-pen
|
- name: bounty-item-pen
|
||||||
amount: 10
|
amount: 5
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
- Write
|
- Pen
|
||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyPercussion
|
id: BountyPercussion
|
||||||
reward: 25000
|
reward: 15000
|
||||||
description: bounty-description-percussion
|
description: bounty-description-percussion
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-percussion
|
- name: bounty-item-percussion
|
||||||
@@ -335,7 +336,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyPie
|
id: BountyPie
|
||||||
reward: 31415
|
reward: 3141
|
||||||
description: bounty-description-pie
|
description: bounty-description-pie
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-pie
|
- name: bounty-item-pie
|
||||||
@@ -348,6 +349,7 @@
|
|||||||
id: BountyPrisonUniform
|
id: BountyPrisonUniform
|
||||||
reward: 8000
|
reward: 8000
|
||||||
description: bounty-description-prison-uniform
|
description: bounty-description-prison-uniform
|
||||||
|
idPrefix: TG
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-prison-uniform
|
- name: bounty-item-prison-uniform
|
||||||
amount: 4
|
amount: 4
|
||||||
@@ -357,7 +359,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyRadio
|
id: BountyRadio
|
||||||
reward: 10000
|
reward: 7500
|
||||||
description: bounty-description-radio
|
description: bounty-description-radio
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-radio
|
- name: bounty-item-radio
|
||||||
@@ -369,21 +371,11 @@
|
|||||||
tags:
|
tags:
|
||||||
- Radio
|
- Radio
|
||||||
|
|
||||||
- type: cargoBounty
|
|
||||||
id: BountyResearchDisk
|
|
||||||
reward: 12000
|
|
||||||
description: bounty-description-research-disk
|
|
||||||
entries:
|
|
||||||
- name: bounty-item-research-disk
|
|
||||||
amount: 1
|
|
||||||
whitelist:
|
|
||||||
components:
|
|
||||||
- ResearchDisk
|
|
||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyShiv
|
id: BountyShiv
|
||||||
reward: 8000
|
reward: 4000
|
||||||
description: bounty-description-shiv
|
description: bounty-description-shiv
|
||||||
|
idPrefix: SYN
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-shiv
|
- name: bounty-item-shiv
|
||||||
amount: 5
|
amount: 5
|
||||||
@@ -393,7 +385,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountySoap
|
id: BountySoap
|
||||||
reward: 8000
|
reward: 4000
|
||||||
description: bounty-description-soap
|
description: bounty-description-soap
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-soap
|
- name: bounty-item-soap
|
||||||
@@ -404,7 +396,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountySoup
|
id: BountySoup
|
||||||
reward: 12000
|
reward: 6000
|
||||||
description: bounty-description-soup
|
description: bounty-description-soup
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-soup
|
- name: bounty-item-soup
|
||||||
@@ -426,7 +418,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountySyringe
|
id: BountySyringe
|
||||||
reward: 10000
|
reward: 5000
|
||||||
description: bounty-description-syringe
|
description: bounty-description-syringe
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-syringe
|
- name: bounty-item-syringe
|
||||||
@@ -439,6 +431,7 @@
|
|||||||
id: BountyTechDisk
|
id: BountyTechDisk
|
||||||
reward: 25000
|
reward: 25000
|
||||||
description: bounty-description-tech-disk
|
description: bounty-description-tech-disk
|
||||||
|
idPrefix: SS13-
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-tech-disk
|
- name: bounty-item-tech-disk
|
||||||
amount: 5
|
amount: 5
|
||||||
@@ -450,6 +443,7 @@
|
|||||||
id: BountyToolbox
|
id: BountyToolbox
|
||||||
reward: 8000
|
reward: 8000
|
||||||
description: bounty-description-toolbox
|
description: bounty-description-toolbox
|
||||||
|
idPrefix: CC
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-toolbox
|
- name: bounty-item-toolbox
|
||||||
amount: 6
|
amount: 6
|
||||||
@@ -459,7 +453,7 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyTrash
|
id: BountyTrash
|
||||||
reward: 700
|
reward: 500
|
||||||
description: bounty-description-trash
|
description: bounty-description-trash
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-trash
|
- name: bounty-item-trash
|
||||||
@@ -503,8 +497,9 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyOrgans
|
id: BountyOrgans
|
||||||
reward: 3500
|
reward: 2000
|
||||||
description: bounty-description-organs
|
description: bounty-description-organs
|
||||||
|
idPrefix: UNTH
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-organs
|
- name: bounty-item-organs
|
||||||
amount: 8
|
amount: 8
|
||||||
@@ -522,22 +517,24 @@
|
|||||||
whitelist:
|
whitelist:
|
||||||
components:
|
components:
|
||||||
- HandLabeler
|
- HandLabeler
|
||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyWarmCloth
|
id: BountyWarmCloth
|
||||||
reward: 6000
|
reward: 2000
|
||||||
description: bounty-description-warm-cloth
|
description: bounty-description-warm-cloth
|
||||||
|
idPrefix: UNTH
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-warm-cloth
|
- name: bounty-item-warm-cloth
|
||||||
amount: 8
|
amount: 8
|
||||||
whitelist:
|
whitelist:
|
||||||
components:
|
components:
|
||||||
- TemperatureProtection
|
- TemperatureProtection
|
||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyBattery
|
id: BountyBattery
|
||||||
reward: 24500
|
reward: 15000
|
||||||
description: bounty-description-battery
|
description: bounty-description-battery
|
||||||
|
idPrefix: UNTH
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-item-battery
|
- name: bounty-item-battery
|
||||||
amount: 15
|
amount: 15
|
||||||
@@ -549,6 +546,7 @@
|
|||||||
id: BountyLaserGun
|
id: BountyLaserGun
|
||||||
reward: 28500
|
reward: 28500
|
||||||
description: bounty-description-lasergun
|
description: bounty-description-lasergun
|
||||||
|
idPrefix: IV
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-lasergun
|
- name: bounty-lasergun
|
||||||
amount: 6
|
amount: 6
|
||||||
@@ -558,11 +556,12 @@
|
|||||||
|
|
||||||
- type: cargoBounty
|
- type: cargoBounty
|
||||||
id: BountyFood
|
id: BountyFood
|
||||||
reward: 9500
|
reward: 4000
|
||||||
description: bounty-description-food
|
description: bounty-description-food
|
||||||
|
idPrefix: UNTH
|
||||||
entries:
|
entries:
|
||||||
- name: bounty-food
|
- name: bounty-food
|
||||||
amount: 30
|
amount: 30
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
- Meat
|
- Meat
|
||||||
|
|||||||
@@ -239,6 +239,7 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Write
|
- Write
|
||||||
|
- Pen
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Misc/bureaucracy.rsi
|
sprite: Objects/Misc/bureaucracy.rsi
|
||||||
state: pen
|
state: pen
|
||||||
@@ -647,4 +648,4 @@
|
|||||||
types:
|
types:
|
||||||
Blunt: 10
|
Blunt: 10
|
||||||
- type: StealTarget
|
- type: StealTarget
|
||||||
stealGroup: BoxFolderQmClipboard
|
stealGroup: BoxFolderQmClipboard
|
||||||
|
|||||||
@@ -35,3 +35,8 @@
|
|||||||
# Used to suffix a number to any mob to identify player controlled mob griefing.
|
# Used to suffix a number to any mob to identify player controlled mob griefing.
|
||||||
- type: nameIdentifierGroup
|
- type: nameIdentifierGroup
|
||||||
id: GenericNumber
|
id: GenericNumber
|
||||||
|
|
||||||
|
- type: nameIdentifierGroup
|
||||||
|
id: Bounty
|
||||||
|
minValue: 0
|
||||||
|
maxValue: 999
|
||||||
|
|||||||
@@ -830,6 +830,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: Pancake
|
id: Pancake
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: Pen
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: PepperShaker
|
id: PepperShaker
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user