Skip to content

Commit 6a815ba

Browse files
MnemotechnicianportfiendhuckletondeltanedasAdeinitas
authored
Feat: Port All Delta-V Mail Improvements (#1011)
# 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 <[email protected]> Co-authored-by: portfiend <[email protected]> Co-authored-by: byte <[email protected]> Co-authored-by: deltanedas <[email protected]> Co-authored-by: Adeinitas <[email protected]> Co-authored-by: ErhardSteinhauer <[email protected]> Co-authored-by: Dvir <[email protected]> Co-authored-by: Dvir <[email protected]> Co-authored-by: Whatstone <[email protected]> Co-authored-by: Whatstone <[email protected]> Co-authored-by: Danger Revolution! <[email protected]> Co-authored-by: Milon <[email protected]>
1 parent 120f73d commit 6a815ba

File tree

86 files changed

+5070
-2099
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+5070
-2099
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Content.Client.UserInterface.Fragments;
2+
using Content.Shared.CartridgeLoader.Cartridges;
3+
using Robust.Client.UserInterface;
4+
5+
namespace Content.Client.CartridgeLoader.Cartridges;
6+
7+
public sealed partial class MailMetricUi : UIFragment
8+
{
9+
private MailMetricUiFragment? _fragment;
10+
11+
public override Control GetUIFragmentRoot()
12+
{
13+
return _fragment!;
14+
}
15+
16+
public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
17+
{
18+
_fragment = new MailMetricUiFragment();
19+
}
20+
21+
public override void UpdateState(BoundUserInterfaceState state)
22+
{
23+
if (state is MailMetricUiState cast)
24+
{
25+
_fragment?.UpdateState(cast);
26+
}
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<cartridges:MailMetricUiFragment
2+
xmlns:cartridges="clr-namespace:Content.Client.CartridgeLoader.Cartridges"
3+
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
4+
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
5+
xmlns="https://spacestation14.io"
6+
Margin="5"
7+
VerticalExpand="True"
8+
Orientation="Vertical">
9+
<PanelContainer StyleClasses="BackgroundDark"></PanelContainer>
10+
<controls:StripeBack Name="MailMetricHeaderContainer">
11+
<PanelContainer>
12+
<Label Name="MailMetricHeader"
13+
Align="Center"
14+
Text="{Loc 'mail-metrics-header'}" />
15+
</PanelContainer>
16+
</controls:StripeBack>
17+
<BoxContainer
18+
Orientation="Vertical"
19+
HorizontalExpand="True"
20+
Margin="20 0">
21+
<BoxContainer Orientation="Horizontal"
22+
HorizontalExpand="True"
23+
SeparationOverride="2">
24+
<Label Name="TitleEmpty1"
25+
SizeFlagsStretchRatio="2"
26+
HorizontalExpand="True"
27+
ClipText="True" />
28+
<Label Name="MailCountLabel"
29+
SizeFlagsStretchRatio="1"
30+
HorizontalExpand="True"
31+
ClipText="True"
32+
StyleClasses="monospace"
33+
Align="Center"
34+
Text="{Loc 'mail-metrics-count-header'}" />
35+
<Label Name="SpesosLabel"
36+
SizeFlagsStretchRatio="1"
37+
HorizontalExpand="True"
38+
ClipText="True"
39+
Align="Center"
40+
StyleClasses="monospace"
41+
Text="{Loc 'mail-metrics-money-header'}" />
42+
</BoxContainer>
43+
<BoxContainer Orientation="Horizontal"
44+
HorizontalExpand="True"
45+
SeparationOverride="2">
46+
<Label Name="OpenedLabel"
47+
SizeFlagsStretchRatio="2"
48+
HorizontalExpand="True"
49+
ClipText="True"
50+
Text="{Loc 'mail-metrics-opened'}" />
51+
<Label Name="OpenedMailCount"
52+
SizeFlagsStretchRatio="1"
53+
HorizontalExpand="True"
54+
Align="Right"
55+
StyleClasses="monospace"
56+
ClipText="True" />
57+
<Label Name="OpenedMailSpesos"
58+
SizeFlagsStretchRatio="1"
59+
HorizontalExpand="True"
60+
Align="Right"
61+
StyleClasses="monospace"
62+
ClipText="True" />
63+
</BoxContainer>
64+
<BoxContainer Orientation="Horizontal"
65+
HorizontalExpand="True"
66+
SeparationOverride="2">
67+
<Label Name="ExpiredLabel"
68+
SizeFlagsStretchRatio="2"
69+
HorizontalExpand="True"
70+
ClipText="True"
71+
Text="{Loc 'mail-metrics-expired'}" />
72+
<Label Name="ExpiredMailCount"
73+
SizeFlagsStretchRatio="1"
74+
HorizontalExpand="True"
75+
Align="Right"
76+
StyleClasses="monospace"
77+
ClipText="True" />
78+
<Label Name="ExpiredMailSpesos"
79+
SizeFlagsStretchRatio="1"
80+
HorizontalExpand="True"
81+
Align="Right"
82+
StyleClasses="monospace"
83+
ClipText="True" />
84+
</BoxContainer>
85+
<BoxContainer Orientation="Horizontal"
86+
HorizontalExpand="True"
87+
SeparationOverride="2">
88+
<Label Name="TamperedLabel"
89+
SizeFlagsStretchRatio="2"
90+
HorizontalExpand="True"
91+
ClipText="True"
92+
Text="{Loc 'mail-metrics-tampered'}" />
93+
<Label Name="TamperedMailCount"
94+
SizeFlagsStretchRatio="1"
95+
HorizontalExpand="True"
96+
Align="Right"
97+
StyleClasses="monospace"
98+
ClipText="True" />
99+
<Label Name="TamperedMailSpesos"
100+
SizeFlagsStretchRatio="1"
101+
HorizontalExpand="True"
102+
Align="Right"
103+
StyleClasses="monospace"
104+
ClipText="True" />
105+
</BoxContainer>
106+
<BoxContainer Orientation="Horizontal"
107+
HorizontalExpand="True"
108+
SeparationOverride="2">
109+
<Label Name="DamagedLabel"
110+
SizeFlagsStretchRatio="2"
111+
HorizontalExpand="True"
112+
ClipText="True"
113+
Text="{Loc 'mail-metrics-damaged'}" />
114+
<Label Name="DamagedMailCount"
115+
SizeFlagsStretchRatio="1"
116+
HorizontalExpand="True"
117+
Align="Right"
118+
StyleClasses="monospace"
119+
ClipText="True" />
120+
<Label Name="DamagedMailSpesos"
121+
SizeFlagsStretchRatio="1"
122+
HorizontalExpand="True"
123+
StyleClasses="monospace"
124+
Align="Right"
125+
ClipText="True" />
126+
</BoxContainer>
127+
<BoxContainer Orientation="Horizontal"
128+
HorizontalExpand="True"
129+
SeparationOverride="2">
130+
<Label Name="UnopenedLabel"
131+
SizeFlagsStretchRatio="2"
132+
HorizontalExpand="True"
133+
ClipText="True"
134+
Text="{Loc 'mail-metrics-unopened'}" />
135+
<Label Name="UnopenedMailCount"
136+
SizeFlagsStretchRatio="1"
137+
HorizontalExpand="True"
138+
StyleClasses="monospace"
139+
Align="Right"
140+
ClipText="True" />
141+
<Label Name="UnopenedMailSpesos"
142+
SizeFlagsStretchRatio="1"
143+
HorizontalExpand="True"
144+
Align="Right"
145+
StyleClasses="monospace"
146+
ClipText="True" />
147+
</BoxContainer>
148+
<BoxContainer Orientation="Horizontal"
149+
HorizontalExpand="True"
150+
SeparationOverride="2">
151+
<Label Name="TotalMailLabel"
152+
SizeFlagsStretchRatio="2"
153+
HorizontalExpand="True"
154+
ClipText="True"
155+
Text="{Loc 'mail-metrics-total'}" />
156+
<Label Name="TotalMailCount"
157+
SizeFlagsStretchRatio="1"
158+
HorizontalExpand="True"
159+
Align="Right"
160+
StyleClasses="monospace"
161+
ClipText="True" />
162+
<Label Name="TotalMailSpesos"
163+
SizeFlagsStretchRatio="1"
164+
HorizontalExpand="True"
165+
Align="Right"
166+
StyleClasses="monospace"
167+
ClipText="True" />
168+
</BoxContainer>
169+
</BoxContainer>
170+
<BoxContainer
171+
Orientation="Vertical"
172+
HorizontalExpand="True"
173+
Margin="10">
174+
<Label
175+
Name="SuccessRateCounts"
176+
Align="Center"
177+
StyleClasses="LabelBig" />
178+
<Label
179+
Name="SuccessRatePercent"
180+
Align="Center"
181+
StyleClasses="LabelBig" />
182+
</BoxContainer>
183+
</cartridges:MailMetricUiFragment>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using Content.Shared.CartridgeLoader.Cartridges;
2+
using Robust.Client.AutoGenerated;
3+
using Robust.Client.UserInterface.Controls;
4+
using Robust.Client.UserInterface.XAML;
5+
6+
namespace Content.Client.CartridgeLoader.Cartridges;
7+
8+
[GenerateTypedNameReferences]
9+
public sealed partial class MailMetricUiFragment : BoxContainer
10+
{
11+
12+
private OpenedMailPercentGrade? _successGrade;
13+
14+
public MailMetricUiFragment()
15+
{
16+
RobustXamlLoader.Load(this);
17+
18+
// This my way of adding multiple classes to a XAML control.
19+
// Haha Batman I'm going to blow up Gotham City
20+
OpenedMailCount.StyleClasses.Add("Good");
21+
OpenedMailSpesos.StyleClasses.Add("Good");
22+
TamperedMailCount.StyleClasses.Add("Danger");
23+
TamperedMailSpesos.StyleClasses.Add("Danger");
24+
ExpiredMailCount.StyleClasses.Add("Danger");
25+
ExpiredMailSpesos.StyleClasses.Add("Danger");
26+
DamagedMailCount.StyleClasses.Add("Danger");
27+
DamagedMailSpesos.StyleClasses.Add("Danger");
28+
UnopenedMailCount.StyleClasses.Add("Caution");
29+
}
30+
31+
public void UpdateState(MailMetricUiState state)
32+
{
33+
UpdateTextLabels(state);
34+
UpdateSuccessGrade(state);
35+
}
36+
37+
public void UpdateTextLabels(MailMetricUiState state)
38+
{
39+
var stats = state.Metrics;
40+
41+
OpenedMailCount.Text = stats.OpenedCount.ToString();
42+
OpenedMailSpesos.Text = stats.Earnings.ToString();
43+
TamperedMailCount.Text = stats.TamperedCount.ToString();
44+
TamperedMailSpesos.Text = stats.TamperedLosses.ToString();
45+
ExpiredMailCount.Text = stats.ExpiredCount.ToString();
46+
ExpiredMailSpesos.Text = stats.ExpiredLosses.ToString();
47+
DamagedMailCount.Text = stats.DamagedCount.ToString();
48+
DamagedMailSpesos.Text = stats.DamagedLosses.ToString();
49+
UnopenedMailCount.Text = state.UnopenedMailCount.ToString();
50+
TotalMailCount.Text = state.TotalMail.ToString();
51+
TotalMailSpesos.Text = stats.TotalIncome.ToString();
52+
SuccessRateCounts.Text = Loc.GetString("mail-metrics-progress",
53+
("opened", stats.OpenedCount),
54+
("total", state.TotalMail));
55+
SuccessRatePercent.Text = Loc.GetString("mail-metrics-progress-percent",
56+
("successRate", state.SuccessRate));
57+
}
58+
59+
public void UpdateSuccessGrade(MailMetricUiState state)
60+
{
61+
var previousGrade = _successGrade;
62+
_successGrade = GetSuccessRateGrade(state.SuccessRate);
63+
64+
// No need to update if they're the same
65+
if (previousGrade == _successGrade)
66+
return;
67+
68+
var previousGradeClass = GetClassForGrade(previousGrade);
69+
if (previousGradeClass != string.Empty)
70+
{
71+
SuccessRatePercent.StyleClasses.Remove(previousGradeClass);
72+
}
73+
74+
SuccessRatePercent.StyleClasses.Add(GetClassForGrade(_successGrade));
75+
}
76+
77+
private static OpenedMailPercentGrade GetSuccessRateGrade(double successRate)
78+
{
79+
return successRate switch
80+
{
81+
> 75 => OpenedMailPercentGrade.Good,
82+
> 50 => OpenedMailPercentGrade.Average,
83+
_ => OpenedMailPercentGrade.Bad,
84+
};
85+
}
86+
87+
private string GetClassForGrade(OpenedMailPercentGrade? grade)
88+
{
89+
return grade switch
90+
{
91+
OpenedMailPercentGrade.Good => "Good",
92+
OpenedMailPercentGrade.Average => "Caution",
93+
OpenedMailPercentGrade.Bad => "Danger",
94+
_ => string.Empty,
95+
};
96+
}
97+
}
98+
99+
enum OpenedMailPercentGrade
100+
{
101+
Good,
102+
Average,
103+
Bad
104+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Content.Shared.Cargo;
2+
using Content.Shared.CartridgeLoader.Cartridges;
3+
4+
namespace Content.Server.Cargo.Components;
5+
6+
/// <summary>
7+
/// Added to the abstract representation of a station to track stats related to mail delivery and income
8+
/// </summary>
9+
[RegisterComponent, Access(typeof(SharedCargoSystem))]
10+
public sealed partial class StationLogisticStatsComponent : Component
11+
{
12+
[DataField]
13+
public MailStats Metrics { get; set; }
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using Content.Shared.Cargo;
2+
using Content.Server.Cargo.Components;
3+
using JetBrains.Annotations;
4+
5+
namespace Content.Server.Cargo.Systems;
6+
7+
public sealed partial class LogisticStatsSystem : SharedCargoSystem
8+
{
9+
[PublicAPI]
10+
public void AddOpenedMailEarnings(EntityUid uid, StationLogisticStatsComponent component, int earnedMoney)
11+
{
12+
component.Metrics = component.Metrics with
13+
{
14+
Earnings = component.Metrics.Earnings + earnedMoney,
15+
OpenedCount = component.Metrics.OpenedCount + 1
16+
};
17+
UpdateLogisticsStats(uid);
18+
}
19+
20+
[PublicAPI]
21+
public void AddExpiredMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
22+
{
23+
component.Metrics = component.Metrics with
24+
{
25+
ExpiredLosses = component.Metrics.ExpiredLosses + lostMoney,
26+
ExpiredCount = component.Metrics.ExpiredCount + 1
27+
};
28+
UpdateLogisticsStats(uid);
29+
}
30+
31+
[PublicAPI]
32+
public void AddDamagedMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
33+
{
34+
component.Metrics = component.Metrics with
35+
{
36+
DamagedLosses = component.Metrics.DamagedLosses + lostMoney,
37+
DamagedCount = component.Metrics.DamagedCount + 1
38+
};
39+
UpdateLogisticsStats(uid);
40+
}
41+
42+
[PublicAPI]
43+
public void AddTamperedMailLosses(EntityUid uid, StationLogisticStatsComponent component, int lostMoney)
44+
{
45+
component.Metrics = component.Metrics with
46+
{
47+
TamperedLosses = component.Metrics.TamperedLosses + lostMoney,
48+
TamperedCount = component.Metrics.TamperedCount + 1
49+
};
50+
UpdateLogisticsStats(uid);
51+
}
52+
53+
private void UpdateLogisticsStats(EntityUid uid) => RaiseLocalEvent(new LogisticStatsUpdatedEvent(uid));
54+
}
55+
56+
public sealed class LogisticStatsUpdatedEvent : EntityEventArgs
57+
{
58+
public EntityUid Station;
59+
public LogisticStatsUpdatedEvent(EntityUid station)
60+
{
61+
Station = station;
62+
}
63+
}

0 commit comments

Comments
 (0)