Files
tbd-station-14/Content.Shared/Roles/JobPrototype.cs
Pieter-Jan Briers 715794dd41 Make department / job list sorting consistent. (#25486)
* Make department / job list sorting consistent.

This makes late join, crew manifest and character profile all apply consistent sorting for jobs and departments.

We use the already-defined weights for departments (so command, then sec, then station specific, then just sort by prototype ID). Jobs also use weight (so heads are always at the top) then prototype ID, then character name (for manifest).

Removed the crewmanifest.ordering CVar as doing it via prototype weight is just easier, and that CVar was already a mess anyways.

* Fix jittery job icons in lists.

They were set to KeepCentered in TextureRect. This has issues because the allocated space is actually an odd number of pixels, so it tries to position the draw at a half pixel offset.

Now, yes, fixing this in TextureRect would make much more sense, but get off my back. (Ok seriously we need better helper functions for doing that in the engine. Don't wanna deal with that right now and I already have this patch made.)

Instead I'm just gonna fix the issue by using VerticalAlignment in all these places instead which ends up doing exactly the same thing YIPPEE.

Also gave a margin next to the icon on the crew manifest. Margins people!
2024-02-23 15:04:44 +11:00

145 lines
5.9 KiB
C#

using Content.Shared.Access;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Roles
{
/// <summary>
/// Describes information for a single job on the station.
/// </summary>
[Prototype("job")]
public sealed partial class JobPrototype : IPrototype
{
[ViewVariables]
[IdDataField]
public string ID { get; private set; } = default!;
[DataField("playTimeTracker", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<PlayTimeTrackerPrototype>))]
public string PlayTimeTracker { get; private set; } = string.Empty;
[DataField("supervisors")]
public string Supervisors { get; private set; } = "nobody";
/// <summary>
/// The name of this job as displayed to players.
/// </summary>
[DataField("name")]
public string Name { get; private set; } = string.Empty;
[ViewVariables(VVAccess.ReadOnly)]
public string LocalizedName => Loc.GetString(Name);
/// <summary>
/// The name of this job as displayed to players.
/// </summary>
[DataField("description")]
public string? Description { get; private set; }
[ViewVariables(VVAccess.ReadOnly)]
public string? LocalizedDescription => Description is null ? null : Loc.GetString(Description);
[DataField("requirements")]
public HashSet<JobRequirement>? Requirements;
[DataField("joinNotifyCrew")]
public bool JoinNotifyCrew { get; private set; } = false;
[DataField("requireAdminNotify")]
public bool RequireAdminNotify { get; private set; } = false;
[DataField("setPreference")]
public bool SetPreference { get; private set; } = true;
/// <summary>
/// Whether this job should show in the ID Card Console.
/// If set to null, it will default to SetPreference's value.
/// </summary>
[DataField]
public bool? OverrideConsoleVisibility { get; private set; } = null;
[DataField("canBeAntag")]
public bool CanBeAntag { get; private set; } = true;
/// <summary>
/// Whether this job is a head.
/// The job system will try to pick heads before other jobs on the same priority level.
/// </summary>
[DataField("weight")]
public int Weight { get; private set; }
/// <summary>
/// How to sort this job relative to other jobs in the UI.
/// Jobs with a higher value with sort before jobs with a lower value.
/// If not set, <see cref="Weight"/> is used as a fallback.
/// </summary>
[DataField]
public int? DisplayWeight { get; private set; }
public int RealDisplayWeight => DisplayWeight ?? Weight;
/// <summary>
/// A numerical score for how much easier this job is for antagonists.
/// For traitors, reduces starting TC by this amount. Other gamemodes can use it for whatever they find fitting.
/// </summary>
[DataField("antagAdvantage")]
public int AntagAdvantage = 0;
[DataField("startingGear", customTypeSerializer: typeof(PrototypeIdSerializer<StartingGearPrototype>))]
public string? StartingGear { get; private set; }
/// <summary>
/// Use this to spawn in as a non-humanoid (borg, test subject, etc.)
/// Starting gear will be ignored.
/// If you want to just add special attributes to a humanoid, use AddComponentSpecial instead.
/// </summary>
[DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string? JobEntity = null;
[DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
public string Icon { get; private set; } = "JobIconUnknown";
[DataField("special", serverOnly: true)]
public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>();
[DataField("access", customTypeSerializer: typeof(PrototypeIdListSerializer<AccessLevelPrototype>))]
public IReadOnlyCollection<string> Access { get; private set; } = Array.Empty<string>();
[DataField("accessGroups", customTypeSerializer: typeof(PrototypeIdListSerializer<AccessGroupPrototype>))]
public IReadOnlyCollection<string> AccessGroups { get; private set; } = Array.Empty<string>();
[DataField("extendedAccess", customTypeSerializer: typeof(PrototypeIdListSerializer<AccessLevelPrototype>))]
public IReadOnlyCollection<string> ExtendedAccess { get; private set; } = Array.Empty<string>();
[DataField("extendedAccessGroups", customTypeSerializer: typeof(PrototypeIdListSerializer<AccessGroupPrototype>))]
public IReadOnlyCollection<string> ExtendedAccessGroups { get; private set; } = Array.Empty<string>();
}
/// <summary>
/// Sorts <see cref="JobPrototype"/>s appropriately for display in the UI,
/// respecting their <see cref="JobPrototype.Weight"/>.
/// </summary>
public sealed class JobUIComparer : IComparer<JobPrototype>
{
public static readonly JobUIComparer Instance = new();
public int Compare(JobPrototype? x, JobPrototype? y)
{
if (ReferenceEquals(x, y))
return 0;
if (ReferenceEquals(null, y))
return 1;
if (ReferenceEquals(null, x))
return -1;
var cmp = -x.RealDisplayWeight.CompareTo(y.RealDisplayWeight);
if (cmp != 0)
return cmp;
return string.Compare(x.ID, y.ID, StringComparison.Ordinal);
}
}
}