]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Skipping bounties (#26537)
authorKillerqu00 <47712032+Killerqu00@users.noreply.github.com>
Tue, 9 Apr 2024 22:18:07 +0000 (00:18 +0200)
committerGitHub <noreply@github.com>
Tue, 9 Apr 2024 22:18:07 +0000 (18:18 -0400)
* 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

Content.Client/Cargo/BUI/CargoBountyConsoleBoundUserInterface.cs
Content.Client/Cargo/UI/BountyEntry.xaml
Content.Client/Cargo/UI/BountyEntry.xaml.cs
Content.Client/Cargo/UI/CargoBountyMenu.xaml.cs
Content.Server/Cargo/Components/StationCargoBountyDatabaseComponent.cs
Content.Server/Cargo/Systems/CargoSystem.Bounty.cs
Content.Shared/Cargo/Components/CargoBountyConsoleComponent.cs
Resources/Locale/en-US/cargo/cargo-bounty-console.ftl
Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml

index 482acb3c877a9af346604d2eff788c19809db2ac..d3365702bcfc54bb346e48a72cfffef748291c78 100644 (file)
@@ -27,6 +27,11 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
             SendMessage(new BountyPrintLabelMessage(id));
         };
 
+        _menu.OnSkipButtonPressed += id =>
+        {
+            SendMessage(new BountySkipMessage(id));
+        };
+
         _menu.OpenCentered();
     }
 
@@ -37,7 +42,7 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
         if (message is not CargoBountyConsoleState state)
             return;
 
-        _menu?.UpdateEntries(state.Bounties);
+        _menu?.UpdateEntries(state.Bounties, state.UntilNextSkip);
     }
 
     protected override void Dispose(bool disposing)
index 60446327b353f9a6f6367b99a357bc04ad6aa8b3..7c61323bd55674664736e989a05cd5253f57d004 100644 (file)
                 </BoxContainer>
                 <Control MinWidth="10"/>
                 <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"/>
                 </BoxContainer>
             </BoxContainer>
index 1fc8a4986a2a6551f9feeebc2960f14251dba05f..027d7b3e8011be238db28d7057cfcbee1a5ff3dc 100644 (file)
@@ -1,11 +1,13 @@
 using Content.Client.Message;
 using Content.Shared.Cargo;
 using Content.Shared.Cargo.Prototypes;
+using Content.Shared.Random;
 using Robust.Client.AutoGenerated;
 using Robust.Client.UserInterface.Controls;
 using Robust.Client.UserInterface.XAML;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Timing;
+using Serilog;
 
 namespace Content.Client.Cargo.UI;
 
@@ -14,15 +16,19 @@ public sealed partial class BountyEntry : BoxContainer
 {
     [Dependency] private readonly IPrototypeManager _prototype = default!;
 
-    public Action? OnButtonPressed;
+    public Action? OnLabelButtonPressed;
+    public Action? OnSkipButtonPressed;
 
     public TimeSpan EndTime;
+    public TimeSpan UntilNextSkip;
 
-    public BountyEntry(CargoBountyData bounty)
+    public BountyEntry(CargoBountyData bounty, TimeSpan untilNextSkip)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
 
+        UntilNextSkip = untilNextSkip;
+
         if (!_prototype.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var bountyPrototype))
             return;
 
@@ -38,6 +44,27 @@ public sealed partial class BountyEntry : BoxContainer
         DescriptionLabel.SetMarkup(Loc.GetString("bounty-console-description-label", ("description", Loc.GetString(bountyPrototype.Description))));
         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);
     }
 }
index 2f1756dd18b3baf175f72aeb3a219cd96118e79a..3767b45e4bed43c5baf3fe9afe96c264156890e8 100644 (file)
@@ -10,19 +10,21 @@ namespace Content.Client.Cargo.UI;
 public sealed partial class CargoBountyMenu : FancyWindow
 {
     public Action<string>? OnLabelButtonPressed;
+    public Action<string>? OnSkipButtonPressed;
 
     public CargoBountyMenu()
     {
         RobustXamlLoader.Load(this);
     }
 
-    public void UpdateEntries(List<CargoBountyData> bounties)
+    public void UpdateEntries(List<CargoBountyData> bounties, TimeSpan untilNextSkip)
     {
         BountyEntriesContainer.Children.Clear();
         foreach (var b in bounties)
         {
-            var entry = new BountyEntry(b);
-            entry.OnButtonPressed += () => OnLabelButtonPressed?.Invoke(b.Id);
+            var entry = new BountyEntry(b, untilNextSkip);
+            entry.OnLabelButtonPressed += () => OnLabelButtonPressed?.Invoke(b.Id);
+            entry.OnSkipButtonPressed += () => OnSkipButtonPressed?.Invoke(b.Id);
 
             BountyEntriesContainer.AddChild(entry);
         }
index d26794a632382000248e2d18a3409f3e970ca817..a7735787cbb69257b3282e4a049b38672833e7ac 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Shared.Cargo;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
 
 namespace Content.Server.Cargo.Components;
 
@@ -32,4 +33,16 @@ public sealed partial class StationCargoBountyDatabaseComponent : Component
     /// </summary>
     [DataField]
     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);
 }
