Play time tracking: Job timers 3: more titles: when the (#9978)
Co-authored-by: Veritius <veritiusgaming@gmail.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
committed by
GitHub
parent
6b94db0336
commit
e852ada6c8
14
Content.Shared/Roles/DepartmentPrototype.cs
Normal file
14
Content.Shared/Roles/DepartmentPrototype.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
|
||||
namespace Content.Shared.Roles;
|
||||
|
||||
[Prototype("department")]
|
||||
public sealed class DepartmentPrototype : IPrototype
|
||||
{
|
||||
[IdDataFieldAttribute] public string ID { get; } = default!;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("roles", customTypeSerializer: typeof(PrototypeIdListSerializer<JobPrototype>))]
|
||||
public List<string> Roles = new();
|
||||
}
|
||||
6
Content.Shared/Roles/IRoleTimer.cs
Normal file
6
Content.Shared/Roles/IRoleTimer.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Content.Shared.Roles;
|
||||
|
||||
public interface IRoleTimer
|
||||
{
|
||||
string Timer { get; }
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Access;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
|
||||
@@ -11,12 +12,13 @@ namespace Content.Shared.Roles
|
||||
[Prototype("job")]
|
||||
public sealed class JobPrototype : IPrototype
|
||||
{
|
||||
private string _name = string.Empty;
|
||||
|
||||
[ViewVariables]
|
||||
[IdDataFieldAttribute]
|
||||
public string ID { get; } = default!;
|
||||
|
||||
[ViewVariables, DataField("playTimeTracker", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<PlayTimeTrackerPrototype>))]
|
||||
public string PlayTimeTracker { get; } = string.Empty;
|
||||
|
||||
[DataField("supervisors")]
|
||||
public string Supervisors { get; } = "nobody";
|
||||
|
||||
@@ -29,6 +31,9 @@ namespace Content.Shared.Roles
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
public string LocalizedName => Loc.GetString(Name);
|
||||
|
||||
[DataField("requirements")]
|
||||
public HashSet<JobRequirement>? Requirements;
|
||||
|
||||
[DataField("joinNotifyCrew")]
|
||||
public bool JoinNotifyCrew { get; } = false;
|
||||
|
||||
@@ -64,9 +69,6 @@ namespace Content.Shared.Roles
|
||||
[DataField("special", serverOnly:true)]
|
||||
public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>();
|
||||
|
||||
[DataField("departments")]
|
||||
public IReadOnlyCollection<string> Departments { get; } = Array.Empty<string>();
|
||||
|
||||
[DataField("access", customTypeSerializer: typeof(PrototypeIdListSerializer<AccessLevelPrototype>))]
|
||||
public IReadOnlyCollection<string> Access { get; } = Array.Empty<string>();
|
||||
|
||||
|
||||
145
Content.Shared/Roles/JobRequirements.cs
Normal file
145
Content.Shared/Roles/JobRequirements.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Roles
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract class for playtime and other requirements for role gates.
|
||||
/// </summary>
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public abstract class JobRequirement
|
||||
{
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class DepartmentTimeRequirement : JobRequirement
|
||||
{
|
||||
[DataField("department", customTypeSerializer: typeof(PrototypeIdSerializer<DepartmentPrototype>))]
|
||||
public string Department = default!;
|
||||
|
||||
/// <summary>
|
||||
/// How long (in seconds) this requirement is.
|
||||
/// </summary>
|
||||
[DataField("time")] public TimeSpan Time;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class RoleTimeRequirement : JobRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// What particular role they need the time requirement with.
|
||||
/// </summary>
|
||||
[DataField("role", customTypeSerializer: typeof(PrototypeIdSerializer<PlayTimeTrackerPrototype>))]
|
||||
public string Role = default!;
|
||||
|
||||
/// <summary>
|
||||
/// How long (in seconds) this requirement is.
|
||||
/// </summary>
|
||||
[DataField("time")] public TimeSpan Time;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class OverallPlaytimeRequirement : JobRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// How long (in seconds) this requirement is.
|
||||
/// </summary>
|
||||
[DataField("time")] public TimeSpan Time;
|
||||
}
|
||||
|
||||
public static class JobRequirements
|
||||
{
|
||||
public static bool TryRequirementsMet(
|
||||
JobPrototype job,
|
||||
Dictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out string? reason,
|
||||
IPrototypeManager prototypes)
|
||||
{
|
||||
reason = null;
|
||||
if (job.Requirements == null)
|
||||
return true;
|
||||
|
||||
foreach (var requirement in job.Requirements)
|
||||
{
|
||||
if (!TryRequirementMet(requirement, playTimes, out reason, prototypes))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string with the reason why a particular requirement may not be met.
|
||||
/// </summary>
|
||||
public static bool TryRequirementMet(
|
||||
JobRequirement requirement,
|
||||
Dictionary<string, TimeSpan> playTimes,
|
||||
[NotNullWhen(false)] out string? reason,
|
||||
IPrototypeManager prototypes)
|
||||
|
||||
{
|
||||
reason = null;
|
||||
|
||||
switch (requirement)
|
||||
{
|
||||
case DepartmentTimeRequirement deptRequirement:
|
||||
var playtime = TimeSpan.Zero;
|
||||
|
||||
// Check all jobs' departments
|
||||
var jobs = prototypes.Index<DepartmentPrototype>(deptRequirement.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 (deptDiff <= 0)
|
||||
return true;
|
||||
|
||||
reason = Loc.GetString(
|
||||
"role-timer-department-insufficient",
|
||||
("time", deptDiff),
|
||||
("department", Loc.GetString(deptRequirement.Department)));
|
||||
return false;
|
||||
|
||||
case OverallPlaytimeRequirement overallRequirement:
|
||||
var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall);
|
||||
var overallDiff = overallRequirement.Time.TotalMinutes - overallTime.TotalMinutes;
|
||||
|
||||
if (overallDiff <= 0 || overallTime >= overallRequirement.Time)
|
||||
return true;
|
||||
|
||||
reason = Loc.GetString("role-timer-overall-insufficient", ("time", overallDiff));
|
||||
return false;
|
||||
|
||||
case RoleTimeRequirement roleRequirement:
|
||||
proto = roleRequirement.Role;
|
||||
|
||||
playTimes.TryGetValue(proto, out var roleTime);
|
||||
var roleDiff = roleRequirement.Time.TotalMinutes - roleTime.TotalMinutes;
|
||||
|
||||
if (roleDiff <= 0)
|
||||
return true;
|
||||
|
||||
reason = Loc.GetString(
|
||||
"role-timer-role-insufficient",
|
||||
("time", roleDiff),
|
||||
("job", Loc.GetString(proto)));
|
||||
return false;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user