diff --git a/Content.IntegrationTests/Tests/Minds/JobTests.cs b/Content.IntegrationTests/Tests/Minds/JobTests.cs
new file mode 100644
index 0000000000..5172049a99
--- /dev/null
+++ b/Content.IntegrationTests/Tests/Minds/JobTests.cs
@@ -0,0 +1,48 @@
+using Content.Shared.Roles;
+using Content.Shared.Roles.Jobs;
+using Robust.Shared.Prototypes;
+using System.Linq;
+
+namespace Content.IntegrationTests.Tests.Station;
+
+[TestFixture]
+[TestOf(typeof(SharedJobSystem))]
+public sealed class JobTest
+{
+ ///
+ /// Ensures that every job belongs to at most 1 primary department.
+ /// Having no primary department is ok.
+ ///
+ [Test]
+ public async Task PrimaryDepartmentsTest()
+ {
+ await using var pair = await PoolManager.GetServerClient();
+ var server = pair.Server;
+
+ var prototypeManager = server.ResolveDependency();
+
+ await server.WaitAssertion(() =>
+ {
+ // only checking primary departments so don't bother with others
+ var departments = prototypeManager.EnumeratePrototypes()
+ .Where(department => department.Primary)
+ .ToList();
+ var jobs = prototypeManager.EnumeratePrototypes();
+ foreach (var job in jobs)
+ {
+ // not actually using the jobs system since that will return the first department
+ // and we need to test that there is never more than 1, so it not sorting them is correct
+ var primaries = 0;
+ foreach (var department in departments)
+ {
+ if (!department.Roles.Contains(job.ID))
+ continue;
+
+ primaries++;
+ Assert.That(primaries, Is.EqualTo(1), $"The job {job.ID} has more than 1 primary department!");
+ }
+ }
+ });
+ await pair.CleanReturnAsync();
+ }
+}
diff --git a/Content.Shared/Roles/DepartmentPrototype.cs b/Content.Shared/Roles/DepartmentPrototype.cs
index f91d1a43fd..b3549d9584 100644
--- a/Content.Shared/Roles/DepartmentPrototype.cs
+++ b/Content.Shared/Roles/DepartmentPrototype.cs
@@ -23,4 +23,11 @@ public sealed partial class DepartmentPrototype : IPrototype
[ViewVariables(VVAccess.ReadWrite),
DataField("roles", customTypeSerializer: typeof(PrototypeIdListSerializer))]
public List Roles = new();
+
+ ///
+ /// Whether this is a primary department or not.
+ /// For example, CE's primary department is engineering since Command has primary: false.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public bool Primary = true;
}
diff --git a/Content.Shared/Roles/Jobs/SharedJobSystem.cs b/Content.Shared/Roles/Jobs/SharedJobSystem.cs
index fe0f9d115b..04ac45c4c5 100644
--- a/Content.Shared/Roles/Jobs/SharedJobSystem.cs
+++ b/Content.Shared/Roles/Jobs/SharedJobSystem.cs
@@ -76,6 +76,30 @@ public abstract class SharedJobSystem : EntitySystem
return false;
}
+ ///
+ /// Like but ignores any non-primary departments.
+ /// For example, with CE it will return Engineering but with captain it will
+ /// not return anything, since Command is not a primary department.
+ ///
+ public bool TryGetPrimaryDepartment(string jobProto, [NotNullWhen(true)] out DepartmentPrototype? departmentPrototype)
+ {
+ // not sorting it since there should only be 1 primary department for a job.
+ // this is enforced by the job tests.
+ var departmentProtos = _protoManager.EnumeratePrototypes();
+
+ foreach (var department in departmentProtos)
+ {
+ if (department.Primary && department.Roles.Contains(jobProto))
+ {
+ departmentPrototype = department;
+ return true;
+ }
+ }
+
+ departmentPrototype = null;
+ return false;
+ }
+
public bool MindHasJobWithId(EntityUid? mindId, string prototypeId)
{
return CompOrNull(mindId)?.Prototype == prototypeId;
diff --git a/Resources/Prototypes/Roles/Jobs/departments.yml b/Resources/Prototypes/Roles/Jobs/departments.yml
index 5b5ee2252d..e1df397721 100644
--- a/Resources/Prototypes/Roles/Jobs/departments.yml
+++ b/Resources/Prototypes/Roles/Jobs/departments.yml
@@ -43,6 +43,7 @@
- HeadOfSecurity
- ResearchDirector
- Quartermaster
+ primary: false
- type: department
id: Engineering
@@ -95,3 +96,4 @@
- Reporter
- Zookeeper
- Psychologist
+ primary: false