Goida revert (#600)
* Revert "- fix: YAML linter fixes. (#598)" This reverts commit012bf3c357. * Revert "Automatic changelog update" This reverts commitcf1c3a9af5. * Revert "[Fix] Base Layer Prototype (#597)" This reverts commitb000423999. * Revert "Modules update (#596)" This reverts commit00fbdead77. * Revert "Automatic changelog update" This reverts commit0d7a12b2a2. * Revert "Fixes (#593)" This reverts commit943c77031c. * Revert "minor loadout fixes (#594)" This reverts commit143c010a89. * Revert "Update DryDock.yml (#595)" This reverts commit4cd0100ac7. * Revert "Automatic changelog update" This reverts commit08eadc690f. * Revert "fix: Maximum message size (#591)" This reverts commit343f3612eb. * Revert "Черри пики 7 (#592)" This reverts commit3f97bdce2f. * Revert "Automatic changelog update" This reverts commit0678eca250. * Revert "Рандомфиксы (#590)" This reverts commit2b9e5e2437. * Revert "Нижнее бельё в лодауты (#580)" This reverts commite01a47b089. * Revert "add lathe sounds (#588)" This reverts commitc80a2985f2. * Revert "Добавил параметр группы для некоторых реагентов (#585)" This reverts commit713b16bb98. * Revert "add hrp ++++ aspect (#587)" This reverts commita6a69cc60f. * Revert "Новые амбиенты и пару песен (#586)" This reverts commit48c86bd846. * Revert "Сообщения в ПДА 2 (#583)" This reverts commitcced3cc98b. * Revert "Automatic changelog update" This reverts commitabf435b11d. * Revert "Chem stuff and more (#584)" This reverts commit3608960f5c. * Revert "JobRequiremet refactor (#579)" This reverts commit9a9c9598e0. * Revert "Revert "Reapply "Нижнее бельё в лодауты""" This reverts commit44447d573f. * Revert "Reapply "Нижнее бельё в лодауты"" This reverts commit0c4d082ad3. * Revert "Revert "Нижнее бельё в лодауты"" This reverts commit56473c5492. * Revert "Нижнее бельё в лодауты" This reverts commitd1cb0cb364. * Revert "DryDock and WhiteMoose update (#578)" This reverts commit14755808af. * Revert "Automatic changelog update" This reverts commit0133f82722. * Revert "Fixes (#576)" This reverts commitb7cc49896c. * Revert "порт системы регенерации солюшена цинки (#574)" This reverts commita22cf3d50b. * Revert "Воровские перчатки (#573)" This reverts commitbb7140f3d4. * Revert "mood resprite (#572)" This reverts commit4db96dc569. * Revert "fix missing letter (#571)" This reverts commit94ea756794. * Revert "Сообщения в ПДА (#564)" This reverts commitd023d29e54. * Revert "- fix: No visible aghost." This reverts commit27e7f25f7e. * Revert "- tweak: Nerf cult shield." This reverts commit6a384246b8.
This commit is contained in:
@@ -41,8 +41,6 @@ public sealed partial class AntagPrototype : IPrototype
|
||||
/// <summary>
|
||||
/// Requirements that must be met to opt in to this antag role.
|
||||
/// </summary>
|
||||
// TODO ROLE TIMERS
|
||||
// Actually check if the requirements are met. Because apparently this is actually unused.
|
||||
[DataField]
|
||||
[DataField("requirements")]
|
||||
public HashSet<JobRequirement>? Requirements;
|
||||
}
|
||||
|
||||
@@ -9,16 +9,16 @@ public sealed partial class DepartmentPrototype : IPrototype
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The name LocId of the department that will be displayed in the various menus.
|
||||
/// A name string.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public LocId Name = string.Empty;
|
||||
public string Name = default!;
|
||||
|
||||
/// <summary>
|
||||
/// A description LocId to display in the character menu as an explanation of the department's function.
|
||||
/// A description string to display in the character menu as an explanation of the department's function.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public LocId Description = string.Empty;
|
||||
[DataField (required: true)]
|
||||
public string Description = default!;
|
||||
|
||||
/// <summary>
|
||||
/// A color representing this department to use for text.
|
||||
@@ -26,8 +26,8 @@ public sealed partial class DepartmentPrototype : IPrototype
|
||||
[DataField(required: true)]
|
||||
public Color Color = default!;
|
||||
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public List<ProtoId<JobPrototype>> Roles = new();
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField(customTypeSerializer: typeof(PrototypeIdListSerializer<JobPrototype>))]
|
||||
public List<string> Roles = new();
|
||||
|
||||
/// <summary>
|
||||
/// Whether this is a primary department or not.
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Preferences;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Roles;
|
||||
|
||||
/// <summary>
|
||||
/// Requires the character to be older or younger than a certain age (inclusive)
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class AgeRequirement : JobRequirement
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public int RequiredAge;
|
||||
|
||||
public override bool Check(IEntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HumanoidCharacterProfile? profile,
|
||||
IReadOnlyDictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason)
|
||||
{
|
||||
reason = new FormattedMessage();
|
||||
|
||||
if (profile is null) //the profile could be null if the player is a ghost. In this case we don't need to block the role selection for ghostrole
|
||||
return true;
|
||||
|
||||
if (!Inverted)
|
||||
{
|
||||
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-age-to-young",
|
||||
("age", RequiredAge)));
|
||||
|
||||
if (profile.Age <= RequiredAge)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-age-to-old",
|
||||
("age", RequiredAge)));
|
||||
|
||||
if (profile.Age >= RequiredAge)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Preferences;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Roles;
|
||||
|
||||
[UsedImplicitly]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class DepartmentTimeRequirement : JobRequirement
|
||||
{
|
||||
public override bool IgnoreIfAdmin => true; // WD
|
||||
|
||||
/// <summary>
|
||||
/// Which department needs the required amount of time.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public ProtoId<DepartmentPrototype> Department = default!;
|
||||
|
||||
/// <summary>
|
||||
/// How long (in seconds) this requirement is.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public TimeSpan Time;
|
||||
|
||||
public override bool Check(IEntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HumanoidCharacterProfile? profile,
|
||||
IReadOnlyDictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason)
|
||||
{
|
||||
reason = new FormattedMessage();
|
||||
var playtime = TimeSpan.Zero;
|
||||
|
||||
// Check all jobs' departments
|
||||
var department = protoManager.Index(Department);
|
||||
var jobs = department.Roles;
|
||||
string proto;
|
||||
|
||||
// Check all jobs' playtime
|
||||
foreach (var other in jobs)
|
||||
{
|
||||
// The schema is stored on the Job role but we want to explode if the timer isn't found anyway.
|
||||
proto = protoManager.Index(other).PlayTimeTracker;
|
||||
|
||||
playTimes.TryGetValue(proto, out var otherTime);
|
||||
playtime += otherTime;
|
||||
}
|
||||
|
||||
var deptDiff = Time.TotalMinutes - playtime.TotalMinutes;
|
||||
var nameDepartment = "role-timer-department-unknown";
|
||||
|
||||
if (protoManager.TryIndex(Department, out var departmentIndexed))
|
||||
{
|
||||
nameDepartment = departmentIndexed.Name;
|
||||
}
|
||||
|
||||
if (!Inverted)
|
||||
{
|
||||
if (deptDiff <= 0)
|
||||
return true;
|
||||
|
||||
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
|
||||
"role-timer-department-insufficient",
|
||||
("time", Math.Ceiling(deptDiff)),
|
||||
("department", Loc.GetString(nameDepartment)),
|
||||
("departmentColor", department.Color.ToHex())));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (deptDiff <= 0)
|
||||
{
|
||||
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
|
||||
"role-timer-department-too-high",
|
||||
("time", -deptDiff),
|
||||
("department", Loc.GetString(nameDepartment)),
|
||||
("departmentColor", department.Color.ToHex())));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
using Content.Shared.Preferences;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Roles;
|
||||
|
||||
[UsedImplicitly]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class OverallPlaytimeRequirement : JobRequirement
|
||||
{
|
||||
public override bool IgnoreIfAdmin => true; // WD
|
||||
|
||||
/// <inheritdoc cref="DepartmentTimeRequirement.Time"/>
|
||||
[DataField(required: true)]
|
||||
public TimeSpan Time;
|
||||
|
||||
public override bool Check(IEntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HumanoidCharacterProfile? profile,
|
||||
IReadOnlyDictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason)
|
||||
{
|
||||
reason = new FormattedMessage();
|
||||
|
||||
var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall);
|
||||
var overallDiff = Time.TotalMinutes - overallTime.TotalMinutes;
|
||||
|
||||
if (!Inverted)
|
||||
{
|
||||
if (overallDiff <= 0 || overallTime >= Time)
|
||||
return true;
|
||||
|
||||
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
|
||||
"role-timer-overall-insufficient",
|
||||
("time", Math.Ceiling(overallDiff))));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (overallDiff <= 0 || overallTime >= Time)
|
||||
{
|
||||
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString("role-timer-overall-too-high",
|
||||
("time", -overallDiff)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Roles;
|
||||
|
||||
[UsedImplicitly]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class RoleTimeRequirement : JobRequirement
|
||||
{
|
||||
public override bool IgnoreIfAdmin => true; // WD
|
||||
|
||||
/// <summary>
|
||||
/// What particular role they need the time requirement with.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public ProtoId<PlayTimeTrackerPrototype> Role = default!;
|
||||
|
||||
/// <inheritdoc cref="DepartmentTimeRequirement.Time"/>
|
||||
[DataField(required: true)]
|
||||
public TimeSpan Time;
|
||||
|
||||
public override bool Check(IEntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HumanoidCharacterProfile? profile,
|
||||
IReadOnlyDictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason)
|
||||
{
|
||||
reason = new FormattedMessage();
|
||||
|
||||
string proto = Role;
|
||||
|
||||
playTimes.TryGetValue(proto, out var roleTime);
|
||||
var roleDiff = 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 (!Inverted)
|
||||
{
|
||||
if (roleDiff <= 0)
|
||||
return true;
|
||||
|
||||
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
|
||||
"role-timer-role-insufficient",
|
||||
("time", Math.Ceiling(roleDiff)),
|
||||
("job", Loc.GetString(proto)),
|
||||
("departmentColor", departmentColor.ToHex())));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (roleDiff <= 0)
|
||||
{
|
||||
reason = FormattedMessage.FromMarkupPermissive(Loc.GetString(
|
||||
"role-timer-role-too-high",
|
||||
("time", -roleDiff),
|
||||
("job", Loc.GetString(proto)),
|
||||
("departmentColor", departmentColor.ToHex())));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Preferences;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Roles;
|
||||
|
||||
/// <summary>
|
||||
/// Requires the character to be or not be on the list of specified species
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class SpeciesRequirement : JobRequirement
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public HashSet<ProtoId<SpeciesPrototype>> Species = new();
|
||||
|
||||
public override bool Check(IEntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HumanoidCharacterProfile? profile,
|
||||
IReadOnlyDictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason)
|
||||
{
|
||||
reason = new FormattedMessage();
|
||||
|
||||
if (profile is null) //the profile could be null if the player is a ghost. In this case we don't need to block the role selection for ghostrole
|
||||
return true;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.Append("[color=yellow]");
|
||||
foreach (var s in Species)
|
||||
{
|
||||
sb.Append(Loc.GetString(protoManager.Index(s).Name) + " ");
|
||||
}
|
||||
|
||||
sb.Append("[/color]");
|
||||
|
||||
if (!Inverted)
|
||||
{
|
||||
reason = FormattedMessage.FromMarkupPermissive($"{Loc.GetString("role-timer-whitelisted-species")}\n{sb}");
|
||||
|
||||
if (!Species.Contains(profile.Species))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
reason = FormattedMessage.FromMarkupPermissive($"{Loc.GetString("role-timer-blacklisted-species")}\n{sb}");
|
||||
|
||||
if (Species.Contains(profile.Species))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
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 ();
|
||||
}
|
||||
@@ -1,57 +1,226 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Roles;
|
||||
|
||||
public static class JobRequirements
|
||||
namespace Content.Shared.Roles
|
||||
{
|
||||
public static bool TryRequirementsMet(
|
||||
JobPrototype job,
|
||||
IReadOnlyDictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason,
|
||||
IEntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HumanoidCharacterProfile? profile,
|
||||
bool isAdmin)
|
||||
/// <summary>
|
||||
/// Abstract class for playtime and other requirements for role gates.
|
||||
/// </summary>
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[Serializable, NetSerializable]
|
||||
public abstract partial class JobRequirement{}
|
||||
|
||||
[UsedImplicitly]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class DepartmentTimeRequirement : JobRequirement
|
||||
{
|
||||
var sys = entManager.System<SharedRoleSystem>();
|
||||
var requirements = sys.GetJobRequirement(job);
|
||||
reason = null;
|
||||
if (requirements == null)
|
||||
return true;
|
||||
/// <summary>
|
||||
/// Which department needs the required amount of time.
|
||||
/// </summary>
|
||||
[DataField("department", customTypeSerializer: typeof(PrototypeIdSerializer<DepartmentPrototype>))]
|
||||
public string Department = default!;
|
||||
|
||||
foreach (var requirement in requirements)
|
||||
/// <summary>
|
||||
/// How long (in seconds) this requirement is.
|
||||
/// </summary>
|
||||
[DataField("time")] public TimeSpan Time;
|
||||
|
||||
/// <summary>
|
||||
/// If true, requirement will return false if playtime above the specified time.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>False</c> by default.<br />
|
||||
/// <c>True</c> for invert general requirement
|
||||
/// </value>
|
||||
[DataField("inverted")] public bool Inverted;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class RoleTimeRequirement : JobRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// What particular role they need the time requirement with.
|
||||
/// </summary>
|
||||
[DataField("role", customTypeSerializer: typeof(PrototypeIdSerializer<PlayTimeTrackerPrototype>))]
|
||||
public string Role = default!;
|
||||
|
||||
/// <inheritdoc cref="DepartmentTimeRequirement.Time"/>
|
||||
[DataField("time")] public TimeSpan Time;
|
||||
|
||||
/// <inheritdoc cref="DepartmentTimeRequirement.Inverted"/>
|
||||
[DataField("inverted")] public bool Inverted;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class OverallPlaytimeRequirement : JobRequirement
|
||||
{
|
||||
/// <inheritdoc cref="DepartmentTimeRequirement.Time"/>
|
||||
[DataField("time")] public TimeSpan Time;
|
||||
|
||||
/// <inheritdoc cref="DepartmentTimeRequirement.Inverted"/>
|
||||
[DataField("inverted")] public bool Inverted;
|
||||
}
|
||||
|
||||
public static class JobRequirements
|
||||
{
|
||||
public static bool TryRequirementsMet(
|
||||
JobPrototype job,
|
||||
Dictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason,
|
||||
IEntityManager entManager,
|
||||
IPrototypeManager prototypes)
|
||||
{
|
||||
if (isAdmin && requirement.IgnoreIfAdmin)
|
||||
continue;
|
||||
reason = null;
|
||||
if (job.Requirements == null)
|
||||
return true;
|
||||
|
||||
if (!requirement.Check(entManager, protoManager, profile, playTimes, out reason))
|
||||
return false;
|
||||
foreach (var requirement in job.Requirements)
|
||||
{
|
||||
if (!TryRequirementMet(requirement, playTimes, out reason, entManager, prototypes))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
/// <summary>
|
||||
/// Returns a string with the reason why a particular requirement may not be met.
|
||||
/// </summary>
|
||||
public static bool TryRequirementMet(
|
||||
JobRequirement requirement,
|
||||
IReadOnlyDictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason,
|
||||
IEntityManager entManager,
|
||||
IPrototypeManager prototypes)
|
||||
{
|
||||
reason = null;
|
||||
|
||||
switch (requirement)
|
||||
{
|
||||
case DepartmentTimeRequirement deptRequirement:
|
||||
var playtime = TimeSpan.Zero;
|
||||
|
||||
// Check all jobs' departments
|
||||
var department = prototypes.Index<DepartmentPrototype>(deptRequirement.Department);
|
||||
var jobs = department.Roles;
|
||||
string proto;
|
||||
|
||||
// Check all jobs' playtime
|
||||
foreach (var other in jobs)
|
||||
{
|
||||
// The schema is stored on the Job role but we want to explode if the timer isn't found anyway.
|
||||
proto = prototypes.Index<JobPrototype>(other).PlayTimeTracker;
|
||||
|
||||
playTimes.TryGetValue(proto, out var otherTime);
|
||||
playtime += otherTime;
|
||||
}
|
||||
|
||||
var deptDiff = deptRequirement.Time.TotalMinutes - playtime.TotalMinutes;
|
||||
|
||||
if (!deptRequirement.Inverted)
|
||||
{
|
||||
if (deptDiff <= 0)
|
||||
return true;
|
||||
|
||||
reason = FormattedMessage.FromMarkup(Loc.GetString(
|
||||
"role-timer-department-insufficient",
|
||||
("time", Math.Ceiling(deptDiff)),
|
||||
("department", Loc.GetString(deptRequirement.Department)),
|
||||
("departmentColor", department.Color.ToHex())));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (deptDiff <= 0)
|
||||
{
|
||||
reason = FormattedMessage.FromMarkup(Loc.GetString(
|
||||
"role-timer-department-too-high",
|
||||
("time", -deptDiff),
|
||||
("department", Loc.GetString(deptRequirement.Department)),
|
||||
("departmentColor", department.Color.ToHex())));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case OverallPlaytimeRequirement overallRequirement:
|
||||
var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall);
|
||||
var overallDiff = overallRequirement.Time.TotalMinutes - overallTime.TotalMinutes;
|
||||
|
||||
if (!overallRequirement.Inverted)
|
||||
{
|
||||
if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
|
||||
return true;
|
||||
|
||||
reason = FormattedMessage.FromMarkup(Loc.GetString(
|
||||
"role-timer-overall-insufficient",
|
||||
("time", Math.Ceiling(overallDiff))));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
|
||||
{
|
||||
reason = FormattedMessage.FromMarkup(Loc.GetString("role-timer-overall-too-high", ("time", -overallDiff)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case RoleTimeRequirement roleRequirement:
|
||||
proto = roleRequirement.Role;
|
||||
|
||||
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 = FormattedMessage.FromMarkup(Loc.GetString(
|
||||
"role-timer-role-insufficient",
|
||||
("time", Math.Ceiling(roleDiff)),
|
||||
("job", Loc.GetString(proto)),
|
||||
("departmentColor", departmentColor.ToHex())));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (roleDiff <= 0)
|
||||
{
|
||||
reason = FormattedMessage.FromMarkup(Loc.GetString(
|
||||
"role-timer-role-too-high",
|
||||
("time", -roleDiff),
|
||||
("job", Loc.GetString(proto)),
|
||||
("departmentColor", departmentColor.ToHex())));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract class for playtime and other requirements for role gates.
|
||||
/// </summary>
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[Serializable, NetSerializable]
|
||||
public abstract partial class JobRequirement
|
||||
{
|
||||
[DataField]
|
||||
public bool Inverted;
|
||||
|
||||
public virtual bool IgnoreIfAdmin => false; // WD
|
||||
|
||||
public abstract bool Check(
|
||||
IEntityManager entManager,
|
||||
IPrototypeManager protoManager,
|
||||
HumanoidCharacterProfile? profile,
|
||||
IReadOnlyDictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out FormattedMessage? reason);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
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;
|
||||
|
||||
@@ -18,30 +15,14 @@ public abstract class SharedRoleSystem : EntitySystem
|
||||
[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)
|
||||
@@ -205,36 +186,4 @@ public abstract class SharedRoleSystem : EntitySystem
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user