Job icons are stored on ID cards (#18233)

This commit is contained in:
PrPleGoo
2023-07-29 10:25:27 +02:00
committed by GitHub
parent 7c9d7423d2
commit 7c088ac1de
65 changed files with 685 additions and 96 deletions

View File

@@ -18,7 +18,8 @@ namespace Content.Client.Access.UI
{ {
base.Open(); base.Open();
_window = new AgentIDCardWindow(); _window?.Dispose();
_window = new AgentIDCardWindow(this);
if (State != null) if (State != null)
UpdateState(State); UpdateState(State);
@@ -39,6 +40,11 @@ namespace Content.Client.Access.UI
SendMessage(new AgentIDCardJobChangedMessage(newJob)); SendMessage(new AgentIDCardJobChangedMessage(newJob));
} }
public void OnJobIconChanged(string newJobIcon)
{
SendMessage(new AgentIDCardJobIconChangedMessage(newJobIcon));
}
/// <summary> /// <summary>
/// Update the UI state based on server-sent info /// Update the UI state based on server-sent info
/// </summary> /// </summary>
@@ -51,6 +57,7 @@ namespace Content.Client.Access.UI
_window.SetCurrentName(cast.CurrentName); _window.SetCurrentName(cast.CurrentName);
_window.SetCurrentJob(cast.CurrentJob); _window.SetCurrentJob(cast.CurrentJob);
_window.SetAllowedIcons(cast.Icons);
} }
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)

View File

@@ -6,5 +6,12 @@
<LineEdit Name="NameLineEdit" /> <LineEdit Name="NameLineEdit" />
<Label Name="CurrentJob" Text="{Loc 'agent-id-card-current-job'}" /> <Label Name="CurrentJob" Text="{Loc 'agent-id-card-current-job'}" />
<LineEdit Name="JobLineEdit" /> <LineEdit Name="JobLineEdit" />
<BoxContainer Orientation="Horizontal" Visible="False">
<Label Text="{Loc 'agent-id-card-job-icon-label'}"/>
<Control HorizontalExpand="True" MinSize="50 0"/>
<GridContainer Name="IconGrid" Columns="10">
<!-- Job icon buttons are generated in the code -->
</GridContainer>
</BoxContainer>
</BoxContainer> </BoxContainer>
</DefaultWindow> </DefaultWindow>

View File

