selector.Setup(items, title, 250, description, guides: antag.Guides);
selector.Select(Profile?.AntagPreferences.Contains(antag.ID) == true ? 0 : 1);
- if (!_requirements.CheckRoleTime(antag.Requirements, out var reason))
+ var requirements = _entManager.System<SharedRoleSystem>().GetAntagRequirement(antag);
+ if (!_requirements.CheckRoleTime(requirements, out var reason))
{
selector.LockRequirements(reason);
Profile = Profile?.WithAntagPreference(antag.ID, false);
if (player == null)
return true;
- return CheckRoleTime(job.Requirements, out reason);
+ return CheckRoleTime(job, out reason);
+ }
+
+ public bool CheckRoleTime(JobPrototype job, [NotNullWhen(false)] out FormattedMessage? reason)
+ {
+ var reqs = _entManager.System<SharedRoleSystem>().GetJobRequirement(job);
+ return CheckRoleTime(reqs, out reason);
}
public bool CheckRoleTime(HashSet<JobRequirement>? requirements, [NotNullWhen(false)] out FormattedMessage? reason)
/// </summary>
public bool IsSessionValid(Entity<AntagSelectionComponent> ent, ICommonSession? session, AntagSelectionDefinition def, EntityUid? mind = null)
{
+ // TODO ROLE TIMERS
+ // Check if antag role requirements are met
+
if (session == null)
return true;
[DataField("rules")] private string _roleRules = "ghost-role-component-default-rules";
+ // TODO ROLE TIMERS
+ // Actually make use of / enforce this requirement?
+ // Why is this even here.
+ // Move to ghost role prototype & respect CCvars.GameRoleTimerOverride
[DataField("requirements")]
public HashSet<JobRequirement>? Requirements;
[Dependency] private readonly MindSystem _minds = default!;
[Dependency] private readonly PlayTimeTrackingManager _tracking = default!;
[Dependency] private readonly IAdminManager _adminManager = default!;
+ [Dependency] private readonly SharedRoleSystem _role = default!;
public override void Initialize()
{
public bool IsAllowed(ICommonSession player, string role)
{
if (!_prototypes.TryIndex<JobPrototype>(role, out var job) ||
- job.Requirements == null ||
!_cfg.GetCVar(CCVars.GameRoleTimers))
return true;
foreach (var job in _prototypes.EnumeratePrototypes<JobPrototype>())
{
- if (job.Requirements != null)
- {
- foreach (var requirement in job.Requirements)
- {
- if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, EntityManager, _prototypes))
- continue;
-
- goto NoRole;
- }
- }
-
- roles.Add(job.ID);
- NoRole:;
+ if (JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes))
+ roles.Add(job.ID);
}
return roles;
for (var i = 0; i < jobs.Count; i++)
{
- var job = jobs[i];
-
- if (!_prototypes.TryIndex(job, out var jobber) ||
- jobber.Requirements == null ||
- jobber.Requirements.Count == 0)
- continue;
-
- foreach (var requirement in jobber.Requirements)
+ if (_prototypes.TryIndex(jobs[i], out var job)
+ && JobRequirements.TryRequirementsMet(job, playTimes, out _, EntityManager, _prototypes))
{
- if (JobRequirements.TryRequirementMet(requirement, playTimes, out _, EntityManager, _prototypes))
- continue;
-
- jobs.RemoveSwap(i);
- i--;
- break;
+ continue;
}
+
+ jobs.RemoveSwap(i);
+ i--;
}
}
using Content.Shared.Maps;
+using Content.Shared.Roles;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.Physics.Components;
public static readonly CVarDef<bool>
GameRoleTimers = CVarDef.Create("game.role_timers", true, CVar.SERVER | CVar.REPLICATED);
+ /// <summary>
+ /// Override default role requirements using a <see cref="JobRequirementOverridePrototype"/>
+ /// </summary>
+ public static readonly CVarDef<string>
+ GameRoleTimerOverride = CVarDef.Create("game.role_timer_override", "", CVar.SERVER | CVar.REPLICATED);
+
/// <summary>
/// If roles should be restricted based on whether or not they are whitelisted.
/// </summary>
/// <summary>
/// The name of the ghostrole.
/// </summary>
- [DataField]
+ [DataField(required: true)]
public string Name { get; set; } = default!;
/// <summary>
/// The description of the ghostrole.
/// </summary>
- [DataField]
+ [DataField(required: true)]
public string Description { get; set; } = default!;
/// <summary>
/// The entity prototype of the ghostrole
/// </summary>
- [DataField]
- public string EntityPrototype = default!;
+ [DataField(required: true)]
+ public EntProtoId EntityPrototype;
/// <summary>
/// Rules of the ghostrole
/// </summary>
- [DataField]
+ [DataField(required: true)]
public string Rules = default!;
-}
\ No newline at end of file
+}
public string Name { get; set; }
public string Description { get; set; }
public string Rules { get; set; }
+
+ // TODO ROLE TIMERS
+ // Actually make use of / enforce this requirement?
+ // Why is this even here.
+ // Move to ghost role prototype & respect CCvars.GameRoleTimerOverride
public HashSet<JobRequirement>? Requirements { get; set; }
/// <inheritdoc cref="GhostRoleKind"/>
/// <summary>
/// Requirements that must be met to opt in to this antag role.
/// </summary>
- [DataField("requirements")]
+ // TODO ROLE TIMERS
+ // Actually check if the requirements are met. Because apparently this is actually unused.
+ [DataField, Access(typeof(SharedRoleSystem), Other = AccessPermissions.None)]
public HashSet<JobRequirement>? Requirements;
/// <summary>
[ViewVariables(VVAccess.ReadOnly)]
public string? LocalizedDescription => Description is null ? null : Loc.GetString(Description);
- [DataField("requirements")]
+ [DataField, Access(typeof(SharedRoleSystem), Other = AccessPermissions.None)]
public HashSet<JobRequirement>? Requirements;
[DataField("joinNotifyCrew")]
--- /dev/null
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Roles;
+
+/// <summary>
+/// Collection of job, antag, and ghost-role job requirements for per-server requirement overrides.
+/// </summary>
+[Prototype]
+public sealed partial class JobRequirementOverridePrototype : IPrototype
+{
+ [ViewVariables]
+ [IdDataField]
+ public string ID { get; private set; } = default!;
+
+ [DataField]
+ public Dictionary<ProtoId<JobPrototype>, HashSet<JobRequirement>> Jobs = new ();
+
+ [DataField]
+ public Dictionary<ProtoId<AntagPrototype>, HashSet<JobRequirement>> Antags = new ();
+}
{
public static bool TryRequirementsMet(
JobPrototype job,
- Dictionary<string, TimeSpan> playTimes,
+ IReadOnlyDictionary<string, TimeSpan> playTimes,
[NotNullWhen(false)] out FormattedMessage? reason,
IEntityManager entManager,
IPrototypeManager prototypes)
{
+ var sys = entManager.System<SharedRoleSystem>();
+ var requirements = sys.GetJobRequirement(job);
reason = null;
- if (job.Requirements == null)
+ if (requirements == null)
return true;
- foreach (var requirement in job.Requirements)
+ foreach (var requirement in requirements)
{
if (!TryRequirementMet(requirement, playTimes, out reason, entManager, prototypes))
return false;
if (deptDiff <= 0)
return true;
- reason = FormattedMessage.FromMarkup(Loc.GetString(
+ reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-department-insufficient",
("time", Math.Ceiling(deptDiff)),
("department", Loc.GetString(deptRequirement.Department)),
{
if (deptDiff <= 0)
{
- reason = FormattedMessage.FromMarkup(Loc.GetString(
+ reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-department-too-high",
("time", -deptDiff),
("department", Loc.GetString(deptRequirement.Department)),
if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
return true;
- reason = FormattedMessage.FromMarkup(Loc.GetString(
+ reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-overall-insufficient",
("time", Math.Ceiling(overallDiff))));
return false;
{
if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
{
- reason = FormattedMessage.FromMarkup(Loc.GetString("role-timer-overall-too-high", ("time", -overallDiff)));
+ reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-overall-too-high", ("time", -overallDiff)));
return false;
}
if (roleDiff <= 0)
return true;
- reason = FormattedMessage.FromMarkup(Loc.GetString(
+ reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-role-insufficient",
("time", Math.Ceiling(roleDiff)),
("job", Loc.GetString(proto)),
{
if (roleDiff <= 0)
{
- reason = FormattedMessage.FromMarkup(Loc.GetString(
+ reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
"role-timer-role-too-high",
("time", -roleDiff),
("job", Loc.GetString(proto)),
-using System.Linq;
using Content.Shared.Administration.Logs;
+using Content.Shared.CCVar;
using Content.Shared.Database;
+using Content.Shared.Ghost.Roles;
using Content.Shared.Mind;
using Content.Shared.Roles.Jobs;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
+using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
[Dependency] private readonly IPrototypeManager _prototypes = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedMindSystem _minds = default!;
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
// TODO please lord make role entities
private readonly HashSet<Type> _antagTypes = new();
+ private JobRequirementOverridePrototype? _requirementOverride;
+
public override void Initialize()
{
// TODO make roles entities
SubscribeLocalEvent<JobComponent, MindGetAllRolesEvent>(OnJobGetAllRoles);
+ Subs.CVar(_cfg, CCVars.GameRoleTimerOverride, SetRequirementOverride, true);
+ }
+
+ private void SetRequirementOverride(string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ _requirementOverride = null;
+ return;
+ }
+
+ if (!_prototypes.TryIndex(value, out _requirementOverride ))
+ Log.Error($"Unknown JobRequirementOverridePrototype: {value}");
}
private void OnJobGetAllRoles(EntityUid uid, JobComponent component, ref MindGetAllRolesEvent args)
if (Resolve(mindId, ref mind) && mind.Session != null)
_audio.PlayGlobal(sound, mind.Session);
}
+
+ public HashSet<JobRequirement>? GetJobRequirement(JobPrototype job)
+ {
+ if (_requirementOverride != null && _requirementOverride.Jobs.TryGetValue(job.ID, out var req))
+ return req;
+
+ return job.Requirements;
+ }
+
+ public HashSet<JobRequirement>? GetJobRequirement(ProtoId<JobPrototype> job)
+ {
+ if (_requirementOverride != null && _requirementOverride.Jobs.TryGetValue(job, out var req))
+ return req;
+
+ return _prototypes.Index(job).Requirements;
+ }
+
+ public HashSet<JobRequirement>? GetAntagRequirement(ProtoId<AntagPrototype> antag)
+ {
+ if (_requirementOverride != null && _requirementOverride.Antags.TryGetValue(antag, out var req))
+ return req;
+
+ return _prototypes.Index(antag).Requirements;
+ }
+
+ public HashSet<JobRequirement>? GetAntagRequirement(AntagPrototype antag)
+ {
+ if (_requirementOverride != null && _requirementOverride.Antags.TryGetValue(antag.ID, out var req))
+ return req;
+
+ return antag.Requirements;
+ }
}
--- /dev/null
+- type: jobRequirementOverride
+ id: Reduced
+ jobs:
+ Captain:
+ - !type:DepartmentTimeRequirement
+ department: Engineering
+ time: 3600 # 1 hours
+ - !type:DepartmentTimeRequirement
+ department: Medical
+ time: 3600 # 1 hours
+ - !type:DepartmentTimeRequirement
+ department: Security
+ time: 3600 # 1 hours
+ - !type:DepartmentTimeRequirement
+ department: Command
+ time: 3600 # 1 hour