]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Make role timer tooltips pretty (#19605)
authormetalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Mon, 11 Sep 2023 05:44:21 +0000 (15:44 +1000)
committerGitHub <noreply@github.com>
Mon, 11 Sep 2023 05:44:21 +0000 (15:44 +1000)
Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
Content.Client/LateJoin/LateJoinGui.cs
Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs
Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs
Content.Client/Roles/JobSystem.cs [new file with mode: 0644]
Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs
Content.Server/Roles/Jobs/JobSystem.cs
Content.Shared/Roles/JobRequirements.cs
Content.Shared/Roles/Jobs/SharedJobSystem.cs
Resources/Locale/en-US/job/role-timers.ftl

index dd8281ecbf5b3721cb2c508ef664ec01076bc5e9..9acfb03126109606981abbb0783f1a21e5977b79 100644 (file)
@@ -257,9 +257,11 @@ namespace Content.Client.LateJoin
                         {
                             jobButton.Disabled = true;
 
-                            if (!string.IsNullOrEmpty(reason))
+                            if (!reason.IsEmpty)
                             {
-                                jobButton.ToolTip = reason;
+                                var tooltip = new Tooltip();
+                                tooltip.SetMessage(reason);
+                                jobButton.TooltipSupplier = _ => tooltip;
                             }
 
                             jobSelector.AddChild(new TextureRect
index 25a00616104c88ecb32f986bd3b202bb3bad11a4..9d5801b925e87db09423b4c1932944c431e621da 100644 (file)
@@ -10,6 +10,7 @@ using Robust.Client.Player;
 using Robust.Shared.Configuration;
 using Robust.Shared.Network;
 using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
 
 namespace Content.Client.Players.PlayTimeTracking;
 
@@ -18,6 +19,7 @@ public sealed class JobRequirementsManager
     [Dependency] private readonly IBaseClient _client = default!;
     [Dependency] private readonly IClientNetManager _net = default!;
     [Dependency] private readonly IConfigurationManager _cfg = default!;
+    [Dependency] private readonly IEntityManager _entManager = default!;
     [Dependency] private readonly IPlayerManager _playerManager = default!;
     [Dependency] private readonly IPrototypeManager _prototypes = default!;
 
@@ -78,13 +80,13 @@ public sealed class JobRequirementsManager
         Updated?.Invoke();
     }
 
-    public bool IsAllowed(JobPrototype job, [NotNullWhen(false)] out string? reason)
+    public bool IsAllowed(JobPrototype job, [NotNullWhen(false)] out FormattedMessage? reason)
     {
         reason = null;
 
         if (_roleBans.Contains($"Job:{job.ID}"))
         {
-            reason = Loc.GetString("role-ban");
+            reason = FormattedMessage.FromUnformatted(Loc.GetString("role-ban"));
             return false;
         }
 
@@ -101,20 +103,15 @@ public sealed class JobRequirementsManager
 
         var reasonBuilder = new StringBuilder();
 
-        var first = true;
         foreach (var requirement in job.Requirements)
         {
-            if (JobRequirements.TryRequirementMet(requirement, _roles, out reason, _prototypes))
+            if (JobRequirements.TryRequirementMet(requirement, _roles, out var jobReason, _entManager, _prototypes))
                 continue;
 
-            if (!first)
-                reasonBuilder.Append('\n');
-            first = false;
-
-            reasonBuilder.AppendLine(reason);
+            reasonBuilder.AppendLine(jobReason.ToMarkup());
         }
 
-        reason = reasonBuilder.Length == 0 ? null : reasonBuilder.ToString();
+        reason = reasonBuilder.Length == 0 ? null : FormattedMessage.FromMarkup(reasonBuilder.ToString().Trim());
         return reason == null;
     }
 }
index 144477199d1a53806b025646aa794836f01ea3e1..076e4805c8c0e11c8254886b02d360d1233968d8 100644 (file)
@@ -21,6 +21,7 @@ using Robust.Client.GameObjects;
 using Robust.Client.Graphics;
 using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.CustomControls;
 using Robust.Client.UserInterface.XAML;
 using Robust.Client.Utility;
 using Robust.Shared.Configuration;
@@ -1272,9 +1273,11 @@ namespace Content.Client.Preferences.UI
                 });
             }
 
