using Content.Shared.Access; using Content.Shared.Guidebook; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.StatusIcon; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Content.Shared._RMC14.Marines.Roles.Ranks; namespace Content.Shared.Roles { /// /// Describes information for a single job on the station. /// [Prototype] public sealed partial class JobPrototype : IPrototype { [ViewVariables] [IdDataField] public string ID { get; private set; } = default!; [DataField("playTimeTracker", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] public string PlayTimeTracker { get; private set; } = string.Empty; /// /// Who is the supervisor for this job. /// [DataField("supervisors")] public string Supervisors { get; private set; } = "nobody"; /// /// The name of this job as displayed to players. /// [DataField("name")] public string Name { get; private set; } = string.Empty; [ViewVariables(VVAccess.ReadOnly)] public string LocalizedName => Loc.GetString(Name); /// /// The "original" name of the role, untranslated. /// This would be, for example, a medic for the french faction being called Médecin /// [DataField("originalName")] public string OriginalName { get; private set; } = string.Empty; /// /// The faction this job belongs to. Used to look for spawnpoints. /// [DataField("faction")] public string Faction { get; private set; } = string.Empty; /// /// The name of this job as displayed to players. /// [DataField("description")] public string? Description { get; private set; } [ViewVariables(VVAccess.ReadOnly)] public string? LocalizedDescription => Description is null ? null : Loc.GetString(Description); /// /// Requirements for the job. /// [DataField, Access(typeof(SharedRoleSystem), Other = AccessPermissions.None)] public HashSet? Requirements; /// /// When true - the station will have anouncement about arrival of this player. /// [DataField("joinNotifyCrew")] public bool JoinNotifyCrew { get; private set; } = false; /// /// When true - the player will recieve a message about importancy of their job. /// [DataField("requireAdminNotify")] public bool RequireAdminNotify { get; private set; } = false; /// /// Should this job appear in preferences menu? /// [DataField("setPreference")] public bool SetPreference { get; private set; } = true; /// /// Should the selected traits be applied for this job? /// [DataField] public bool ApplyTraits { get; private set; } = true; /// /// Whether this job should show in the ID Card Console. /// If set to null, it will default to SetPreference's value. /// [DataField] public bool? OverrideConsoleVisibility { get; private set; } = null; [DataField("canBeAntag")] public bool CanBeAntag { get; private set; } = true; /// /// The "weight" or importance of this job. If this number is large, the job system will assign this job /// before assigning other jobs. /// [DataField("weight")] public int Weight { get; private set; } /// /// 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, is used as a fallback. /// [DataField] public int? DisplayWeight { get; private set; } public int RealDisplayWeight => DisplayWeight ?? Weight; /// /// 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. /// [DataField("antagAdvantage")] public int AntagAdvantage = 0; [DataField] public ProtoId? StartingGear { get; private set; } [DataField] public List>? RandomStartingGears { get; private set; } = new(); /// /// 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. /// [DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? JobEntity = null; /// /// Entity to use as a preview in the lobby/character editor. /// Same restrictions as apply. /// [DataField] public EntProtoId? JobPreviewEntity = null; [DataField] public ProtoId Icon { get; private set; } = "JobIconUnknown"; [DataField("special", serverOnly: true)] public JobSpecial[] Special { get; private set; } = Array.Empty(); [DataField("access")] public IReadOnlyCollection> Access { get; private set; } = Array.Empty>(); [DataField("accessGroups")] public IReadOnlyCollection> AccessGroups { get; private set; } = Array.Empty>(); [DataField("extendedAccess")] public IReadOnlyCollection> ExtendedAccess { get; private set; } = Array.Empty>(); [DataField("extendedAccessGroups")] public IReadOnlyCollection> ExtendedAccessGroups { get; private set; } = Array.Empty>(); [DataField] public bool Whitelisted; /// /// Optional list of guides associated with this role. If the guides are opened, the first entry in this list /// will be used to select the currently selected guidebook. /// [DataField] public List>? Guides; //RMC Ranks [DataField] public readonly Dictionary, HashSet?>? Ranks; } /// /// Sorts s appropriately for display in the UI, /// respecting their . /// public sealed class JobUIComparer : IComparer { 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); } } }