@@ -1,18 +1,35 @@
using Robust.Client.UserInterface.CustomControls; using Content.Client.Stylesheets;
using Content.Shared.StatusIcon;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using System.Numerics;
namespace Content.Client.Access.UI namespace Content.Client.Access.UI
{ {
[GenerateTypedNameReferences] [GenerateTypedNameReferences]
public sealed partial class AgentIDCardWindow : DefaultWindow public sealed partial class AgentIDCardWindow : DefaultWindow
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
private readonly SpriteSystem _spriteSystem;
private readonly AgentIDCardBoundUserInterface _bui;
private const int JobIconColumnCount = 10;
public event Action<string>? OnNameChanged; public event Action<string>? OnNameChanged;
public event Action<string>? OnJobChanged; public event Action<string>? OnJobChanged;
public AgentIDCardWindow() public AgentIDCardWindow(AgentIDCardBoundUserInterface bui)
{ {
RobustXamlLoader.Load(this); RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>();
_bui = bui;
NameLineEdit.OnTextEntered += e => OnNameChanged?.Invoke(e.Text); NameLineEdit.OnTextEntered += e => OnNameChanged?.Invoke(e.Text);
NameLineEdit.OnFocusExit += e => OnNameChanged?.Invoke(e.Text); NameLineEdit.OnFocusExit += e => OnNameChanged?.Invoke(e.Text);
@@ -21,6 +38,51 @@ namespace Content.Client.Access.UI
JobLineEdit.OnFocusExit += e => OnJobChanged?.Invoke(e.Text); JobLineEdit.OnFocusExit += e => OnJobChanged?.Invoke(e.Text);
} }
public void SetAllowedIcons(HashSet<string> icons)
{
IconGrid.DisposeAllChildren();
var jobIconGroup = new ButtonGroup();
var i = 0;
foreach (var jobIconId in icons)
{
if (!_prototypeManager.TryIndex<StatusIconPrototype>(jobIconId, out var jobIcon))
{
continue;
}
String styleBase = StyleBase.ButtonOpenBoth;
var modulo = i % JobIconColumnCount;
if (modulo == 0)
styleBase = StyleBase.ButtonOpenRight;
else if (modulo == JobIconColumnCount - 1)
styleBase = StyleBase.ButtonOpenLeft;
// Generate buttons
var jobIconButton = new Button
{
Access = AccessLevel.Public,
StyleClasses = { styleBase },
MaxSize = new Vector2(42, 28),
Group = jobIconGroup,
Pressed = i == 0,
};
// Generate buttons textures
TextureRect jobIconTexture = new TextureRect
{
Texture = _spriteSystem.Frame0(jobIcon.Icon),
TextureScale = new Vector2(2.5f, 2.5f),
Stretch = TextureRect.StretchMode.KeepCentered,
};
jobIconButton.AddChild(jobIconTexture);
jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIcon.ID);
IconGrid.AddChild(jobIconButton);
i++;
}
}
public void SetCurrentName(string name) public void SetCurrentName(string name)
{ {
NameLineEdit.Text = name; NameLineEdit.Text = name;

View File

@@ -1,5 +1,3 @@
using System.Linq;
using System.Numerics;
using Content.Client.Stylesheets; using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls; using Content.Client.UserInterface.Controls;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
@@ -7,11 +5,12 @@ using Content.Shared.Chemistry.Reagent;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
using Robust.Client.Utility; using Robust.Client.Utility;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using System.Linq;
using System.Numerics;
using static Robust.Client.UserInterface.Controls.BoxContainer; using static Robust.Client.UserInterface.Controls.BoxContainer;
namespace Content.Client.Chemistry.UI namespace Content.Client.Chemistry.UI

View File

@@ -3,7 +3,9 @@ using System.Numerics;
using Content.Shared.CCVar; using Content.Shared.CCVar;
using Content.Shared.CrewManifest; using Content.Shared.CrewManifest;
using Content.Shared.Roles; using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.ResourceManagement; using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
@@ -100,8 +102,15 @@ public sealed partial class CrewManifestUi : DefaultWindow
private sealed class CrewManifestSection : BoxContainer private sealed class CrewManifestSection : BoxContainer
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
private readonly SpriteSystem _spriteSystem = default!;
public CrewManifestSection(string sectionTitle, List<CrewManifestEntry> entries, IResourceCache cache, CrewManifestSystem crewManifestSystem) public CrewManifestSection(string sectionTitle, List<CrewManifestEntry> entries, IResourceCache cache, CrewManifestSystem crewManifestSystem)
{ {
IoCManager.InjectDependencies(this);
_spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>();
Orientation = LayoutOrientation.Vertical; Orientation = LayoutOrientation.Vertical;
HorizontalExpand = true; HorizontalExpand = true;
@@ -122,9 +131,6 @@ public sealed partial class CrewManifestUi : DefaultWindow
AddChild(gridContainer); AddChild(gridContainer);
var path = new ResPath("/Textures/Interface/Misc/job_icons.rsi");
cache.TryGetResource(path, out RSIResource? rsi);
foreach (var entry in entries) foreach (var entry in entries)
{ {
var name = new RichTextLabel() var name = new RichTextLabel()
@@ -143,25 +149,15 @@ public sealed partial class CrewManifestUi : DefaultWindow
title.SetMessage(entry.JobTitle); title.SetMessage(entry.JobTitle);
if (rsi != null) if (_prototypeManager.TryIndex<StatusIconPrototype>(entry.JobIcon, out var jobIcon))
{ {
var icon = new TextureRect() var icon = new TextureRect()
{ {
TextureScale = new Vector2(2, 2), TextureScale = new Vector2(2, 2),
Stretch = TextureRect.StretchMode.KeepCentered Stretch = TextureRect.StretchMode.KeepCentered,
Texture = _spriteSystem.Frame0(jobIcon.Icon),
}; };
if (rsi.RSI.TryGetState(entry.JobIcon, out _))
{
var specifier = new SpriteSpecifier.Rsi(path, entry.JobIcon);
icon.Texture = specifier.Frame0();
}
else if (rsi.RSI.TryGetState("Unknown", out _))
{
var specifier = new SpriteSpecifier.Rsi(path, "Unknown");
icon.Texture = specifier.Frame0();
}
titleContainer.AddChild(icon); titleContainer.AddChild(icon);
titleContainer.AddChild(title); titleContainer.AddChild(title);
} }

View File

@@ -5,6 +5,7 @@ using Content.Client.UserInterface.Controls;
using Content.Client.Players.PlayTimeTracking; using Content.Client.Players.PlayTimeTracking;
using Content.Shared.CCVar; using Content.Shared.CCVar;
using Content.Shared.Roles; using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Robust.Client.Console; using Robust.Client.Console;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
@@ -233,8 +234,8 @@ namespace Content.Client.LateJoin
Stretch = TextureRect.StretchMode.KeepCentered Stretch = TextureRect.StretchMode.KeepCentered
}; };
var specifier = new SpriteSpecifier.Rsi(new ("/Textures/Interface/Misc/job_icons.rsi"), prototype.Icon); var jobIcon = _prototypeManager.Index<StatusIconPrototype>(prototype.Icon);
icon.Texture = _sprites.Frame0(specifier); icon.Texture = _sprites.Frame0(jobIcon.Icon);
jobSelector.AddChild(icon); jobSelector.AddChild(icon);
var jobLabel = new Label var jobLabel = new Label

View File

@@ -13,6 +13,7 @@ using Content.Shared.Humanoid.Markings;
using Content.Shared.Humanoid.Prototypes; using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Preferences; using Content.Shared.Preferences;
using Content.Shared.Roles; using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Content.Shared.Traits; using Content.Shared.Traits;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects; using Robust.Client.GameObjects;
@@ -574,7 +575,7 @@ namespace Content.Client.Preferences.UI
foreach (var job in jobs) foreach (var job in jobs)
{ {
var selector = new JobPrioritySelector(job); var selector = new JobPrioritySelector(job, _prototypeManager);
if (!_requirements.IsAllowed(job, out var reason)) if (!_requirements.IsAllowed(job, out var reason))
{ {
@@ -1192,7 +1193,7 @@ namespace Content.Client.Preferences.UI
private Label _requirementsLabel; private Label _requirementsLabel;
private Label _jobTitle; private Label _jobTitle;
public JobPrioritySelector(JobPrototype job) public JobPrioritySelector(JobPrototype job, IPrototypeManager prototypeManager)
{ {
Job = job; Job = job;
@@ -1222,12 +1223,8 @@ namespace Content.Client.Preferences.UI
Stretch = TextureRect.StretchMode.KeepCentered Stretch = TextureRect.StretchMode.KeepCentered
}; };
if (job.Icon != null) var jobIcon = prototypeManager.Index<StatusIconPrototype>(job.Icon);
{ icon.Texture = jobIcon.Icon.Frame0();
var specifier = new SpriteSpecifier.Rsi(new ("/Textures/Interface/Misc/job_icons.rsi"),
job.Icon);
icon.Texture = specifier.Frame0();
}
_requirementsLabel = new Label() _requirementsLabel = new Label()
{ {

View File

@@ -1,7 +1,15 @@
using Content.Shared.StatusIcon;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
namespace Content.Server.Access.Components namespace Content.Server.Access.Components
{ {
[RegisterComponent] [RegisterComponent]
public sealed class AgentIDCardComponent : Component public sealed class AgentIDCardComponent : Component
{ {
/// <summary>
/// Set of job icons that the agent ID card can show.
/// </summary>
[DataField("icons", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<StatusIconPrototype>))]
public readonly HashSet<string> Icons = new();
} }
} }

View File

@@ -4,7 +4,9 @@ using Content.Server.UserInterface;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.StatusIcon;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
namespace Content.Server.Access.Systems namespace Content.Server.Access.Systems
{ {
@@ -13,6 +15,7 @@ namespace Content.Server.Access.Systems
[Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IdCardSystem _cardSystem = default!; [Dependency] private readonly IdCardSystem _cardSystem = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -22,6 +25,7 @@ namespace Content.Server.Access.Systems
SubscribeLocalEvent<AgentIDCardComponent, AfterActivatableUIOpenEvent>(AfterUIOpen); SubscribeLocalEvent<AgentIDCardComponent, AfterActivatableUIOpenEvent>(AfterUIOpen);
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardNameChangedMessage>(OnNameChanged); SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardNameChangedMessage>(OnNameChanged);
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardJobChangedMessage>(OnJobChanged); SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardJobChangedMessage>(OnJobChanged);
SubscribeLocalEvent<AgentIDCardComponent, AgentIDCardJobIconChangedMessage>(OnJobIconChanged);
} }
private void OnAfterInteract(EntityUid uid, AgentIDCardComponent component, AfterInteractEvent args) private void OnAfterInteract(EntityUid uid, AgentIDCardComponent component, AfterInteractEvent args)
@@ -61,7 +65,7 @@ namespace Content.Server.Access.Systems
if (!TryComp<IdCardComponent>(uid, out var idCard)) if (!TryComp<IdCardComponent>(uid, out var idCard))
return; return;
var state = new AgentIDCardBoundUserInterfaceState(idCard.FullName ?? "", idCard.JobTitle ?? ""); var state = new AgentIDCardBoundUserInterfaceState(idCard.FullName ?? "", idCard.JobTitle ?? "", component.Icons);
UserInterfaceSystem.SetUiState(ui, state, args.Session); UserInterfaceSystem.SetUiState(ui, state, args.Session);
} }
@@ -80,5 +84,20 @@ namespace Content.Server.Access.Systems
_cardSystem.TryChangeFullName(uid, args.Name, idCard); _cardSystem.TryChangeFullName(uid, args.Name, idCard);
} }
private void OnJobIconChanged(EntityUid uid, AgentIDCardComponent comp, AgentIDCardJobIconChangedMessage args)
{
if (!TryComp<IdCardComponent>(uid, out var idCard))
{
return;
}
if (!_prototypeManager.TryIndex<StatusIconPrototype>(args.JobIcon, out var jobIcon))
{
return;
}
_cardSystem.TryChangeJobIcon(uid, jobIcon, idCard);
}
} }
} }

View File

@@ -1,4 +1,3 @@
using System.Linq;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Server.StationRecords.Systems; using Content.Server.StationRecords.Systems;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
@@ -7,10 +6,12 @@ using Content.Shared.Administration.Logs;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Roles; using Content.Shared.Roles;
using Content.Shared.StationRecords; using Content.Shared.StationRecords;
using Content.Shared.StatusIcon;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using System.Linq;
using static Content.Shared.Access.Components.IdCardConsoleComponent; using static Content.Shared.Access.Components.IdCardConsoleComponent;
namespace Content.Server.Access.Systems; namespace Content.Server.Access.Systems;
@@ -129,6 +130,12 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
_idCard.TryChangeFullName(targetId, newFullName, player: player); _idCard.TryChangeFullName(targetId, newFullName, player: player);
_idCard.TryChangeJobTitle(targetId, newJobTitle, player: player); _idCard.TryChangeJobTitle(targetId, newJobTitle, player: player);
if (_prototype.TryIndex<JobPrototype>(newJobProto, out var job)
&& _prototype.TryIndex<StatusIconPrototype>(job.Icon, out var jobIcon))
{
_idCard.TryChangeJobIcon(targetId, jobIcon, player: player);
}
if (!newAccessList.TrueForAll(x => component.AccessLevels.Contains(x))) if (!newAccessList.TrueForAll(x => component.AccessLevels.Contains(x)))
{ {
_sawmill.Warning($"User {ToPrettyString(uid)} tried to write unknown access tag."); _sawmill.Warning($"User {ToPrettyString(uid)} tried to write unknown access tag.");
@@ -145,7 +152,7 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
// I hate that C# doesn't have an option for this and don't desire to write this out the hard way. // I hate that C# doesn't have an option for this and don't desire to write this out the hard way.
// var difference = newAccessList.Difference(oldTags); // var difference = newAccessList.Difference(oldTags);
var difference = (newAccessList.Union(oldTags)).Except(newAccessList.Intersect(oldTags)).ToHashSet(); var difference = newAccessList.Union(oldTags).Except(newAccessList.Intersect(oldTags)).ToHashSet();
// NULL SAFETY: PrivilegedIdIsAuthorized checked this earlier. // NULL SAFETY: PrivilegedIdIsAuthorized checked this earlier.
var privilegedPerms = _accessReader.FindAccessTags(privilegedId!.Value).ToHashSet(); var privilegedPerms = _accessReader.FindAccessTags(privilegedId!.Value).ToHashSet();
if (!difference.IsSubsetOf(privilegedPerms)) if (!difference.IsSubsetOf(privilegedPerms))
@@ -163,7 +170,7 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
_adminLogger.Add(LogType.Action, LogImpact.Medium, _adminLogger.Add(LogType.Action, LogImpact.Medium,
$"{ToPrettyString(player):player} has modified {ToPrettyString(targetId):entity} with the following accesses: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]"); $"{ToPrettyString(player):player} has modified {ToPrettyString(targetId):entity} with the following accesses: [{string.Join(", ", addedTags.Union(removedTags))}] [{string.Join(", ", newAccessList)}]");
UpdateStationRecord(uid, targetId, newFullName, newJobTitle, newJobProto); UpdateStationRecord(uid, targetId, newFullName, newJobTitle, job);
} }
/// <summary> /// <summary>
@@ -184,7 +191,7 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
return privilegedId != null && _accessReader.IsAllowed(privilegedId.Value, reader); return privilegedId != null && _accessReader.IsAllowed(privilegedId.Value, reader);
} }
private void UpdateStationRecord(EntityUid uid, EntityUid targetId, string newFullName, string newJobTitle, string newJobProto) private void UpdateStationRecord(EntityUid uid, EntityUid targetId, string newFullName, string newJobTitle, JobPrototype? newJobProto)
{ {
if (_station.GetOwningStation(uid) is not { } station if (_station.GetOwningStation(uid) is not { } station
|| !EntityManager.TryGetComponent<StationRecordKeyStorageComponent>(targetId, out var keyStorage) || !EntityManager.TryGetComponent<StationRecordKeyStorageComponent>(targetId, out var keyStorage)
@@ -197,10 +204,10 @@ public sealed class IdCardConsoleSystem : SharedIdCardConsoleSystem
record.Name = newFullName; record.Name = newFullName;
record.JobTitle = newJobTitle; record.JobTitle = newJobTitle;
if (_prototype.TryIndex<JobPrototype>(newJobProto, out var job)) if (newJobProto != null)
{ {
record.JobPrototype = newJobProto; record.JobPrototype = newJobProto.ID;
record.JobIcon = job.Icon; record.JobIcon = newJobProto.Icon;
} }
_record.Synchronize(station); _record.Synchronize(station);

View File

@@ -1,4 +1,3 @@
using System.Linq;
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.Kitchen.Components; using Content.Server.Kitchen.Components;
using Content.Server.Popups; using Content.Server.Popups;
@@ -7,8 +6,10 @@ using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.StatusIcon;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using System.Linq;
namespace Content.Server.Access.Systems namespace Content.Server.Access.Systems
{ {
@@ -118,6 +119,30 @@ namespace Content.Server.Access.Systems
return true; return true;
} }
public bool TryChangeJobIcon(EntityUid uid, StatusIconPrototype jobIcon, IdCardComponent? id = null, EntityUid? player = null)
{
if (!Resolve(uid, ref id))
{
return false;
}
if (id.JobIcon == jobIcon.ID)
{
return true;
}
id.JobIcon = jobIcon.ID;
Dirty(id);
if (player != null)
{
_adminLogger.Add(LogType.Identity, LogImpact.Low,
$"{ToPrettyString(player.Value):player} has changed the job icon of {ToPrettyString(id.Owner):entity} to {jobIcon} ");
}
return true;
}
/// <summary> /// <summary>
/// Attempts to change the full name of a card. /// Attempts to change the full name of a card.
/// Returns true/false. /// Returns true/false.

View File

@@ -4,6 +4,7 @@ using Content.Server.Station.Components;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.Roles; using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
namespace Content.Server.Access.Systems namespace Content.Server.Access.Systems
@@ -67,8 +68,12 @@ namespace Content.Server.Access.Systems
_accessSystem.SetAccessToJob(uid, job, extended); _accessSystem.SetAccessToJob(uid, job, extended);
// and also change job title on a card id
_cardSystem.TryChangeJobTitle(uid, job.LocalizedName); _cardSystem.TryChangeJobTitle(uid, job.LocalizedName);
if (_prototypeManager.TryIndex<StatusIconPrototype>(job.Icon, out var jobIcon))
{
_cardSystem.TryChangeJobIcon(uid, jobIcon);
}
} }
} }
} }

