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(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)
|
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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -525,8 +520,9 @@
|
|||||||
|
|
||||||
- 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
|
||||||
@@ -536,8 +532,9 @@
|
|||||||
|
|
||||||
- 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,8 +556,9 @@
|
|||||||
|
|
||||||
- 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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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