-            public void LockRequirements(string requirements)
+            public void LockRequirements(FormattedMessage requirements)
             {
-                _lockStripe.ToolTip = requirements;
+                var tooltip = new Tooltip();
+                tooltip.SetMessage(requirements);
+                _lockStripe.TooltipSupplier = _ => tooltip;
                 _lockStripe.Visible = true;
                 _optionButton.Visible = false;
             }
diff --git a/Content.Client/Roles/JobSystem.cs b/Content.Client/Roles/JobSystem.cs
new file mode 100644 (file)
index 0000000..f49bb7d
--- /dev/null
@@ -0,0 +1,9 @@
+using Content.Shared.Roles;
+using Content.Shared.Roles.Jobs;
+
+namespace Content.Client.Roles;
+
+public sealed class JobSystem : SharedJobSystem
+{
+
+}
index 3902b8e1b90698e86ad49023dc3621c80c789006..6442ef2c67cb97447a614319889e65515dee1d27 100644 (file)
@@ -165,7 +165,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
 
         var playTimes = _tracking.GetTrackerTimes(player);
 
-        return JobRequirements.TryRequirementsMet(job, playTimes, out _, _prototypes);
+        return JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes);
     }
 
     public HashSet<string> GetDisallowedJobs(IPlayerSession player)
@@ -182,7 +182,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
             {
                 foreach (var requirement in job.Requirements)
                 {
-                    if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, _prototypes))
+                    if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, EntityManager, _prototypes))
                         continue;
 
                     goto NoRole;
@@ -220,7 +220,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
 
             foreach (var requirement in jobber.Requirements)
             {
-                if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, _prototypes))
+                if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, EntityManager, _prototypes))
                     continue;
 
                 jobs.RemoveSwap(i);
index 22d62862154b31452644d714941a14084330a227..66224d1abad0542ff80f3c5d067c2891261d2974 100644 (file)
@@ -4,14 +4,18 @@ using Content.Server.Mind;
 using Content.Shared.Mind;
 using Content.Shared.Roles;
 using Content.Shared.Roles.Jobs;
+using Robust.Shared.Prototypes;
 
 namespace Content.Server.Roles.Jobs;
 