View File

@@ -19,6 +19,7 @@ using Content.Shared.Preferences;
using Content.Shared.Random; using Content.Shared.Random;
using Content.Shared.Random.Helpers; using Content.Shared.Random.Helpers;
using Content.Shared.Roles; using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.Map; using Robust.Shared.Map;
@@ -220,6 +221,11 @@ public sealed class StationSpawningSystem : EntitySystem
_cardSystem.TryChangeFullName(cardId, characterName, card); _cardSystem.TryChangeFullName(cardId, characterName, card);
_cardSystem.TryChangeJobTitle(cardId, jobPrototype.LocalizedName, card); _cardSystem.TryChangeJobTitle(cardId, jobPrototype.LocalizedName, card);
if (_prototypeManager.TryIndex<StatusIconPrototype>(jobPrototype.Icon, out var jobIcon))
{
_cardSystem.TryChangeJobIcon(cardId, jobIcon, card);
}
var extendedAccess = false; var extendedAccess = false;
if (station != null) if (station != null)
{ {

View File

@@ -1,6 +1,8 @@
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.PDA; using Content.Shared.PDA;
using Content.Shared.StatusIcon;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Access.Components namespace Content.Shared.Access.Components
{ {
@@ -18,5 +20,13 @@ namespace Content.Shared.Access.Components
[AutoNetworkedField] [AutoNetworkedField]
[Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite)] [Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite)]
public string? JobTitle; public string? JobTitle;
/// <summary>
/// The state of the job icon rsi.
/// </summary>
[DataField("jobIcon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
[AutoNetworkedField]
public string JobIcon = "JobIconUnknown";
} }
} }

