Skipping bounties (#26537)
* add button to menu * networking and component work * try to add access stuff * main functionality done * add access lock? I think? * remove extra line * fix access system * move SkipTime to StationCargoBountyDatabaseComponent * Disable/Enable skip button based on cooldown * remove debugging * add access denied sound * remove DataField tags * dynamic timer
This commit is contained in:
@@ -27,6 +27,11 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
|
|||||||
SendMessage(new BountyPrintLabelMessage(id));
|
SendMessage(new BountyPrintLabelMessage(id));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_menu.OnSkipButtonPressed += id =>
|
||||||
|
{
|
||||||
|
SendMessage(new BountySkipMessage(id));
|
||||||
|
};
|
||||||
|
|
||||||
_menu.OpenCentered();
|
_menu.OpenCentered();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +42,7 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
|
|||||||
if (message is not CargoBountyConsoleState state)
|
if (message is not CargoBountyConsoleState state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_menu?.UpdateEntries(state.Bounties);
|
_menu?.UpdateEntries(state.Bounties, state.UntilNextSkip);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
|
|||||||
@@ -13,7 +13,18 @@
|
|||||||
</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"/>
|
<BoxContainer Orientation="Horizontal" MinWidth="120">
|
||||||
|
<Button Name="PrintButton"
|
||||||
|
Text="{Loc 'bounty-console-label-button-text'}"
|
||||||
|
HorizontalExpand="False"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
StyleClasses="OpenRight"/>
|
||||||
|
<Button Name="SkipButton"
|
||||||
|
Text="{Loc 'bounty-console-skip-button-text'}"
|
||||||
|
HorizontalExpand="False"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
StyleClasses="OpenLeft"/>
|
||||||
|
</BoxContainer>
|
||||||
<RichTextLabel Name="IdLabel" HorizontalAlignment="Right" Margin="0 0 5 0"/>
|
<RichTextLabel Name="IdLabel" HorizontalAlignment="Right" Margin="0 0 5 0"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
using Content.Client.Message;
|
using Content.Client.Message;
|
||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
using Content.Shared.Cargo.Prototypes;
|
using Content.Shared.Cargo.Prototypes;
|
||||||
|
using Content.Shared.Random;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace Content.Client.Cargo.UI;
|
namespace Content.Client.Cargo.UI;
|
||||||
|
|
||||||
@@ -14,15 +16,19 @@ public sealed partial class BountyEntry : BoxContainer
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
|
|
||||||
public Action? OnButtonPressed;
|
public Action? OnLabelButtonPressed;
|
||||||
|
public Action? OnSkipButtonPressed;
|
||||||
|
|
||||||
public TimeSpan EndTime;
|
public TimeSpan EndTime;
|
||||||
|
public TimeSpan UntilNextSkip;
|
||||||
|
|
||||||
public BountyEntry(CargoBountyData bounty)
|
public BountyEntry(CargoBountyData bounty, TimeSpan untilNextSkip)
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
|
UntilNextSkip = untilNextSkip;
|
||||||
|
|
||||||
if (!_prototype.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var bountyPrototype))
|
if (!_prototype.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var bountyPrototype))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -38,6 +44,27 @@ public sealed partial class BountyEntry : BoxContainer
|
|||||||
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.SetMarkup(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 += _ => OnLabelButtonPressed?.Invoke();
|
||||||
|
SkipButton.OnPressed += _ => OnSkipButtonPressed?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateSkipButton(float deltaSeconds)
|
||||||
|
{
|
||||||
|
UntilNextSkip -= TimeSpan.FromSeconds(deltaSeconds);
|
||||||
|
if (UntilNextSkip > TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
SkipButton.Label.Text = UntilNextSkip.ToString("mm\\:ss");
|
||||||
|
SkipButton.Disabled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkipButton.Label.Text = Loc.GetString("bounty-console-skip-button-text");
|
||||||
|
SkipButton.Disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void FrameUpdate(FrameEventArgs args)
|
||||||
|
{
|
||||||
|
base.FrameUpdate(args);
|
||||||
|
UpdateSkipButton(args.DeltaSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,19 +10,21 @@ namespace Content.Client.Cargo.UI;
|
|||||||
public sealed partial class CargoBountyMenu : FancyWindow
|
public sealed partial class CargoBountyMenu : FancyWindow
|
||||||
{
|
{
|
||||||
public Action<string>? OnLabelButtonPressed;
|
public Action<string>? OnLabelButtonPressed;
|
||||||
|
public Action<string>? OnSkipButtonPressed;
|
||||||
|
|
||||||
public CargoBountyMenu()
|
public CargoBountyMenu()
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateEntries(List<CargoBountyData> bounties)
|
public void UpdateEntries(List<CargoBountyData> bounties, TimeSpan untilNextSkip)
|
||||||
{
|
{
|
||||||
BountyEntriesContainer.Children.Clear();
|
BountyEntriesContainer.Children.Clear();
|
||||||
foreach (var b in bounties)
|
foreach (var b in bounties)
|
||||||
{
|
{
|
||||||
var entry = new BountyEntry(b);
|
var entry = new BountyEntry(b, untilNextSkip);
|
||||||
entry.OnButtonPressed += () => OnLabelButtonPressed?.Invoke(b.Id);
|
entry.OnLabelButtonPressed += () => OnLabelButtonPressed?.Invoke(b.Id);
|
||||||
|
entry.OnSkipButtonPressed += () => OnSkipButtonPressed?.Invoke(b.Id);
|
||||||
|
|
||||||
BountyEntriesContainer.AddChild(entry);
|
BountyEntriesContainer.AddChild(entry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
namespace Content.Server.Cargo.Components;
|
namespace Content.Server.Cargo.Components;
|
||||||
|
|
||||||
@@ -32,4 +33,16 @@ public sealed partial class StationCargoBountyDatabaseComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public HashSet<string> CheckedBounties = new();
|
public HashSet<string> CheckedBounties = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time at which players will be able to skip the next bounty.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||||
|
public TimeSpan NextSkipTime = TimeSpan.Zero;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time between skipping bounties.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan SkipDelay = TimeSpan.FromMinutes(15);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Content.Server.Cargo.Components;
|
|||||||
using Content.Server.Labels;
|
using Content.Server.Labels;
|
||||||
using Content.Server.NameIdentifier;
|
using Content.Server.NameIdentifier;
|
||||||
using Content.Server.Paper;
|
using Content.Server.Paper;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Shared.Access.Components;
|
||||||
using Content.Shared.Cargo;
|
using Content.Shared.Cargo;
|
||||||
using Content.Shared.Cargo.Components;
|
using Content.Shared.Cargo.Components;
|
||||||
using Content.Shared.Cargo.Prototypes;
|
using Content.Shared.Cargo.Prototypes;
|
||||||
@@ -35,6 +35,7 @@ public sealed partial class CargoSystem
|
|||||||
{
|
{
|
||||||
SubscribeLocalEvent<CargoBountyConsoleComponent, BoundUIOpenedEvent>(OnBountyConsoleOpened);
|
SubscribeLocalEvent<CargoBountyConsoleComponent, BoundUIOpenedEvent>(OnBountyConsoleOpened);
|
||||||
SubscribeLocalEvent<CargoBountyConsoleComponent, BountyPrintLabelMessage>(OnPrintLabelMessage);
|
SubscribeLocalEvent<CargoBountyConsoleComponent, BountyPrintLabelMessage>(OnPrintLabelMessage);
|
||||||
|
SubscribeLocalEvent<CargoBountyConsoleComponent, BountySkipMessage>(OnSkipBountyMessage);
|
||||||
SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
|
SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
|
||||||
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
|
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
|
||||||
SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
|
||||||
@@ -50,7 +51,8 @@ public sealed partial class CargoSystem
|
|||||||
!TryComp<StationCargoBountyDatabaseComponent>(station, out var bountyDb))
|
!TryComp<StationCargoBountyDatabaseComponent>(station, out var bountyDb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(bountyDb.Bounties));
|
var untilNextSkip = bountyDb.NextSkipTime - _timing.CurTime;
|
||||||
|
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(bountyDb.Bounties, untilNextSkip));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPrintLabelMessage(EntityUid uid, CargoBountyConsoleComponent component, BountyPrintLabelMessage args)
|
private void OnPrintLabelMessage(EntityUid uid, CargoBountyConsoleComponent component, BountyPrintLabelMessage args)
|
||||||
@@ -70,6 +72,37 @@ public sealed partial class CargoSystem
|
|||||||
_audio.PlayPvs(component.PrintSound, uid);
|
_audio.PlayPvs(component.PrintSound, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnSkipBountyMessage(EntityUid uid, CargoBountyConsoleComponent component, BountySkipMessage args)
|
||||||
|
{
|
||||||
|
if (_station.GetOwningStation(uid) is not { } station || !TryComp<StationCargoBountyDatabaseComponent>(station, out var db))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_timing.CurTime < db.NextSkipTime)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TryGetBountyFromId(station, args.BountyId, out var bounty))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Session.AttachedEntity is not { Valid: true } mob)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp<AccessReaderComponent>(uid, out var accessReaderComponent) &&
|
||||||
|
!_accessReaderSystem.IsAllowed(mob, uid, accessReaderComponent))
|
||||||
|
{
|
||||||
|
_audio.PlayPvs(component.DenySound, uid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryRemoveBounty(station, bounty.Value))
|
||||||
|
return;
|
||||||
|
|
||||||
|
FillBountyDatabase(station);
|
||||||
|
db.NextSkipTime = _timing.CurTime + db.SkipDelay;
|
||||||
|
var untilNextSkip = db.NextSkipTime - _timing.CurTime;
|
||||||
|
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(db.Bounties, untilNextSkip));
|
||||||
|
_audio.PlayPvs(component.SkipSound, uid);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetupBountyLabel(EntityUid uid, EntityUid stationId, CargoBountyData bounty, PaperComponent? paper = null, CargoBountyLabelComponent? label = null)
|
public void SetupBountyLabel(EntityUid uid, EntityUid stationId, CargoBountyData bounty, PaperComponent? paper = null, CargoBountyLabelComponent? label = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref paper, ref label) || !_protoMan.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var prototype))
|
if (!Resolve(uid, ref paper, ref label) || !_protoMan.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var prototype))
|
||||||
@@ -431,7 +464,8 @@ public sealed partial class CargoSystem
|
|||||||
!TryComp<StationCargoBountyDatabaseComponent>(station, out var db))
|
!TryComp<StationCargoBountyDatabaseComponent>(station, out var db))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(db.Bounties), ui: ui);
|
var untilNextSkip = db.NextSkipTime - _timing.CurTime;
|
||||||
|
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(db.Bounties, untilNextSkip), ui: ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,16 +32,30 @@ public sealed partial class CargoBountyConsoleComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("printSound")]
|
[DataField("printSound")]
|
||||||
public SoundSpecifier PrintSound = new SoundPathSpecifier("/Audio/Machines/printer.ogg");
|
public SoundSpecifier PrintSound = new SoundPathSpecifier("/Audio/Machines/printer.ogg");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sound made when the bounty is skipped.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("skipSound")]
|
||||||
|
public SoundSpecifier SkipSound = new SoundPathSpecifier("/Audio/Effects/Cargo/ping.ogg");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sound made when bounty skipping is denied due to lacking access.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("denySound")]
|
||||||
|
public SoundSpecifier DenySound = new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_two.ogg");
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetSerializable, Serializable]
|
[NetSerializable, Serializable]
|
||||||
public sealed class CargoBountyConsoleState : BoundUserInterfaceState
|
public sealed class CargoBountyConsoleState : BoundUserInterfaceState
|
||||||
{
|
{
|
||||||
public List<CargoBountyData> Bounties;
|
public List<CargoBountyData> Bounties;
|
||||||
|
public TimeSpan UntilNextSkip;
|
||||||
|
|
||||||
public CargoBountyConsoleState(List<CargoBountyData> bounties)
|
public CargoBountyConsoleState(List<CargoBountyData> bounties, TimeSpan untilNextSkip)
|
||||||
{
|
{
|
||||||
Bounties = bounties;
|
Bounties = bounties;
|
||||||
|
UntilNextSkip = untilNextSkip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,3 +69,14 @@ public sealed class BountyPrintLabelMessage : BoundUserInterfaceMessage
|
|||||||
BountyId = bountyId;
|
BountyId = bountyId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class BountySkipMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public string BountyId;
|
||||||
|
|
||||||
|
public BountySkipMessage(string bountyId)
|
||||||
|
{
|
||||||
|
BountyId = bountyId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
bounty-console-menu-title = Cargo bounty console
|
bounty-console-menu-title = Cargo bounty console
|
||||||
bounty-console-label-button-text = Print label
|
bounty-console-label-button-text = Print label
|
||||||
|
bounty-console-skip-button-text = Skip
|
||||||
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=orange]{$item}[/color]
|
bounty-console-manifest-label = Manifest: [color=orange]{$item}[/color]
|
||||||
|
|||||||
@@ -791,6 +791,8 @@
|
|||||||
radius: 1.5
|
radius: 1.5
|
||||||
energy: 1.6
|
energy: 1.6
|
||||||
color: "#b89f25"
|
color: "#b89f25"
|
||||||
|
- type: AccessReader
|
||||||
|
access: [["Quartermaster"]]
|
||||||
- type: GuideHelp
|
- type: GuideHelp
|
||||||
guides:
|
guides:
|
||||||
- CargoBounties
|
- CargoBounties
|
||||||
|
|||||||
Reference in New Issue
Block a user