+/// <summary>
+///     Handles the job data on mind entities.
+/// </summary>
 public sealed class JobSystem : SharedJobSystem
 {
     [Dependency] private readonly IChatManager _chat = default!;
-    [Dependency] private readonly MindSystem _minds = default!;
-    [Dependency] private readonly SharedRoleSystem _roles = default!;
+    [Dependency] private readonly MindSystem _mind = default!;
+    [Dependency] private readonly RoleSystem _roles = default!;
 
     public override void Initialize()
     {
@@ -23,7 +27,7 @@ public sealed class JobSystem : SharedJobSystem
         if (args.Silent)
             return;
 
-        if (!_minds.TryGetSession(mindId, out var session))
+        if (!_mind.TryGetSession(mindId, out var session))
             return;
 
         if (!MindTryGetJob(mindId, out _, out var prototype))
index 7e0c1a98aa874c305cd18e779b6452864c9561c8..dd54ca60cf5b43d67878defd63de47becfdaf1b0 100644 (file)
@@ -1,8 +1,10 @@
 using System.Diagnostics.CodeAnalysis;
 using Content.Shared.Players.PlayTimeTracking;
+using Content.Shared.Roles.Jobs;
 using JetBrains.Annotations;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+using Robust.Shared.Utility;
 
 namespace Content.Shared.Roles
 {
@@ -67,7 +69,8 @@ namespace Content.Shared.Roles
         public static bool TryRequirementsMet(
             JobPrototype job,
             Dictionary<string, TimeSpan> playTimes,
-            [NotNullWhen(false)] out string? reason,
+            [NotNullWhen(false)] out FormattedMessage? reason,
+            IEntityManager entManager,
             IPrototypeManager prototypes)
         {
             reason = null;
@@ -76,7 +79,7 @@ namespace Content.Shared.Roles
 
             foreach (var requirement in job.Requirements)
             {
-                if (!TryRequirementMet(requirement, playTimes, out reason, prototypes))
+                if (!TryRequirementMet(requirement, playTimes, out reason, entManager, prototypes))
                     return false;
             }
 
@@ -89,9 +92,9 @@ namespace Content.Shared.Roles
         public static bool TryRequirementMet(
             JobRequirement requirement,
             Dictionary<string, TimeSpan> playTimes,
-            [NotNullWhen(false)] out string? reason,
+            [NotNullWhen(false)] out FormattedMessage? reason,
+            IEntityManager entManager,
             IPrototypeManager prototypes)
-
         {
             reason = null;
 
@@ -101,7 +104,8 @@ namespace Content.Shared.Roles
                     var playtime = TimeSpan.Zero;
 
                     // Check all jobs' departments
-                    var jobs = prototypes.Index<DepartmentPrototype>(deptRequirement.Department).Roles;
+                    var department = prototypes.Index<DepartmentPrototype>(deptRequirement.Department);
+                    var jobs = department.Roles;
                     string proto;
 
                     // Check all jobs' playtime
@@ -121,20 +125,22 @@ namespace Content.Shared.Roles
                         if (deptDiff <= 0)
                             return true;
 
-                        reason = Loc.GetString(
+                        reason = FormattedMessage.FromMarkup(Loc.GetString(
                             "role-timer-department-insufficient",
                             ("time", deptDiff),
-                            ("department", Loc.GetString(deptRequirement.Department)));
+                            ("department", Loc.GetString(deptRequirement.Department)),
+                            ("departmentColor", department.Color.ToHex())));
                         return false;
                     }
                     else
                     {
                         if (deptDiff <= 0)
                         {
-                            reason = Loc.GetString(
+                            reason = FormattedMessage.FromMarkup(Loc.GetString(
                                 "role-timer-department-too-high",
                                 ("time", -deptDiff),
-                                ("department", Loc.GetString(deptRequirement.Department)));
+                                ("department", Loc.GetString(deptRequirement.Department)),
+                                ("departmentColor", department.Color.ToHex())));
                             return false;
                         }
 
@@ -150,14 +156,14 @@ namespace Content.Shared.Roles
                         if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
                             return true;
 
-                        reason = Loc.GetString("role-timer-overall-insufficient", ("time", overallDiff));
+                        reason = FormattedMessage.FromMarkup(Loc.GetString("role-timer-overall-insufficient", ("time", overallDiff)));
                         return false;
                     }
                     else
                     {
                         if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
                         {
-                            reason = Loc.GetString("role-timer-overall-too-high", ("time", -overallDiff));
+                            reason = FormattedMessage.FromMarkup(Loc.GetString("role-timer-overall-too-high", ("time", -overallDiff)));
                             return false;
                         }
 
@@ -169,26 +175,37 @@ namespace Content.Shared.Roles
 
                     playTimes.TryGetValue(proto, out var roleTime);
                     var roleDiff = roleRequirement.Time.TotalMinutes - roleTime.TotalMinutes;
+                    var departmentColor = Color.Yellow;
+
+                    if (entManager.EntitySysManager.TryGetEntitySystem(out SharedJobSystem? jobSystem))
+                    {
+                        var jobProto = jobSystem.GetJobPrototype(proto);
+
+                        if (jobSystem.TryGetDepartment(jobProto, out var departmentProto))
+                            departmentColor = departmentProto.Color;
+                    }
 
                     if (!roleRequirement.Inverted)
                     {
                         if (roleDiff <= 0)
                             return true;
 
-                        reason = Loc.GetString(
+                        reason = FormattedMessage.FromMarkup(Loc.GetString(
                             "role-timer-role-insufficient",
                             ("time", roleDiff),
-                            ("job", Loc.GetString(proto)));
+                            ("job", Loc.GetString(proto)),
+                            ("departmentColor", departmentColor.ToHex())));
                         return false;
                     }
                     else
                     {
                         if (roleDiff <= 0)
                         {
-                            reason = Loc.GetString(
+                            reason = FormattedMessage.FromMarkup(Loc.GetString(
                                 "role-timer-role-too-high",
                                 ("time", -roleDiff),
-                                ("job", Loc.GetString(proto)));
+                                ("job", Loc.GetString(proto)),
+                                ("departmentColor", departmentColor.ToHex())));
                             return false;
                         }
 
index f172b3d310aff85ecc1fd924067353eee7f7bc00..6ab5776a77e74fed6b860b87434901bddd629594 100644 (file)
@@ -1,7 +1,10 @@
 using System.Diagnostics.CodeAnalysis;
+using System.Linq;
 using Content.Shared.Players;
+using Content.Shared.Players.PlayTimeTracking;
 using Robust.Shared.Players;
 using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
 
 namespace Content.Shared.Roles.Jobs;
 
@@ -13,6 +16,71 @@ public abstract class SharedJobSystem : EntitySystem
     [Dependency] private readonly IPrototypeManager _prototypes = default!;
     [Dependency] private readonly SharedPlayerSystem _playerSystem = default!;
 
+    [Dependency] private readonly IPrototypeManager _protoManager = default!;
+    private readonly Dictionary<string, string> _inverseTrackerLookup = new();
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        _protoManager.PrototypesReloaded += OnProtoReload;
+        SetupTrackerLookup();
+    }
+
+    public override void Shutdown()
+    {
+        base.Shutdown();
+        _protoManager.PrototypesReloaded -= OnProtoReload;
+        _inverseTrackerLookup.Clear();
+    }
+
+    private void OnProtoReload(PrototypesReloadedEventArgs obj)
+    {
+        _inverseTrackerLookup.Clear();
+        SetupTrackerLookup();
+    }
+
+    private void SetupTrackerLookup()
+    {
+        // This breaks if you have N trackers to 1 JobId but future concern.
+        foreach (var job in _protoManager.EnumeratePrototypes<JobPrototype>())
+        {
+            _inverseTrackerLookup.Add(job.PlayTimeTracker, job.ID);
+        }
+    }
+
+    /// <summary>
+    /// Gets the corresponding Job Prototype to a <see cref="PlayTimeTrackerPrototype"/>
+    /// </summary>
+    /// <param name="trackerProto"></param>
+    /// <returns></returns>
+    public string GetJobPrototype(string trackerProto)
+    {
+        DebugTools.Assert(_protoManager.HasIndex<PlayTimeTrackerPrototype>(trackerProto));
+        return _inverseTrackerLookup[trackerProto];
+    }
+
+    /// <summary>
+    /// Tries to get the first corresponding department for this job prototype.
+    /// </summary>
+    public bool TryGetDepartment(string jobProto, [NotNullWhen(true)] out DepartmentPrototype? departmentPrototype)
+    {
+        // Not that many departments so we can just eat the cost instead of storing the inverse lookup.
+        var departmentProtos = _protoManager.EnumeratePrototypes<DepartmentPrototype>().ToList();
+        departmentProtos.Sort((x, y) => string.Compare(x.ID, y.ID, StringComparison.Ordinal));
+
+        foreach (var department in departmentProtos)
+        {
+            if (department.Roles.Contains(jobProto))
+            {
+                departmentPrototype = department;
+                return true;
+            }
+        }
+
+        departmentPrototype = null;
+        return false;
+    }
+
     public bool MindHasJobWithId(EntityUid? mindId, string prototypeId)
     {
         return CompOrNull<JobComponent>(mindId)?.PrototypeId == prototypeId;
index 8e70e234d3d709d5ee19c5d426cc2016c05717aa..1981f5e795776143a258489500f7dda69c33e0cc 100644 (file)
@@ -1,9 +1,9 @@
-role-timer-department-insufficient = You require {TOSTRING($time, "0")} more minutes in {$department} department to play this role.
-role-timer-department-too-high = You require {TOSTRING($time, "0")} fewer minutes in {$department} department to play this role. (Are you trying to play a trainee role?)
-role-timer-overall-insufficient = You require {TOSTRING($time, "0")} more minutes of playtime to play this role.
-role-timer-overall-too-high = You require {TOSTRING($time, "0")} fewer minutes of playtime to play this role. (Are you trying to play a trainee role?)
-role-timer-role-insufficient = You require {TOSTRING($time, "0")} more minutes with {$job} to play this role.
-role-timer-role-too-high = You require {TOSTRING($time, "0")} fewer minutes with {$job} to play this role. (Are you trying to play a trainee role?)
+role-timer-department-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes of [color={$departmentColor}]{$department}[/color] department playtime to play this role.
+role-timer-department-too-high = You require [color=yellow]{TOSTRING($time, "0")}[/color] fewer minutes in [color={$departmentColor}]{$department}[/color] department to play this role. (Are you trying to play a trainee role?)
+role-timer-overall-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes of playtime to play this role.
+role-timer-overall-too-high = You require [color=yellow]{TOSTRING($time, "0")}[/color] fewer minutes of playtime to play this role. (Are you trying to play a trainee role?)
+role-timer-role-insufficient = You require [color=yellow]{TOSTRING($time, "0")}[/color] more minutes with [color={$departmentColor}]{$job}[/color] to play this role.
+role-timer-role-too-high = You require[color=yellow] {TOSTRING($time, "0")}[/color] fewer minutes with [color={$departmentColor}]{$job}[/color] to play this role. (Are you trying to play a trainee role?)
 
 role-timer-locked = Locked (hover for details)