View File

@@ -23,11 +23,13 @@ namespace Content.Shared.Access.Systems
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class AgentIDCardBoundUserInterfaceState : BoundUserInterfaceState public sealed class AgentIDCardBoundUserInterfaceState : BoundUserInterfaceState
{ {
public readonly HashSet<string> Icons;
public string CurrentName { get; } public string CurrentName { get; }
public string CurrentJob { get; } public string CurrentJob { get; }
public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob) public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob, HashSet<string> icons)
{ {
Icons = icons;
CurrentName = currentName; CurrentName = currentName;
CurrentJob = currentJob; CurrentJob = currentJob;
} }
@@ -54,4 +56,15 @@ namespace Content.Shared.Access.Systems
Job = job; Job = job;
} }
} }
[Serializable, NetSerializable]
public sealed class AgentIDCardJobIconChangedMessage : BoundUserInterfaceMessage
{
public string JobIcon { get; }
public AgentIDCardJobIconChangedMessage(string jobIcon)
{
JobIcon = jobIcon;
}
}
} }

View File

@@ -1,5 +1,6 @@
using Content.Shared.Access; using Content.Shared.Access;
using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.StatusIcon;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
@@ -80,9 +81,10 @@ namespace Content.Shared.Roles
[DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))] [DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string? JobEntity = null; public string? JobEntity = null;
[DataField("icon")] public string Icon { get; } = string.Empty; [DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
public string Icon { get; } = "JobIconUnknown";
[DataField("special", serverOnly:true)] [DataField("special", serverOnly: true)]
public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>(); public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>();
[DataField("access", customTypeSerializer: typeof(PrototypeIdListSerializer<AccessLevelPrototype>))] [DataField("access", customTypeSerializer: typeof(PrototypeIdListSerializer<AccessLevelPrototype>))]

View File

@@ -1,4 +1,4 @@
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
namespace Content.Shared.StatusIcon.Components; namespace Content.Shared.StatusIcon.Components;

View File

@@ -1,4 +1,6 @@
using Robust.Shared.Prototypes; using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Shared.StatusIcon; namespace Content.Shared.StatusIcon;
@@ -32,8 +34,17 @@ public class StatusIconData : IComparable<StatusIconData>
/// <see cref="StatusIconData"/> but in new convenient prototype form! /// <see cref="StatusIconData"/> but in new convenient prototype form!
/// </summary> /// </summary>
[Prototype("statusIcon")] [Prototype("statusIcon")]
public sealed class StatusIconPrototype : StatusIconData, IPrototype public sealed class StatusIconPrototype : StatusIconData, IPrototype, IInheritingPrototype
{ {
/// <inheritdoc />
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<StatusIconPrototype>))]
public string[]? Parents { get; }
/// <inheritdoc />
[NeverPushInheritance]
[AbstractDataField]
public bool Abstract { get; }
/// <inheritdoc/> /// <inheritdoc/>
[IdDataField] [IdDataField]
public string ID { get; } = default!; public string ID { get; } = default!;

View File

@@ -3,4 +3,5 @@ agent-id-new-1 = Gained one new access from {THE($card)}.
agent-id-new = Gained {$number} new accesses from {THE($card)}. agent-id-new = Gained {$number} new accesses from {THE($card)}.
agent-id-card-current-name = Name: agent-id-card-current-name = Name:
agent-id-card-current-job = Job: agent-id-card-current-job = Job:
agent-id-card-job-icon-label = Job icon:
agent-id-menu-title = Agent ID Card agent-id-menu-title = Agent ID Card

View File

@@ -499,6 +499,58 @@
suffix: Agent suffix: Agent
components: components:
- type: AgentIDCard - type: AgentIDCard
icons:
# TODO figure out a better way of doing this.
# Probably by adding a bool or icon-category data-field to the icon prototype?
- JobIconDetective
- JobIconQuarterMaster
- JobIconBotanist
- JobIconBoxer
- JobIconAtmosphericTechnician
- JobIconNanotrasen
- JobIconPrisoner
- JobIconJanitor
- JobIconChemist
- JobIconStationEngineer
- JobIconSecurityOfficer
- JobIconChiefMedicalOfficer
- JobIconRoboticist
- JobIconChaplain
- JobIconLawyer
- JobIconUnknown
- JobIconLibrarian
- JobIconCargoTechnician
- JobIconScientist
- JobIconResearchAssistant
- JobIconGeneticist
- JobIconClown
- JobIconCaptain
- JobIconHeadOfPersonnel
- JobIconVirologist
- JobIconShaftMiner
- JobIconPassenger
- JobIconChiefEngineer
- JobIconBartender
- JobIconHeadOfSecurity
- JobIconBrigmedic
- JobIconMedicalDoctor
- JobIconParamedic
- JobIconChef
- JobIconWarden
- JobIconResearchDirector
- JobIconMime
- JobIconMusician
- JobIconReporter
- JobIconPsychologist
- JobIconMedicalIntern
- JobIconTechnicalAssistant
- JobIconServiceWorker
- JobIconSecurityCadet
- JobIconZookeeper
- JobIconSeniorPhysician
- JobIconSeniorOfficer
- JobIconSeniorEngineer
- JobIconSeniorResearcher
- type: ActivatableUI - type: ActivatableUI
key: enum.AgentIDCardUiKey.Key key: enum.AgentIDCardUiKey.Key
inHandsOnly: true inHandsOnly: true

View File

@@ -4,7 +4,7 @@
description: job-description-cargotech description: job-description-cargotech
playTimeTracker: JobCargoTechnician playTimeTracker: JobCargoTechnician
startingGear: CargoTechGear startingGear: CargoTechGear
icon: "CargoTechnician" icon: "JobIconCargoTechnician"
supervisors: job-supervisors-qm supervisors: job-supervisors-qm
access: access:
- Cargo - Cargo

View File

@@ -17,7 +17,7 @@
time: 144000 #40 hrs time: 144000 #40 hrs
weight: 10 weight: 10
startingGear: QuartermasterGear startingGear: QuartermasterGear
icon: "QuarterMaster" icon: "JobIconQuarterMaster"
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -9,7 +9,7 @@
time: 10800 # 3 hrs time: 10800 # 3 hrs
- !type:OverallPlaytimeRequirement - !type:OverallPlaytimeRequirement
time: 36000 #10 hrs time: 36000 #10 hrs
icon: "ShaftMiner" icon: "JobIconShaftMiner"
startingGear: SalvageSpecialistGear startingGear: SalvageSpecialistGear
supervisors: job-supervisors-qm supervisors: job-supervisors-qm
access: access:

View File

@@ -4,7 +4,7 @@
description: job-description-passenger description: job-description-passenger
playTimeTracker: JobPassenger playTimeTracker: JobPassenger
startingGear: PassengerGear startingGear: PassengerGear
icon: "Passenger" icon: "JobIconPassenger"
supervisors: job-supervisors-everyone supervisors: job-supervisors-everyone
access: access:
- Maintenance - Maintenance

View File

@@ -8,7 +8,7 @@
department: Civilian department: Civilian
time: 1800 time: 1800
startingGear: BartenderGear startingGear: BartenderGear
icon: "Bartender" icon: "JobIconBartender"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Service - Service

View File

@@ -4,7 +4,7 @@
description: job-description-botanist description: job-description-botanist
playTimeTracker: JobBotanist playTimeTracker: JobBotanist
startingGear: BotanistGear startingGear: BotanistGear
icon: "Botanist" icon: "JobIconBotanist"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Service - Service

View File

@@ -4,7 +4,7 @@
description: job-description-chaplain description: job-description-chaplain
playTimeTracker: JobChaplain playTimeTracker: JobChaplain
startingGear: ChaplainGear startingGear: ChaplainGear
icon: "Chaplain" icon: "JobIconChaplain"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Chapel - Chapel

View File

@@ -8,7 +8,7 @@
department: Civilian department: Civilian
time: 1800 time: 1800
startingGear: ChefGear startingGear: ChefGear
icon: "Chef" icon: "JobIconChef"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Service - Service

View File

@@ -4,7 +4,7 @@
description: job-description-clown description: job-description-clown
playTimeTracker: JobClown playTimeTracker: JobClown
startingGear: ClownGear startingGear: ClownGear
icon: "Clown" icon: "JobIconClown"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Theatre - Theatre

View File

@@ -4,7 +4,7 @@
description: job-description-janitor description: job-description-janitor
playTimeTracker: JobJanitor playTimeTracker: JobJanitor
startingGear: JanitorGear startingGear: JanitorGear
icon: "Janitor" icon: "JobIconJanitor"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Janitor - Janitor

View File

@@ -7,7 +7,7 @@
- !type:OverallPlaytimeRequirement - !type:OverallPlaytimeRequirement
time: 36000 # 10 hrs time: 36000 # 10 hrs
startingGear: LawyerGear startingGear: LawyerGear
icon: "Lawyer" icon: "JobIconLawyer"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Service - Service

View File

@@ -4,7 +4,7 @@
description: job-description-librarian description: job-description-librarian
playTimeTracker: JobLibrarian playTimeTracker: JobLibrarian
startingGear: LibrarianGear startingGear: LibrarianGear
icon: "Librarian" icon: "JobIconLibrarian"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Service - Service

View File

@@ -7,7 +7,7 @@
- !type:OverallPlaytimeRequirement - !type:OverallPlaytimeRequirement
time: 14400 #4 hrs time: 14400 #4 hrs
startingGear: MimeGear startingGear: MimeGear
icon: "Mime" icon: "JobIconMime"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Theatre - Theatre

View File

@@ -4,7 +4,7 @@
description: job-description-musician description: job-description-musician
playTimeTracker: JobMusician playTimeTracker: JobMusician
startingGear: MusicianGear startingGear: MusicianGear
icon: "Musician" icon: "JobIconMusician"
supervisors: job-supervisors-hire supervisors: job-supervisors-hire
access: access:
- Maintenance # TODO Remove maint access for all gimmick jobs once access work is completed - Maintenance # TODO Remove maint access for all gimmick jobs once access work is completed

View File

@@ -4,7 +4,7 @@
description: job-description-serviceworker description: job-description-serviceworker
playTimeTracker: JobServiceWorker playTimeTracker: JobServiceWorker
startingGear: ServiceWorkerGear startingGear: ServiceWorkerGear
icon: "ServiceWorker" icon: "JobIconServiceWorker"
supervisors: job-supervisors-service supervisors: job-supervisors-service
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -18,7 +18,7 @@
time: 54000 # 15 hours time: 54000 # 15 hours
weight: 20 weight: 20
startingGear: CaptainGear startingGear: CaptainGear
icon: "Captain" icon: "JobIconCaptain"
requireAdminNotify: true requireAdminNotify: true
joinNotifyCrew: true joinNotifyCrew: true
supervisors: job-supervisors-centcom supervisors: job-supervisors-centcom

View File

@@ -5,7 +5,7 @@
playTimeTracker: JobCentralCommandOfficial playTimeTracker: JobCentralCommandOfficial
setPreference: false setPreference: false
startingGear: CentcomGear startingGear: CentcomGear
icon: "Nanotrasen" icon: "JobIconNanotrasen"
supervisors: job-supervisors-hos supervisors: job-supervisors-hos
canBeAntag: false canBeAntag: false
accessGroups: accessGroups:

View File

@@ -18,7 +18,7 @@
time: 36000 # 10 hours time: 36000 # 10 hours
weight: 20 weight: 20
startingGear: HoPGear startingGear: HoPGear
icon: "HeadOfPersonnel" icon: "JobIconHeadOfPersonnel"
requireAdminNotify: true requireAdminNotify: true
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
canBeAntag: false canBeAntag: false

View File

@@ -8,7 +8,7 @@
department: Engineering department: Engineering
time: 54000 # 15 hrs time: 54000 # 15 hrs
startingGear: AtmosphericTechnicianGear startingGear: AtmosphericTechnicianGear
icon: "AtmosphericTechnician" icon: "JobIconAtmosphericTechnician"
supervisors: job-supervisors-ce supervisors: job-supervisors-ce
access: access:
- Maintenance - Maintenance

View File

@@ -17,7 +17,7 @@
time: 144000 #40 hrs time: 144000 #40 hrs
weight: 10 weight: 10
startingGear: ChiefEngineerGear startingGear: ChiefEngineerGear
icon: "ChiefEngineer" icon: "JobIconChiefEngineer"
requireAdminNotify: true requireAdminNotify: true
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
canBeAntag: false canBeAntag: false

View File

@@ -14,7 +14,7 @@
department: Engineering department: Engineering
time: 216000 # 60 hrs time: 216000 # 60 hrs
startingGear: SeniorEngineerGear startingGear: SeniorEngineerGear
icon: "SeniorEngineer" icon: "JobIconSeniorEngineer"
supervisors: job-supervisors-ce supervisors: job-supervisors-ce
access: access:
- Maintenance - Maintenance

View File

@@ -8,7 +8,7 @@
department: Engineering department: Engineering
time: 14400 #4 hrs time: 14400 #4 hrs
startingGear: StationEngineerGear startingGear: StationEngineerGear
icon: "StationEngineer" icon: "JobIconStationEngineer"
supervisors: job-supervisors-ce supervisors: job-supervisors-ce
access: access:
- Maintenance - Maintenance

View File

@@ -9,7 +9,7 @@
time: 54000 #15 hrs time: 54000 #15 hrs
inverted: true # stop playing intern if you're good at engineering! inverted: true # stop playing intern if you're good at engineering!
startingGear: TechnicalAssistantGear startingGear: TechnicalAssistantGear
icon: "TechnicalAssistant" icon: "JobIconTechnicalAssistant"
supervisors: job-supervisors-engineering supervisors: job-supervisors-engineering
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -6,7 +6,7 @@
playTimeTracker: JobERTLeader playTimeTracker: JobERTLeader
setPreference: false setPreference: false
startingGear: ERTLeaderGearEVA startingGear: ERTLeaderGearEVA
icon: "Nanotrasen" icon: "JobIconNanotrasen"
supervisors: job-supervisors-centcom supervisors: job-supervisors-centcom
canBeAntag: false canBeAntag: false
accessGroups: accessGroups:
@@ -51,7 +51,7 @@
playTimeTracker: JobERTEngineer playTimeTracker: JobERTEngineer
setPreference: false setPreference: false
startingGear: ERTEngineerGearEVA startingGear: ERTEngineerGearEVA
icon: "Nanotrasen" icon: "JobIconNanotrasen"
supervisors: job-supervisors-centcom supervisors: job-supervisors-centcom
canBeAntag: false canBeAntag: false
accessGroups: accessGroups:
@@ -96,7 +96,7 @@
playTimeTracker: JobERTSecurity playTimeTracker: JobERTSecurity
setPreference: false setPreference: false
startingGear: ERTEngineerGearEVA startingGear: ERTEngineerGearEVA
icon: "Nanotrasen" icon: "JobIconNanotrasen"
supervisors: job-supervisors-centcom supervisors: job-supervisors-centcom
canBeAntag: false canBeAntag: false
accessGroups: accessGroups:
@@ -143,7 +143,7 @@
playTimeTracker: JobERTMedical playTimeTracker: JobERTMedical
setPreference: false setPreference: false
startingGear: ERTMedicalGearEVA startingGear: ERTMedicalGearEVA
icon: "Nanotrasen" icon: "JobIconNanotrasen"
supervisors: job-supervisors-centcom supervisors: job-supervisors-centcom
canBeAntag: false canBeAntag: false
accessGroups: accessGroups:
@@ -190,7 +190,7 @@
playTimeTracker: JobERTJanitor playTimeTracker: JobERTJanitor
setPreference: false setPreference: false
startingGear: ERTJanitorGearEVA startingGear: ERTJanitorGearEVA
icon: "Nanotrasen" icon: "JobIconNanotrasen"
supervisors: job-supervisors-centcom supervisors: job-supervisors-centcom
canBeAntag: false canBeAntag: false
accessGroups: accessGroups:

View File

@@ -8,7 +8,7 @@
department: Medical department: Medical
time: 14400 #4 hrs time: 14400 #4 hrs
startingGear: ChemistGear startingGear: ChemistGear
icon: "Chemist" icon: "JobIconChemist"
supervisors: job-supervisors-cmo supervisors: job-supervisors-cmo
access: access:
- Medical - Medical

View File

@@ -19,7 +19,7 @@
time: 144000 #40 hrs time: 144000 #40 hrs
weight: 10 weight: 10
startingGear: CMOGear startingGear: CMOGear
icon: "ChiefMedicalOfficer" icon: "JobIconChiefMedicalOfficer"
requireAdminNotify: true requireAdminNotify: true
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
canBeAntag: false canBeAntag: false

View File

@@ -8,7 +8,7 @@
department: Medical department: Medical
time: 14400 #4 hrs time: 14400 #4 hrs
startingGear: DoctorGear startingGear: DoctorGear
icon: "MedicalDoctor" icon: "JobIconMedicalDoctor"
supervisors: job-supervisors-cmo supervisors: job-supervisors-cmo
access: access:
- Medical - Medical

View File

@@ -9,7 +9,7 @@
time: 54000 # 15 hrs time: 54000 # 15 hrs
inverted: true # stop playing intern if you're good at med! inverted: true # stop playing intern if you're good at med!
startingGear: MedicalInternGear startingGear: MedicalInternGear
icon: "MedicalIntern" icon: "JobIconMedicalIntern"
supervisors: job-supervisors-medicine supervisors: job-supervisors-medicine
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -10,7 +10,7 @@
- !type:OverallPlaytimeRequirement - !type:OverallPlaytimeRequirement
time: 54000 # 15 hrs time: 54000 # 15 hrs
startingGear: ParamedicGear startingGear: ParamedicGear
icon: "Paramedic" icon: "JobIconParamedic"
supervisors: job-supervisors-cmo supervisors: job-supervisors-cmo
access: access:
- Medical - Medical

View File

@@ -14,7 +14,7 @@
department: Medical department: Medical
time: 216000 # 60 hrs time: 216000 # 60 hrs
startingGear: SeniorPhysicianGear startingGear: SeniorPhysicianGear
icon: "SeniorPhysician" icon: "JobIconSeniorPhysician"
supervisors: job-supervisors-cmo supervisors: job-supervisors-cmo
access: access:
- Medical - Medical

View File

@@ -9,7 +9,7 @@
time: 54000 #15 hrs time: 54000 #15 hrs
inverted: true # stop playing intern if you're good at science! inverted: true # stop playing intern if you're good at science!
startingGear: ResearchAssistantGear startingGear: ResearchAssistantGear
icon: "ResearchAssistant" icon: "JobIconResearchAssistant"
supervisors: job-supervisors-science supervisors: job-supervisors-science
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -11,7 +11,7 @@
time: 144000 #40 hrs time: 144000 #40 hrs
weight: 10 weight: 10
startingGear: ResearchDirectorGear startingGear: ResearchDirectorGear
icon: "ResearchDirector" icon: "JobIconResearchDirector"
requireAdminNotify: true requireAdminNotify: true
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
canBeAntag: false canBeAntag: false

View File

@@ -8,7 +8,7 @@
department: Science department: Science
time: 14400 #4 hrs time: 14400 #4 hrs
startingGear: ScientistGear startingGear: ScientistGear
icon: "Scientist" icon: "JobIconScientist"
supervisors: job-supervisors-rd supervisors: job-supervisors-rd
access: access:
- Research - Research

View File

@@ -8,7 +8,7 @@
department: Science department: Science
time: 216000 #60 hrs time: 216000 #60 hrs
startingGear: SeniorResearcherGear startingGear: SeniorResearcherGear
icon: "SeniorResearcher" icon: "JobIconSeniorResearcher"
supervisors: job-supervisors-rd supervisors: job-supervisors-rd
access: access:
- Research - Research

View File

@@ -8,7 +8,7 @@
department: Security department: Security
time: 54000 # 15 hours time: 54000 # 15 hours
startingGear: DetectiveGear startingGear: DetectiveGear
icon: "Detective" icon: "JobIconDetective"
supervisors: job-supervisors-hos supervisors: job-supervisors-hos
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -17,7 +17,7 @@
time: 144000 #40 hrs time: 144000 #40 hrs
weight: 10 weight: 10
startingGear: HoSGear startingGear: HoSGear
icon: "HeadOfSecurity" icon: "JobIconHeadOfSecurity"
requireAdminNotify: true requireAdminNotify: true
supervisors: job-supervisors-captain supervisors: job-supervisors-captain
canBeAntag: false canBeAntag: false

View File

@@ -11,7 +11,7 @@
time: 54000 #15 hrs time: 54000 #15 hrs
inverted: true # stop playing intern if you're good at security! inverted: true # stop playing intern if you're good at security!
startingGear: SecurityCadetGear startingGear: SecurityCadetGear
icon: "SecurityCadet" icon: "JobIconSecurityCadet"
supervisors: job-supervisors-security supervisors: job-supervisors-security
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -8,7 +8,7 @@
department: Security department: Security
time: 36000 #10 hrs time: 36000 #10 hrs
startingGear: SecurityOfficerGear startingGear: SecurityOfficerGear
icon: "SecurityOfficer" icon: "JobIconSecurityOfficer"
supervisors: job-supervisors-hos supervisors: job-supervisors-hos
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -17,7 +17,7 @@
department: Security department: Security
time: 216000 # 60 hrs time: 216000 # 60 hrs
startingGear: SeniorOfficerGear startingGear: SeniorOfficerGear
icon: "SeniorOfficer" icon: "JobIconSeniorOfficer"
supervisors: job-supervisors-hos supervisors: job-supervisors-hos
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -8,7 +8,7 @@
role: JobSecurityOfficer role: JobSecurityOfficer
time: 36000 #10 hrs time: 36000 #10 hrs
startingGear: WardenGear startingGear: WardenGear
icon: "Warden" icon: "JobIconWarden"
supervisors: job-supervisors-hos supervisors: job-supervisors-hos
canBeAntag: false canBeAntag: false
access: access:

View File

@@ -4,7 +4,7 @@
description: job-description-boxer description: job-description-boxer
playTimeTracker: JobBoxer playTimeTracker: JobBoxer
startingGear: BoxerGear startingGear: BoxerGear
icon: "Boxer" icon: "JobIconBoxer"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Service - Service

View File

@@ -4,7 +4,7 @@
description: job-description-psychologist description: job-description-psychologist
playTimeTracker: JobPsychologist playTimeTracker: JobPsychologist
startingGear: PsychologistGear startingGear: PsychologistGear
icon: "Psychologist" icon: "JobIconPsychologist"
supervisors: job-supervisors-cmo supervisors: job-supervisors-cmo
access: access:
- Medical - Medical

View File

@@ -4,7 +4,7 @@
description: job-description-reporter description: job-description-reporter
playTimeTracker: JobReporter playTimeTracker: JobReporter
startingGear: ReporterGear startingGear: ReporterGear
icon: "Reporter" icon: "JobIconReporter"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Service - Service

View File

@@ -4,7 +4,7 @@
description: job-description-zookeeper description: job-description-zookeeper
playTimeTracker: JobZookeeper playTimeTracker: JobZookeeper
startingGear: ZookeeperGear startingGear: ZookeeperGear
icon: "Zookeeper" icon: "JobIconZookeeper"
supervisors: job-supervisors-hop supervisors: job-supervisors-hop
access: access:
- Service - Service

View File

@@ -0,0 +1,361 @@
- type: statusIcon
id: JobIcon
abstract: true
priority: 1
- type: statusIcon
parent: JobIcon
id: JobIconDetective
icon:
sprite: Interface/Misc/job_icons.rsi
state: Detective
- type: statusIcon
parent: JobIcon
id: JobIconQuarterMaster
icon:
sprite: Interface/Misc/job_icons.rsi
state: QuarterMaster
- type: statusIcon
parent: JobIcon
id: JobIconBotanist
icon:
sprite: Interface/Misc/job_icons.rsi
state: Botanist
- type: statusIcon
parent: JobIcon
id: JobIconBoxer
icon:
sprite: Interface/Misc/job_icons.rsi
state: Boxer
- type: statusIcon
parent: JobIcon
id: JobIconAtmosphericTechnician
icon:
sprite: Interface/Misc/job_icons.rsi
state: AtmosphericTechnician
- type: statusIcon
parent: JobIcon
id: JobIconNanotrasen
icon:
sprite: Interface/Misc/job_icons.rsi
state: Nanotrasen
- type: statusIcon
parent: JobIcon
id: JobIconPrisoner
icon:
sprite: Interface/Misc/job_icons.rsi
state: Prisoner
- type: statusIcon
parent: JobIcon
id: JobIconJanitor
icon:
sprite: Interface/Misc/job_icons.rsi
state: Janitor
- type: statusIcon
parent: JobIcon
id: JobIconChemist
icon:
sprite: Interface/Misc/job_icons.rsi
state: Chemist
- type: statusIcon
parent: JobIcon
id: JobIconStationEngineer
icon:
sprite: Interface/Misc/job_icons.rsi
state: StationEngineer
- type: statusIcon
parent: JobIcon
id: JobIconSecurityOfficer
icon:
sprite: Interface/Misc/job_icons.rsi
state: SecurityOfficer
- type: statusIcon
parent: JobIcon
id: JobIconNoId
icon:
sprite: Interface/Misc/job_icons.rsi
state: NoId
- type: statusIcon
parent: JobIcon
id: JobIconChiefMedicalOfficer
icon:
sprite: Interface/Misc/job_icons.rsi
state: ChiefMedicalOfficer
- type: statusIcon
parent: JobIcon
id: JobIconRoboticist
icon:
sprite: Interface/Misc/job_icons.rsi
state: Roboticist
- type: statusIcon
parent: JobIcon
id: JobIconChaplain
icon:
sprite: Interface/Misc/job_icons.rsi
state: Chaplain
- type: statusIcon
parent: JobIcon
id: JobIconLawyer
icon:
sprite: Interface/Misc/job_icons.rsi
state: Lawyer
- type: statusIcon
parent: JobIcon
id: JobIconUnknown
icon:
sprite: Interface/Misc/job_icons.rsi
state: Unknown
- type: statusIcon
parent: JobIcon
id: JobIconLibrarian
icon:
sprite: Interface/Misc/job_icons.rsi
state: Librarian
- type: statusIcon
parent: JobIcon
id: JobIconCargoTechnician
icon:
sprite: Interface/Misc/job_icons.rsi
state: CargoTechnician
- type: statusIcon
parent: JobIcon
id: JobIconScientist
icon:
sprite: Interface/Misc/job_icons.rsi
state: Scientist
- type: statusIcon
parent: JobIcon
id: JobIconResearchAssistant
icon:
sprite: Interface/Misc/job_icons.rsi
state: ResearchAssistant
- type: statusIcon
parent: JobIcon
id: JobIconGeneticist
icon:
sprite: Interface/Misc/job_icons.rsi
state: Geneticist
- type: statusIcon
parent: JobIcon
id: JobIconClown
icon:
sprite: Interface/Misc/job_icons.rsi
state: Clown
- type: statusIcon
parent: JobIcon
id: JobIconCaptain
icon:
sprite: Interface/Misc/job_icons.rsi
state: Captain
- type: statusIcon
parent: JobIcon
id: JobIconHeadOfPersonnel
icon:
sprite: Interface/Misc/job_icons.rsi
state: HeadOfPersonnel
- type: statusIcon
parent: JobIcon
id: JobIconVirologist
icon:
sprite: Interface/Misc/job_icons.rsi
state: Virologist
- type: statusIcon
parent: JobIcon
id: JobIconShaftMiner
icon:
sprite: Interface/Misc/job_icons.rsi
state: ShaftMiner
- type: statusIcon
parent: JobIcon
id: JobIconPassenger
icon:
sprite: Interface/Misc/job_icons.rsi
state: Passenger
- type: statusIcon
parent: JobIcon
id: JobIconChiefEngineer
icon:
sprite: Interface/Misc/job_icons.rsi
state: ChiefEngineer
- type: statusIcon
parent: JobIcon
id: JobIconBartender
icon:
sprite: Interface/Misc/job_icons.rsi
state: Bartender
- type: statusIcon
parent: JobIcon
id: JobIconHeadOfSecurity
icon:
sprite: Interface/Misc/job_icons.rsi
state: HeadOfSecurity
- type: statusIcon
parent: JobIcon
id: JobIconBrigmedic
icon:
sprite: Interface/Misc/job_icons.rsi
state: Brigmedic
- type: statusIcon
parent: JobIcon
id: JobIconMedicalDoctor
icon:
sprite: Interface/Misc/job_icons.rsi
state: MedicalDoctor
- type: statusIcon
parent: JobIcon
id: JobIconParamedic
icon:
sprite: Interface/Misc/job_icons.rsi
state: Paramedic
- type: statusIcon
parent: JobIcon
id: JobIconChef
icon:
sprite: Interface/Misc/job_icons.rsi
state: Chef
- type: statusIcon
parent: JobIcon
id: JobIconWarden
icon:
sprite: Interface/Misc/job_icons.rsi
state: Warden
- type: statusIcon
parent: JobIcon
id: JobIconResearchDirector
icon:
sprite: Interface/Misc/job_icons.rsi
state: ResearchDirector
- type: statusIcon
parent: JobIcon
id: JobIconMime
icon:
sprite: Interface/Misc/job_icons.rsi
state: Mime
- type: statusIcon
parent: JobIcon
id: JobIconMusician
icon:
sprite: Interface/Misc/job_icons.rsi
state: Musician
- type: statusIcon
parent: JobIcon
id: JobIconReporter
icon:
sprite: Interface/Misc/job_icons.rsi
state: Reporter
- type: statusIcon
parent: JobIcon
id: JobIconPsychologist
icon:
sprite: Interface/Misc/job_icons.rsi
state: Psychologist
- type: statusIcon
parent: JobIcon
id: JobIconMedicalIntern
icon:
sprite: Interface/Misc/job_icons.rsi
state: MedicalIntern
- type: statusIcon
parent: JobIcon
id: JobIconTechnicalAssistant
icon:
sprite: Interface/Misc/job_icons.rsi
state: TechnicalAssistant
- type: statusIcon
parent: JobIcon
id: JobIconServiceWorker
icon:
sprite: Interface/Misc/job_icons.rsi
state: ServiceWorker
- type: statusIcon
parent: JobIcon
id: JobIconSecurityCadet
icon:
sprite: Interface/Misc/job_icons.rsi
state: SecurityCadet
- type: statusIcon
parent: JobIcon
id: JobIconZombie # This is a perfectly legitimate profession to pursue
icon:
sprite: Interface/Misc/job_icons.rsi
state: Zombie
- type: statusIcon
parent: JobIcon
id: JobIconZookeeper
icon:
sprite: Interface/Misc/job_icons.rsi
state: Zookeeper
- type: statusIcon
parent: JobIcon
id: JobIconSeniorPhysician
icon:
sprite: Interface/Misc/job_icons.rsi
state: SeniorPhysician
- type: statusIcon
parent: JobIcon
id: JobIconSeniorOfficer
icon:
sprite: Interface/Misc/job_icons.rsi
state: SeniorOfficer
- type: statusIcon
parent: JobIcon
id: JobIconSeniorEngineer
icon:
sprite: Interface/Misc/job_icons.rsi
state: SeniorEngineer
- type: statusIcon
parent: JobIcon
id: JobIconSeniorResearcher
icon:
sprite: Interface/Misc/job_icons.rsi
state: SeniorResearcher