From 25c6538b089eeaecd5481f705a1040df50cdc277 Mon Sep 17 00:00:00 2001
From: Whatstone <166147148+whatston3@users.noreply.github.com>
Date: Fri, 18 Oct 2024 11:30:53 -0400
Subject: [PATCH] End of Round Cash Summary Revision (#2276)
---
Content.Server/_NF/Bank/BankSystem.cs | 32 ++++-
.../_NF/GameRule/NfAdventureRuleSystem.cs | 129 +++++++++++++++---
.../Locale/en-US/_NF/adventure/adventure.ftl | 12 +-
.../round-end/round-end-summary-window.ftl | 5 +-
4 files changed, 152 insertions(+), 26 deletions(-)
diff --git a/Content.Server/_NF/Bank/BankSystem.cs b/Content.Server/_NF/Bank/BankSystem.cs
index 18c7670e181..7bcc1421225 100644
--- a/Content.Server/_NF/Bank/BankSystem.cs
+++ b/Content.Server/_NF/Bank/BankSystem.cs
@@ -208,11 +208,11 @@ public bool TryBankDeposit(ICommonSession session, PlayerPreferences prefs, Huma
}
///
- /// Attempts to add money to a character's bank account. This should always be used instead of attempting to modify the bankaccountcomponent directly
+ /// Retrieves a character's balance via its in-game entity, if it has one.
///
/// The UID that the bank account is connected to, typically the player controlled mob
- /// The amount of spesos to add into the bank account
- /// true if the transaction was successful, false if it was not
+ /// When successful, contains the account balance in spesos. Otherwise, set to 0.
+ /// true if the account was successfully queried.
public bool TryGetBalance(EntityUid ent, out int balance)
{
if (!_playerManager.TryGetSessionByEntity(ent, out var session) ||
@@ -234,6 +234,32 @@ public bool TryGetBalance(EntityUid ent, out int balance)
return true;
}
+ ///
+ /// Retrieves a character's balance via a player's session.
+ ///
+ /// The session of the player character to query.
+ /// When successful, contains the account balance in spesos. Otherwise, set to 0.
+ /// true if the account was successfully queried.
+ public bool TryGetBalance(ICommonSession session, out int balance)
+ {
+ if (!_prefsManager.TryGetCachedPreferences(session.UserId, out var prefs))
+ {
+ _log.Info($"{session.UserId} has no cached prefs");
+ balance = 0;
+ return false;
+ }
+
+ if (prefs.SelectedCharacter is not HumanoidCharacterProfile profile)
+ {
+ _log.Info($"{session.UserId} has the wrong prefs type");
+ balance = 0;
+ return false;
+ }
+
+ balance = profile.BankBalance;
+ return true;
+ }
+
///
/// Update the bank balance to the character's current account balance.
///
diff --git a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs
index c6b88987d95..475fe794447 100644
--- a/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs
+++ b/Content.Server/_NF/GameRule/NfAdventureRuleSystem.cs
@@ -7,7 +7,6 @@
using System.Threading.Tasks;
using Content.Shared._NF.GameRule;
using Content.Server.Procedural;
-using Content.Shared.Bank.Components;
using Content.Server._NF.GameTicking.Events;
using Content.Shared.Procedural;
using Robust.Server.GameObjects;
@@ -30,9 +29,16 @@
using Robust.Shared.Configuration;
using Robust.Shared.Physics.Components;
using Content.Server.Shuttles.Components;
+using Content.Shared._NF.Bank;
using Content.Shared.Tiles;
using Content.Server._NF.PublicTransit.Components;
using Content.Server._NF.GameRule.Components;
+using Content.Server.Bank;
+using Robust.Shared.Player;
+using Robust.Shared.Network;
+using Content.Shared.GameTicking;
+using Robust.Shared.Enums;
+using Robust.Server.Player;
namespace Content.Server._NF.GameRule;
@@ -44,6 +50,7 @@ public sealed class NfAdventureRuleSystem : GameRuleSystem _players = new();
+ private Dictionary _players = new();
private float _distanceOffset = 1f;
private List _stationCoords = new();
@@ -67,23 +97,40 @@ public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent(OnPlayerSpawningEvent);
+ SubscribeLocalEvent(OnPlayerDetachedEvent);
+ SubscribeLocalEvent(OnRoundRestart);
+ _playerManager.PlayerStatusChanged += PlayerManagerOnPlayerStatusChanged;
}
protected override void AppendRoundEndText(EntityUid uid, AdventureRuleComponent component, GameRuleComponent gameRule, ref RoundEndTextAppendEvent ev)
{
- var profitText = Loc.GetString($"adventure-mode-profit-text");
- var lossText = Loc.GetString($"adventure-mode-loss-text");
ev.AddLine(Loc.GetString("adventure-list-start"));
var allScore = new List>();
- foreach (var player in _players)
+ foreach (var (player, playerInfo) in _players)
{
- if (!TryComp(player.Item1, out var bank) || !TryComp(player.Item1, out var meta))
+ var endBalance = playerInfo.EndBalance;
+ if (_bank.TryGetBalance(player, out var bankBalance))
+ {
+ endBalance = bankBalance;
+ }
+
+ // Check if endBalance is valid (non-negative)
+ if (endBalance < 0)
continue;
- var profit = bank.Balance - player.Item2;
- ev.AddLine($"- {meta.EntityName} {profitText} {profit} Spesos");
- allScore.Add(new Tuple(meta.EntityName, profit));
+ var profit = endBalance - playerInfo.StartBalance;
+ string summaryText;
+ if (profit < 0)
+ {
+ summaryText = Loc.GetString("adventure-mode-list-loss", ("amount", BankSystemExtensions.ToSpesoString(-profit)));
+ }
+ else
+ {
+ summaryText = Loc.GetString("adventure-mode-list-profit", ("amount", BankSystemExtensions.ToSpesoString(profit)));
+ }
+ ev.AddLine($"- {playerInfo.Name} {summaryText}");
+ allScore.Add(new Tuple(playerInfo.Name, profit));
}
if (!(allScore.Count >= 1))
@@ -93,20 +140,27 @@ protected override void AppendRoundEndText(EntityUid uid, AdventureRuleComponent
relayText += '\n';
var highScore = allScore.OrderByDescending(h => h.Item2).ToList();
- for (var i = 0; i < 10 && i < highScore.Count; i++)
+ for (var i = 0; i < 10 && highScore.Count > 0; i++)
{
- relayText += $"{highScore.First().Item1} {profitText} {highScore.First().Item2} Spesos";
+ if (highScore.First().Item2 < 0)
+ break;
+ var profitText = Loc.GetString("adventure-mode-top-profit", ("amount", BankSystemExtensions.ToSpesoString(highScore.First().Item2)));
+ relayText += $"{highScore.First().Item1} {profitText}";
relayText += '\n';
- highScore.Remove(highScore.First());
+ highScore.RemoveAt(0);
}
+ relayText += '\n'; // Extra line separating the
relayText += Loc.GetString("adventure-list-low");
relayText += '\n';
highScore.Reverse();
- for (var i = 0; i < 10 && i < highScore.Count; i++)
+ for (var i = 0; i < 10 && highScore.Count > 0; i++)
{
- relayText += $"{highScore.First().Item1} {lossText} {highScore.First().Item2} Spesos";
+ if (highScore.First().Item2 > 0)
+ break;
+ var lossText = Loc.GetString("adventure-mode-top-loss", ("amount", BankSystemExtensions.ToSpesoString(-highScore.First().Item2)));
+ relayText += $"{highScore.First().Item1} {lossText}";
relayText += '\n';
- highScore.Remove(highScore.First());
+ highScore.RemoveAt(0);
}
ReportRound(relayText);
}
@@ -115,11 +169,52 @@ private void OnPlayerSpawningEvent(PlayerSpawnCompleteEvent ev)
{
if (ev.Player.AttachedEntity is { Valid: true } mobUid)
{
- _players.Add((mobUid, ev.Profile.BankBalance));
EnsureComp(mobUid);
+
+ // Store player info with the bank balance - we have it directly, and BankSystem won't have a cache yet.
+ if (!_players.ContainsKey(mobUid))
+ _players[mobUid] = new PlayerRoundBankInformation(ev.Profile.BankBalance, MetaData(mobUid).EntityName, ev.Player.UserId);
}
}
+ private void OnPlayerDetachedEvent(PlayerDetachedEvent ev)
+ {
+ if (ev.Entity is not { Valid: true } mobUid)
+ return;
+
+ if (_players.ContainsKey(mobUid))
+ {
+ if (_players[mobUid].UserId == ev.Player.UserId &&
+ _bank.TryGetBalance(ev.Player, out var bankBalance))
+ {
+ _players[mobUid].EndBalance = bankBalance;
+ }
+ }
+ }
+
+ private void PlayerManagerOnPlayerStatusChanged(object? _, SessionStatusEventArgs e)
+ {
+ // Treat all disconnections as being possibly final.
+ if (e.NewStatus != SessionStatus.Disconnected ||
+ e.Session.AttachedEntity == null)
+ return;
+
+ var mobUid = e.Session.AttachedEntity.Value;
+ if (_players.ContainsKey(mobUid))
+ {
+ if (_players[mobUid].UserId == e.Session.UserId &&
+ _bank.TryGetBalance(e.Session, out var bankBalance))
+ {
+ _players[mobUid].EndBalance = bankBalance;
+ }
+ }
+ }
+
+ private void OnRoundRestart(RoundRestartCleanupEvent ev)
+ {
+ _players.Clear();
+ }
+
protected override void Started(EntityUid uid, AdventureRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
{
_mapId = GameTicker.DefaultMap;
@@ -439,7 +534,7 @@ private void AddStationCoordsToSet(Vector2 coords)
_stationCoords.Add(coords);
}
- private async Task ReportRound(String message, int color = 0x77DDE7)
+ private async Task ReportRound(String message, int color = 0x77DDE7)
{
Logger.InfoS("discord", message);
String webhookUrl = _configurationManager.GetCVar(CCVars.DiscordLeaderboardWebhook);
diff --git a/Resources/Locale/en-US/_NF/adventure/adventure.ftl b/Resources/Locale/en-US/_NF/adventure/adventure.ftl
index c65acd137c1..4930e8675b3 100644
--- a/Resources/Locale/en-US/_NF/adventure/adventure.ftl
+++ b/Resources/Locale/en-US/_NF/adventure/adventure.ftl
@@ -1,9 +1,11 @@
## UI
-adventure-list-start = NT Galactic Bank
-adventure-mode-profit-text = made a total profit of: {" "}
-adventure-mode-loss-text = lost a total of: {" "}
-adventure-list-high = Today's Top Earners:
-adventure-list-low = Today's Biggest Spenders:
+adventure-list-start = [color=gold]NT Galactic Bank[/color]
+adventure-mode-list-profit = made a total profit of [color=#d19e5e]{$amount}[/color].
+adventure-mode-list-loss = lost a total of [color=#659cc9]{$amount}[/color].
+adventure-mode-top-profit = made a total profit of {$amount}.
+adventure-mode-top-loss = lost a total of {$amount}.
+adventure-list-high = This Shift's Top Earners:
+adventure-list-low = This Shift's Biggest Spenders:
adventure-title = New Frontier Adventure Mode
adventure-description = Join a ship crew or buy your own and explore, research, salvage, or haul your way to riches!
currency = Spesos
diff --git a/Resources/Locale/en-US/round-end/round-end-summary-window.ftl b/Resources/Locale/en-US/round-end/round-end-summary-window.ftl
index 58d26319b32..11f88052265 100644
--- a/Resources/Locale/en-US/round-end/round-end-summary-window.ftl
+++ b/Resources/Locale/en-US/round-end/round-end-summary-window.ftl
@@ -2,7 +2,10 @@ round-end-summary-window-title = Round End Summary
round-end-summary-window-round-end-summary-tab-title = Round Information
round-end-summary-window-player-manifest-tab-title = Player Manifest
round-end-summary-window-round-id-label = Round [color=white]#{$roundId}[/color] has ended.
-round-end-summary-window-gamemode-name-label = The game mode was [color=white]{$gamemode}[/color].
+# Frontier
+round-end-summary-window-gamemode-name-label = {""}
+# round-end-summary-window-gamemode-name-label = The game mode was [color=white]{$gamemode}[/color].
+# End Frontier
round-end-summary-window-duration-label = It lasted for [color=yellow]{$hours} hours, {$minutes} minutes, and {$seconds} seconds.
round-end-summary-window-player-info-if-observer-text = [color=gray]{$playerOOCName}[/color] was [color=lightblue]{$playerICName}[/color], an observer.
round-end-summary-window-player-info-if-not-observer-text = [color=gray]{$playerOOCName}[/color] was [color={$icNameColor}]{$playerICName}[/color] playing role of [color=orange]{$playerRole}[/color].