index ee5ae631fd9d3702a34158867a6d9f81ca493703..22e5c67e1759aaea8829a8c61aa604220c82ed2f 100644 (file)
@@ -4,7 +4,7 @@ using Content.Server.Cargo.Components;
 using Content.Server.Labels;
 using Content.Server.NameIdentifier;
 using Content.Server.Paper;
-using Content.Server.Station.Systems;
+using Content.Shared.Access.Components;
 using Content.Shared.Cargo;
 using Content.Shared.Cargo.Components;
 using Content.Shared.Cargo.Prototypes;
@@ -35,6 +35,7 @@ public sealed partial class CargoSystem
     {
         SubscribeLocalEvent<CargoBountyConsoleComponent, BoundUIOpenedEvent>(OnBountyConsoleOpened);
         SubscribeLocalEvent<CargoBountyConsoleComponent, BountyPrintLabelMessage>(OnPrintLabelMessage);
+        SubscribeLocalEvent<CargoBountyConsoleComponent, BountySkipMessage>(OnSkipBountyMessage);
         SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
         SubscribeLocalEvent<EntitySoldEvent>(OnSold);
         SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
@@ -50,7 +51,8 @@ public sealed partial class CargoSystem
             !TryComp<StationCargoBountyDatabaseComponent>(station, out var bountyDb))
             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)
@@ -70,6 +72,37 @@ public sealed partial class CargoSystem
         _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)
     {
         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))
                 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);
         }
     }
 
index 7b1acf836fdcd3fdf41303a6de2b0d9feb9b1857..bf82a08127e530994bd116461b76bb4a7c0387d4 100644 (file)
@@ -32,16 +32,30 @@ public sealed partial class CargoBountyConsoleComponent : Component
     /// </summary>
     [DataField("printSound")]
     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]
 public sealed class CargoBountyConsoleState : BoundUserInterfaceState
 {
     public List<CargoBountyData> Bounties;
+    public TimeSpan UntilNextSkip;
 
-    public CargoBountyConsoleState(List<CargoBountyData> bounties)
+    public CargoBountyConsoleState(List<CargoBountyData> bounties, TimeSpan untilNextSkip)
     {
         Bounties = bounties;
+        UntilNextSkip = untilNextSkip;
     }
 }
 
@@ -55,3 +69,14 @@ public sealed class BountyPrintLabelMessage : BoundUserInterfaceMessage
         BountyId = bountyId;
     }
 }
+
+[Serializable, NetSerializable]
+public sealed class BountySkipMessage : BoundUserInterfaceMessage
+{
+    public string BountyId;
+
+    public BountySkipMessage(string bountyId)
+    {
+        BountyId = bountyId;
+    }
+}
index ec80d91f47f34d1399d70e18f0439305b6a115b5..bf7868e3df703dd748229cd83a1ab8b3b8729d06 100644 (file)
@@ -1,5 +1,6 @@
 bounty-console-menu-title = Cargo bounty console
 bounty-console-label-button-text = Print label
+bounty-console-skip-button-text = Skip
 bounty-console-time-label = Time: [color=orange]{$time}[/color]
 bounty-console-reward-label = Reward: [color=limegreen]${$reward}[/color]
 bounty-console-manifest-label = Manifest: [color=orange]{$item}[/color]
index d467a01f8353e1e8873e1f51c08048fb2d553f59..95bf2e1dd4a5688305fb94bcf356407ecacb7680 100644 (file)
     radius: 1.5
     energy: 1.6
     color: "#b89f25"
+  - type: AccessReader
+    access: [["Quartermaster"]]
   - type: GuideHelp
     guides:
     - CargoBounties