Skip to content

Commit

Permalink
Feat: Port All Delta-V Mail Improvements (#1011)
Browse files Browse the repository at this point in the history
# Description
Showing some love to our hard-working couriers.

This cherry-picks the following PRs from delta-v:
- DeltaV-Station/Delta-v#1472 - Adds a
MailMetrics PDA cartridge for couriers and the LO
- DeltaV-Station/Delta-v#1652 - Ports mail
tweaks from frontier to delta-v, adding large packages, RPDs (mail
cannons), and more mail
- DeltaV-Station/Delta-v#1788 - Adding a couple
more packages
- DeltaV-Station/Delta-v#1925 - Fixing the
non-functional "last known location" part of mail descriptions

Some mail items, such as the opporozidone syringe and rainbow
joints/blunts, had to be disabled because we don't have them (yet?)

<details><summary><h1>Media</h1></summary>
<p>


![image](https://github.com/user-attachments/assets/2299ffc3-17ce-4743-886c-7705e8789e96)


![image](https://github.com/user-attachments/assets/a2ee1a07-d765-41e7-8f70-f94a50412398)


![image](https://github.com/user-attachments/assets/03b16b8e-0eff-4332-99ad-d4a201ee8f2b)


![image](https://github.com/user-attachments/assets/44d2e5c2-db79-4d8d-8877-693648edd35d)


![image](https://github.com/user-attachments/assets/f3d7bdbb-fc14-4f2f-bf30-aa54fdf49099)


![image](https://github.com/user-attachments/assets/b1e4c53f-c9d8-496b-a72e-f4f4b702e368)

</p>
</details>

---

# Changelog
:cl:
- add: The Courier and Logistics Officer now have a new program in their
PDA for tracking mail delivery performance, including earnings and
percent of packages opened, damaged, or expired.
- add: The list of possible mail packages has been greately expanded,
and now includes large parcels.
- add: The CourierDrobe now offers a rapid mail delivery device, along
with capsules for it.

---------

Signed-off-by: Adeinitas <147965189+adeinitas@users.noreply.github.com>
Co-authored-by: portfiend <109661617+portfiend@users.noreply.github.com>
Co-authored-by: byte <50130120+huckleton@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: Adeinitas <147965189+adeinitas@users.noreply.github.com>
Co-authored-by: ErhardSteinhauer <65374927+ErhardSteinhauer@users.noreply.github.com>
Co-authored-by: Dvir <dvirf01@gmail.com>
Co-authored-by: Dvir <39403717+dvir001@users.noreply.github.com>
Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com>
Co-authored-by: Whatstone <whatstone3@gmail.com>
Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com>
Co-authored-by: Milon <plmilonpl@gmail.com>
  • Loading branch information
12 people authored Oct 13, 2024
1 parent 120f73d commit 6a815ba
Show file tree
Hide file tree
Showing 86 changed files with 5,070 additions and 2,099 deletions.
28 changes: 28 additions & 0 deletions Content.Client/CartridgeLoader/Cartridges/MailMetricUi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Content.Client.UserInterface.Fragments;
using Content.Shared.CartridgeLoader.Cartridges;
using Robust.Client.UserInterface;

namespace Content.Client.CartridgeLoader.Cartridges;

public sealed partial class MailMetricUi : UIFragment
{
private MailMetricUiFragment? _fragment;

public override Control GetUIFragmentRoot()
{
return _fragment!;
}

public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
{
_fragment = new MailMetricUiFragment();
}

public override void UpdateState(BoundUserInterfaceState state)
{
if (state is MailMetricUiState cast)
{
_fragment?.UpdateState(cast);
}
}
}
183 changes: 183 additions & 0 deletions Content.Client/CartridgeLoader/Cartridges/MailMetricUiFragment.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<cartridges:MailMetricUiFragment
xmlns:cartridges="clr-namespace:Content.Client.CartridgeLoader.Cartridges"
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns="https://spacestation14.io"
Margin="5"
VerticalExpand="True"
Orientation="Vertical">
<PanelContainer StyleClasses="BackgroundDark"></PanelContainer>
<controls:StripeBack Name="MailMetricHeaderContainer">
<PanelContainer>
<Label Name="MailMetricHeader"
Align="Center"
Text="{Loc 'mail-metrics-header'}" />
</PanelContainer>
</controls:StripeBack>
<BoxContainer
Orientation="Vertical"
HorizontalExpand="True"
Margin="20 0">
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="2">
<Label Name="TitleEmpty1"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True" />
<Label Name="MailCountLabel"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
ClipText="True"
StyleClasses="monospace"
Align="Center"
Text="{Loc 'mail-metrics-count-header'}" />
<Label Name="SpesosLabel"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
ClipText="True"
Align="Center"
StyleClasses="monospace"
Text="{Loc 'mail-metrics-money-header'}" />
</BoxContainer>
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="2">
<Label Name="OpenedLabel"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"
Text="{Loc 'mail-metrics-opened'}" />
<Label Name="OpenedMailCount"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
<Label Name="OpenedMailSpesos"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="2">
<Label Name="ExpiredLabel"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"
Text="{Loc 'mail-metrics-expired'}" />
<Label Name="ExpiredMailCount"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
<Label Name="ExpiredMailSpesos"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="2">
<Label Name="TamperedLabel"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"
Text="{Loc 'mail-metrics-tampered'}" />
<Label Name="TamperedMailCount"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
<Label Name="TamperedMailSpesos"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="2">
<Label Name="DamagedLabel"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"
Text="{Loc 'mail-metrics-damaged'}" />
<Label Name="DamagedMailCount"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
<Label Name="DamagedMailSpesos"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
StyleClasses="monospace"
Align="Right"
ClipText="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="2">
<Label Name="UnopenedLabel"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"
Text="{Loc 'mail-metrics-unopened'}" />
<Label Name="UnopenedMailCount"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
StyleClasses="monospace"
Align="Right"
ClipText="True" />
<Label Name="UnopenedMailSpesos"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
</BoxContainer>
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="2">
<Label Name="TotalMailLabel"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"
Text="{Loc 'mail-metrics-total'}" />
<Label Name="TotalMailCount"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
<Label Name="TotalMailSpesos"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
Align="Right"
StyleClasses="monospace"
ClipText="True" />
</BoxContainer>
</BoxContainer>
<BoxContainer
Orientation="Vertical"
HorizontalExpand="True"
Margin="10">
<Label
Name="SuccessRateCounts"
Align="Center"
StyleClasses="LabelBig" />
<Label
Name="SuccessRatePercent"
Align="Center"
StyleClasses="LabelBig" />
</BoxContainer>
</cartridges:MailMetricUiFragment>
104 changes: 104 additions & 0 deletions Content.Client/CartridgeLoader/Cartridges/MailMetricUiFragment.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using Content.Shared.CartridgeLoader.Cartridges;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;

namespace Content.Client.CartridgeLoader.Cartridges;

[GenerateTypedNameReferences]
public sealed partial class MailMetricUiFragment : BoxContainer
{

private OpenedMailPercentGrade? _successGrade;

public MailMetricUiFragment()
{
RobustXamlLoader.Load(this);

// This my way of adding multiple classes to a XAML control.
// Haha Batman I'm going to blow up Gotham City
OpenedMailCount.StyleClasses.Add("Good");
OpenedMailSpesos.StyleClasses.Add("Good");
TamperedMailCount.StyleClasses.Add("Danger");
TamperedMailSpesos.StyleClasses.Add("Danger");
ExpiredMailCount.StyleClasses.Add("Danger");
ExpiredMailSpesos.StyleClasses.Add("Danger");
DamagedMailCount.StyleClasses.Add("Danger");
DamagedMailSpesos.StyleClasses.Add("Danger");
UnopenedMailCount.StyleClasses.Add("Caution");
}

public void UpdateState(MailMetricUiState state)
{
UpdateTextLabels(state);
UpdateSuccessGrade(state);
}

public void UpdateTextLabels(MailMetricUiState state)
{
var stats = state.Metrics;

OpenedMailCount.Text = stats.OpenedCount.ToString();
OpenedMailSpesos.Text = stats.Earnings.ToString();
TamperedMailCount.Text = stats.TamperedCount.ToString();
TamperedMailSpesos.Text = stats.TamperedLosses.ToString();
ExpiredMailCount.Text = stats.ExpiredCount.ToString();
ExpiredMailSpesos.Text = stats.ExpiredLosses.ToString();
DamagedMailCount.Text = stats.DamagedCount.ToString();
DamagedMailSpesos.Text = stats.DamagedLosses.ToString();
UnopenedMailCount.Text = state.UnopenedMailCount.ToString();
TotalMailCount.Text = state.TotalMail.ToString();
TotalMailSpesos.Text = stats.TotalIncome.ToString();
SuccessRateCounts.Text = Loc.GetString("mail-metrics-progress",
("opened", stats.OpenedCount),
("total", state.TotalMail));
SuccessRatePercent.Text = Loc.GetString("mail-metrics-progress-percent",
("successRate", state.SuccessRate));
}

public void UpdateSuccessGrade(MailMetricUiState state)
{
var previousGrade = _successGrade;
_successGrade = GetSuccessRateGrade(state.SuccessRate);

// No need to update if they're the same
if (previousGrade == _successGrade)
return;

var previousGradeClass = GetClassForGrade(previousGrade);
if (previousGradeClass != string.Empty)
{
SuccessRatePercent.StyleClasses.Remove(previousGradeClass);
}

SuccessRatePercent.StyleClasses.Add(GetClassForGrade(_successGrade));
}

private static OpenedMailPercentGrade GetSuccessRateGrade(double successRate)
{
return successRate switch
{
> 75 => OpenedMailPercentGrade.Good,
> 50 => OpenedMailPercentGrade.Average,
_ => OpenedMailPercentGrade.Bad,
};
}

private string GetClassForGrade(OpenedMailPercentGrade? grade)
{
return grade switch
{
OpenedMailPercentGrade.Good => "Good",
OpenedMailPercentGrade.Average => "Caution",
OpenedMailPercentGrade.Bad => "Danger",
_ => string.Empty,
};
}
}

enum OpenedMailPercentGrade
{
Good,
Average,
Bad
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Content.Shared.Cargo;
using Content.Shared.CartridgeLoader.Cartridges;

namespace Content.Server.Cargo.Components;

/// <summary>
/// Added to the abstract representation of a station to track stats related to mail delivery and income
/// </summary>
[RegisterComponent, Access(typeof(SharedCargoSystem))]
public sealed partial class StationLogisticStatsComponent : Component
{
[DataField]
public MailStats Metrics { get; set; }
}
63 changes: 63 additions & 0 deletions Content.Server/Cargo/Systems/LogisticStatsSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Content.Shared.Cargo;
using Content.Server.Cargo.Components;
using JetBrains.Annotations;

namespace Content.Server.Cargo.Systems;

public sealed partial class LogisticStatsSystem : SharedCargoSystem
{
[PublicAPI]
public void AddOpenedMailEarnings(EntityUid uid, StationLogisticStatsComponent component, int earnedMoney)
{
component.Metrics = component.Metrics with
{
Earnings = component.Metrics.Earnings + earnedMoney,
OpenedCount = component.Metrics.OpenedCount + 1
};
UpdateLogisticsStats(uid);
}

[PublicAPI]
public void AddExpiredMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
{
component.Metrics = component.Metrics with
{
ExpiredLosses = component.Metrics.ExpiredLosses + lostMoney,
ExpiredCount = component.Metrics.ExpiredCount + 1
};
UpdateLogisticsStats(uid);
}

[PublicAPI]
public void AddDamagedMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
{
component.Metrics = component.Metrics with
{
DamagedLosses = component.Metrics.DamagedLosses + lostMoney,
DamagedCount = component.Metrics.DamagedCount + 1
};
UpdateLogisticsStats(uid);
}

[PublicAPI]
public void AddTamperedMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
{
component.Metrics = component.Metrics with
{
TamperedLosses = component.Metrics.TamperedLosses + lostMoney,
TamperedCount = component.Metrics.TamperedCount + 1
};
UpdateLogisticsStats(uid);
}

private void UpdateLogisticsStats(EntityUid uid) => RaiseLocalEvent(new LogisticStatsUpdatedEvent(uid));
}

public sealed class LogisticStatsUpdatedEvent : EntityEventArgs
{
public EntityUid Station;
public LogisticStatsUpdatedEvent(EntityUid station)
{
Station = station;
}
}
Loading

0 comments on commit 6a815ba

Please sign in to comment.