Add tooltips to the agent ID job icons and improve status icon prototypes (#28575)

* add tooltips to agentid job icons

* forgot to stage this

* make StatusIconPrototype abstract

* minor visual improvements

* cleanup

* use currentculture to sort job names

* review
This commit is contained in:
slarticodefast
2024-08-09 08:14:07 +02:00
committed by GitHub
parent eab0c34822
commit e0d30aff4e
38 changed files with 362 additions and 236 deletions

View File

@@ -38,7 +38,7 @@ namespace Content.Client.Access.UI
SendMessage(new AgentIDCardJobChangedMessage(newJob));
}
public void OnJobIconChanged(ProtoId<StatusIconPrototype> newJobIconId)
public void OnJobIconChanged(ProtoId<JobIconPrototype> newJobIconId)
{
SendMessage(new AgentIDCardJobIconChangedMessage(newJobIconId));
}
@@ -55,7 +55,7 @@ namespace Content.Client.Access.UI
_window.SetCurrentName(cast.CurrentName);
_window.SetCurrentJob(cast.CurrentJob);
_window.SetAllowedIcons(cast.Icons, cast.CurrentJobIconId);
_window.SetAllowedIcons(cast.CurrentJobIconId);
}
}
}

View File

@@ -6,12 +6,9 @@
<LineEdit Name="NameLineEdit" />
<Label Name="CurrentJob" Text="{Loc 'agent-id-card-current-job'}" />
<LineEdit Name="JobLineEdit" />
<BoxContainer Orientation="Horizontal">
<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>
</DefaultWindow>

View File

@@ -8,6 +8,7 @@ using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using System.Numerics;
using System.Linq;
namespace Content.Client.Access.UI
{
@@ -23,7 +24,7 @@ namespace Content.Client.Access.UI
public event Action<string>? OnNameChanged;
public event Action<string>? OnJobChanged;
public event Action<ProtoId<StatusIconPrototype>>? OnJobIconChanged;
public event Action<ProtoId<JobIconPrototype>>? OnJobIconChanged;
public AgentIDCardWindow()
{
@@ -38,17 +39,16 @@ namespace Content.Client.Access.UI
JobLineEdit.OnFocusExit += e => OnJobChanged?.Invoke(e.Text);
}
public void SetAllowedIcons(HashSet<ProtoId<StatusIconPrototype>> icons, string currentJobIconId)
public void SetAllowedIcons(string currentJobIconId)
{
IconGrid.DisposeAllChildren();
var jobIconGroup = new ButtonGroup();
var jobIconButtonGroup = new ButtonGroup();
var i = 0;
foreach (var jobIconId in icons)
var icons = _prototypeManager.EnumeratePrototypes<JobIconPrototype>().Where(icon => icon.AllowSelection).ToList();
icons.Sort((x, y) => string.Compare(x.LocalizedJobName, y.LocalizedJobName, StringComparison.CurrentCulture));
foreach (var jobIcon in icons)
{
if (!_prototypeManager.TryIndex(jobIconId, out var jobIcon))
continue;
String styleBase = StyleBase.ButtonOpenBoth;
var modulo = i % JobIconColumnCount;
if (modulo == 0)
@@ -62,8 +62,9 @@ namespace Content.Client.Access.UI
Access = AccessLevel.Public,
StyleClasses = { styleBase },
MaxSize = new Vector2(42, 28),
Group = jobIconGroup,
Pressed = i == 0,
Group = jobIconButtonGroup,
Pressed = currentJobIconId == jobIcon.ID,
ToolTip = jobIcon.LocalizedJobName
};
// Generate buttons textures
@@ -78,9 +79,6 @@ namespace Content.Client.Access.UI
jobIconButton.OnPressed += _ => OnJobIconChanged?.Invoke(jobIcon.ID);
IconGrid.AddChild(jobIconButton);
if (jobIconId.Equals(currentJobIconId))
jobIconButton.Pressed = true;
i++;
}
}

View File

@@ -51,7 +51,7 @@ public sealed class CrewManifestSection : BoxContainer
title.SetMessage(entry.JobTitle);
if (prototypeManager.TryIndex<StatusIconPrototype>(entry.JobIcon, out var jobIcon))
if (prototypeManager.TryIndex<JobIconPrototype>(entry.JobIcon, out var jobIcon))
{
var icon = new TextureRect()
{

View File

@@ -257,7 +257,7 @@ public sealed partial class CrewMonitoringWindow : FancyWindow
mainContainer.AddChild(jobContainer);
// Job icon
if (_prototypeManager.TryIndex<StatusIconPrototype>(sensor.JobIcon, out var proto))
if (_prototypeManager.TryIndex<JobIconPrototype>(sensor.JobIcon, out var proto))
{
var jobIcon = new TextureRect()
{

View File

@@ -33,7 +33,7 @@ public sealed class EntityHealthBarOverlay : Overlay
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
public HashSet<string> DamageContainers = new();
public ProtoId<StatusIconPrototype>? StatusIcon;
public ProtoId<HealthIconPrototype>? StatusIcon;
public EntityHealthBarOverlay(IEntityManager entManager, IPrototypeManager prototype)
{

View File

@@ -53,17 +53,17 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem<ShowHealthIconsCo
args.StatusIcons.AddRange(healthIcons);
}
private IReadOnlyList<StatusIconPrototype> DecideHealthIcons(Entity<DamageableComponent> entity)
private IReadOnlyList<HealthIconPrototype> DecideHealthIcons(Entity<DamageableComponent> entity)
{
var damageableComponent = entity.Comp;
if (damageableComponent.DamageContainerID == null ||
!DamageContainers.Contains(damageableComponent.DamageContainerID))
{
return Array.Empty<StatusIconPrototype>();
return Array.Empty<HealthIconPrototype>();
}
var result = new List<StatusIconPrototype>();
var result = new List<HealthIconPrototype>();
// Here you could check health status, diseases, mind status, etc. and pick a good icon, or multiple depending on whatever.
if (damageableComponent?.DamageContainerID == "Biological")

View File

@@ -13,7 +13,7 @@ public sealed class ShowJobIconsSystem : EquipmentHudSystem<ShowJobIconsComponen
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
[ValidatePrototypeId<StatusIconPrototype>]
[ValidatePrototypeId<JobIconPrototype>]
private const string JobIconForNoId = "JobIconNoId";
public override void Initialize()
@@ -52,7 +52,7 @@ public sealed class ShowJobIconsSystem : EquipmentHudSystem<ShowJobIconsComponen
}
}
if (_prototype.TryIndex<StatusIconPrototype>(iconId, out var iconPrototype))
if (_prototype.TryIndex<JobIconPrototype>(iconId, out var iconPrototype))
ev.StatusIcons.Add(iconPrototype);
else
Log.Error($"Invalid job icon prototype: {iconPrototype}");

View File

@@ -22,7 +22,7 @@ public sealed class ShowSyndicateIconsSystem : EquipmentHudSystem<ShowSyndicateI
if (!IsActive)
return;
if (_prototype.TryIndex<StatusIconPrototype>(component.SyndStatusIcon, out var iconPrototype))
if (_prototype.TryIndex<FactionIconPrototype>(component.SyndStatusIcon, out var iconPrototype))
ev.StatusIcons.Add(iconPrototype);
}
}

View File

@@ -1,15 +1,7 @@
using Content.Shared.StatusIcon;
using Robust.Shared.Prototypes;
namespace Content.Server.Access.Components;
namespace Content.Server.Access.Components
{
[RegisterComponent]
public sealed partial class AgentIDCardComponent : Component
{
/// <summary>
/// Set of job icons that the agent ID card can show.
/// Allows an ID card to copy accesses from other IDs and to change the name, job title and job icon via an interface.
/// </summary>
[DataField]
public HashSet<ProtoId<StatusIconPrototype>> Icons;
}
}
[RegisterComponent]
public sealed partial class AgentIDCardComponent : Component { }

View File

@@ -67,7 +67,7 @@ namespace Content.Server.Access.Systems
if (!TryComp<IdCardComponent>(uid, out var idCard))
return;
var state = new AgentIDCardBoundUserInterfaceState(idCard.FullName ?? "", idCard.JobTitle ?? "", idCard.JobIcon ?? "", component.Icons);
var state = new AgentIDCardBoundUserInterfaceState(idCard.FullName ?? "", idCard.JobTitle ?? "", idCard.JobIcon);
_uiSystem.SetUiState(uid, AgentIDCardUiKey.Key, state);
}
@@ -101,7 +101,7 @@ namespace Content.Server.Access.Systems
_cardSystem.TryChangeJobDepartment(uid, job, idCard);
}
private bool TryFindJobProtoFromIcon(StatusIconPrototype jobIcon, [NotNullWhen(true)] out JobPrototype? job)
private bool TryFindJobProtoFromIcon(JobIconPrototype jobIcon, [NotNullWhen(true)] out JobPrototype? job)
{
foreach (var jobPrototype in _prototypeManager.EnumeratePrototypes<JobPrototype>())
{

View File

@@ -323,7 +323,6 @@ public sealed class SuitSensorSystem : EntitySystem
userName = card.Comp.FullName;
if (card.Comp.JobTitle != null)
userJob = card.Comp.JobTitle;
if (card.Comp.JobIcon != null)
userJobIcon = card.Comp.JobIcon;
foreach (var department in card.Comp.JobDepartments)

View File

@@ -2,7 +2,7 @@ using Content.Shared.Access.Systems;
using Content.Shared.PDA;
using Content.Shared.StatusIcon;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Prototypes;
namespace Content.Shared.Access.Components;
@@ -11,34 +11,34 @@ namespace Content.Shared.Access.Components;
[Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite)]
public sealed partial class IdCardComponent : Component
{
[DataField("fullName"), ViewVariables(VVAccess.ReadWrite)]
[DataField]
[AutoNetworkedField]
// FIXME Friends
public string? FullName;
[DataField("jobTitle")]
[DataField]
[AutoNetworkedField]
[Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite), ViewVariables(VVAccess.ReadWrite)]
[Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite)]
public string? JobTitle;
/// <summary>
/// The state of the job icon rsi.
/// </summary>
[DataField("jobIcon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
[DataField]
[AutoNetworkedField]
public string JobIcon = "JobIconUnknown";
public ProtoId<JobIconPrototype> JobIcon = "JobIconUnknown";
/// <summary>
/// The unlocalized names of the departments associated with the job
/// </summary>
[DataField("jobDepartments")]
[DataField]
[AutoNetworkedField]
public List<LocId> JobDepartments = new();
/// <summary>
/// Determines if accesses from this card should be logged by <see cref="AccessReaderComponent"/>
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
[DataField]
public bool BypassLogging;
[DataField]

View File

@@ -25,14 +25,12 @@ namespace Content.Shared.Access.Systems
[Serializable, NetSerializable]
public sealed class AgentIDCardBoundUserInterfaceState : BoundUserInterfaceState
{
public readonly HashSet<ProtoId<StatusIconPrototype>> Icons;
public string CurrentName { get; }
public string CurrentJob { get; }
public string CurrentJobIconId { get; }
public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob, string currentJobIconId, HashSet<ProtoId<StatusIconPrototype>> icons)
public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob, string currentJobIconId)
{
Icons = icons;
CurrentName = currentName;
CurrentJob = currentJob;
CurrentJobIconId = currentJobIconId;
@@ -64,9 +62,9 @@ namespace Content.Shared.Access.Systems
[Serializable, NetSerializable]
public sealed class AgentIDCardJobIconChangedMessage : BoundUserInterfaceMessage
{
public ProtoId<StatusIconPrototype> JobIconId { get; }
public ProtoId<JobIconPrototype> JobIconId { get; }
public AgentIDCardJobIconChangedMessage(ProtoId<StatusIconPrototype> jobIconId)
public AgentIDCardJobIconChangedMessage(ProtoId<JobIconPrototype> jobIconId)
{
JobIconId = jobIconId;
}

View File

@@ -114,7 +114,7 @@ public abstract class SharedIdCardSystem : EntitySystem
return true;
}
public bool TryChangeJobIcon(EntityUid uid, StatusIconPrototype jobIcon, IdCardComponent? id = null, EntityUid? player = null)
public bool TryChangeJobIcon(EntityUid uid, JobIconPrototype jobIcon, IdCardComponent? id = null, EntityUid? player = null)
{
if (!Resolve(uid, ref id))
{

View File

@@ -66,7 +66,7 @@ namespace Content.Shared.Damage
public List<ProtoId<DamageTypePrototype>> RadiationDamageTypeIDs = new() { "Radiation" };
[DataField]
public Dictionary<MobState, ProtoId<StatusIconPrototype>> HealthIcons = new()
public Dictionary<MobState, ProtoId<HealthIconPrototype>> HealthIcons = new()
{
{ MobState.Alive, "HealthIconFine" },
{ MobState.Critical, "HealthIconCritical" },
@@ -74,7 +74,7 @@ namespace Content.Shared.Damage
};
[DataField]
public ProtoId<StatusIconPrototype> RottingIcon = "HealthIconRotting";
public ProtoId<HealthIconPrototype> RottingIcon = "HealthIconRotting";
[DataField]
public FixedPoint2? HealthBarThreshold;

View File

@@ -12,5 +12,5 @@ namespace Content.Shared.Mindshield.Components;
public sealed partial class MindShieldComponent : Component
{
[DataField, ViewVariables(VVAccess.ReadWrite)]
public ProtoId<StatusIconPrototype> MindShieldStatusIcon = "MindShieldIcon";
public ProtoId<SecurityIconPrototype> MindShieldStatusIcon = "MindShieldIcon";
}

View File

@@ -17,6 +17,6 @@ public sealed partial class NukeOperativeComponent : Component
/// <summary>
///
/// </summary>
[DataField("syndStatusIcon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
[DataField("syndStatusIcon", customTypeSerializer: typeof(PrototypeIdSerializer<FactionIconPrototype>))]
public string SyndStatusIcon = "SyndicateFaction";
}

View File

@@ -24,18 +24,18 @@ public sealed class HungerSystem : EntitySystem
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
[Dependency] private readonly SharedJetpackSystem _jetpack = default!;
[ValidatePrototypeId<StatusIconPrototype>]
[ValidatePrototypeId<SatiationIconPrototype>]
private const string HungerIconOverfedId = "HungerIconOverfed";
[ValidatePrototypeId<StatusIconPrototype>]
[ValidatePrototypeId<SatiationIconPrototype>]
private const string HungerIconPeckishId = "HungerIconPeckish";
[ValidatePrototypeId<StatusIconPrototype>]
[ValidatePrototypeId<SatiationIconPrototype>]
private const string HungerIconStarvingId = "HungerIconStarving";
private StatusIconPrototype? _hungerIconOverfed;
private StatusIconPrototype? _hungerIconPeckish;
private StatusIconPrototype? _hungerIconStarving;
private SatiationIconPrototype? _hungerIconOverfed;
private SatiationIconPrototype? _hungerIconPeckish;
private SatiationIconPrototype? _hungerIconStarving;
public override void Initialize()
{
@@ -216,7 +216,7 @@ public sealed class HungerSystem : EntitySystem
}
}
public bool TryGetStatusIconPrototype(HungerComponent component, [NotNullWhen(true)] out StatusIconPrototype? prototype)
public bool TryGetStatusIconPrototype(HungerComponent component, [NotNullWhen(true)] out SatiationIconPrototype? prototype)
{
switch (component.CurrentThreshold)
{

View File

@@ -22,18 +22,18 @@ public sealed class ThirstSystem : EntitySystem
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
[Dependency] private readonly SharedJetpackSystem _jetpack = default!;
[ValidatePrototypeId<StatusIconPrototype>]
[ValidatePrototypeId<SatiationIconPrototype>]
private const string ThirstIconOverhydratedId = "ThirstIconOverhydrated";
[ValidatePrototypeId<StatusIconPrototype>]
[ValidatePrototypeId<SatiationIconPrototype>]
private const string ThirstIconThirstyId = "ThirstIconThirsty";
[ValidatePrototypeId<StatusIconPrototype>]
[ValidatePrototypeId<SatiationIconPrototype>]
private const string ThirstIconParchedId = "ThirstIconParched";
private StatusIconPrototype? _thirstIconOverhydrated = null;
private StatusIconPrototype? _thirstIconThirsty = null;
private StatusIconPrototype? _thirstIconParched = null;
private SatiationIconPrototype? _thirstIconOverhydrated = null;
private SatiationIconPrototype? _thirstIconThirsty = null;
private SatiationIconPrototype? _thirstIconParched = null;
public override void Initialize()
{
@@ -128,7 +128,7 @@ public sealed class ThirstSystem : EntitySystem
}
}
public bool TryGetStatusIconPrototype(ThirstComponent component, out StatusIconPrototype? prototype)
public bool TryGetStatusIconPrototype(ThirstComponent component, out SatiationIconPrototype? prototype)
{
switch (component.CurrentThirstThreshold)
{

View File

@@ -19,5 +19,5 @@ public sealed partial class ShowHealthBarsComponent : Component
public List<string> DamageContainers = new();
[DataField]
public ProtoId<StatusIconPrototype>? HealthStatusIcon = "HealthIconFine";
public ProtoId<HealthIconPrototype>? HealthStatusIcon = "HealthIconFine";
}

View File

@@ -15,7 +15,7 @@ public sealed partial class HeadRevolutionaryComponent : Component
/// The status icon corresponding to the head revolutionary.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public ProtoId<StatusIconPrototype> StatusIcon { get; set; } = "HeadRevolutionaryFaction";
public ProtoId<FactionIconPrototype> StatusIcon { get; set; } = "HeadRevolutionaryFaction";
/// <summary>
/// How long the stun will last after the user is converted.

View File

@@ -16,7 +16,7 @@ public sealed partial class RevolutionaryComponent : Component
/// The status icon prototype displayed for revolutionaries
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public ProtoId<StatusIconPrototype> StatusIcon { get; set; } = "RevolutionaryFaction";
public ProtoId<FactionIconPrototype> StatusIcon { get; set; } = "RevolutionaryFaction";
/// <summary>
/// Sound that plays when you are chosen as Rev. (Placeholder until I find something cool I guess)

View File

@@ -99,7 +99,7 @@ namespace Content.Shared.Roles
public string? JobEntity = null;
[DataField]
public ProtoId<StatusIconPrototype> Icon { get; private set; } = "JobIconUnknown";
public ProtoId<JobIconPrototype> Icon { get; private set; } = "JobIconUnknown";
[DataField("special", serverOnly: true)]
public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>();

View File

@@ -18,5 +18,5 @@ public sealed partial class SSDIndicatorComponent : Component
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public ProtoId<StatusIconPrototype> Icon = "SSDIcon";
public ProtoId<SsdIconPrototype> Icon = "SSDIcon";
}

View File

@@ -11,5 +11,5 @@ public sealed partial class CriminalRecordComponent : Component
/// The icon that should be displayed based on the criminal status of the entity.
/// </summary>
[DataField, AutoNetworkedField]
public ProtoId<StatusIconPrototype> StatusIcon = "SecurityIconWanted";
public ProtoId<SecurityIconPrototype> StatusIcon = "SecurityIconWanted";
}

View File

@@ -73,7 +73,6 @@ public partial class StatusIconData : IComparable<StatusIconData>
/// </summary>
[DataField]
public bool IsShaded = false;
public int CompareTo(StatusIconData? other)
{
return Priority.CompareTo(other?.Priority ?? int.MaxValue);
@@ -83,11 +82,21 @@ public partial class StatusIconData : IComparable<StatusIconData>
/// <summary>
/// <see cref="StatusIconData"/> but in new convenient prototype form!
/// </summary>
[Prototype("statusIcon")]
public sealed partial class StatusIconPrototype : StatusIconData, IPrototype, IInheritingPrototype
public abstract partial class StatusIconPrototype : StatusIconData, IPrototype
{
/// <inheritdoc/>
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<StatusIconPrototype>))]
[IdDataField]
public string ID { get; private set; } = default!;
}
/// <summary>
/// StatusIcons for showing jobs on the sec HUD
/// </summary>
[Prototype]
public sealed partial class JobIconPrototype : StatusIconPrototype, IInheritingPrototype
{
/// <inheritdoc />
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<JobIconPrototype>))]
public string[]? Parents { get; }
/// <inheritdoc />
@@ -95,9 +104,116 @@ public sealed partial class StatusIconPrototype : StatusIconData, IPrototype, II
[AbstractDataField]
public bool Abstract { get; }
/// <summary>
/// Name of the icon used for menu tooltips.
/// </summary>
[DataField]
public string JobName { get; private set; } = string.Empty;
[ViewVariables(VVAccess.ReadOnly)]
public string LocalizedJobName => Loc.GetString(JobName);
/// <summary>
/// Should the agent ID or ID card console be able to use this job icon?
/// </summary>
[DataField]
public bool AllowSelection = true;
}
/// <summary>
/// StatusIcons for the med HUD
/// </summary>
[Prototype]
public sealed partial class HealthIconPrototype : StatusIconPrototype, IInheritingPrototype
{
/// <inheritdoc />
[IdDataField]
public string ID { get; private set; } = default!;
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<HealthIconPrototype>))]
public string[]? Parents { get; }
/// <inheritdoc />
[NeverPushInheritance]
[AbstractDataField]
public bool Abstract { get; }
}
/// <summary>
/// StatusIcons for the beer goggles and fried onion goggles
/// </summary>
[Prototype]
public sealed partial class SatiationIconPrototype : StatusIconPrototype, IInheritingPrototype
{
/// <inheritdoc />
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<SatiationIconPrototype>))]
public string[]? Parents { get; }
/// <inheritdoc />
[NeverPushInheritance]
[AbstractDataField]
public bool Abstract { get; }
}
/// <summary>
/// StatusIcons for showing the wanted status on the sec HUD
/// </summary>
[Prototype]
public sealed partial class SecurityIconPrototype : StatusIconPrototype, IInheritingPrototype
{
/// <inheritdoc />
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<SecurityIconPrototype>))]
public string[]? Parents { get; }
/// <inheritdoc />
[NeverPushInheritance]
[AbstractDataField]
public bool Abstract { get; }
}
/// <summary>
/// StatusIcons for faction membership
/// </summary>
[Prototype]
public sealed partial class FactionIconPrototype : StatusIconPrototype, IInheritingPrototype
{
/// <inheritdoc />
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<FactionIconPrototype>))]
public string[]? Parents { get; }
/// <inheritdoc />
[NeverPushInheritance]
[AbstractDataField]
public bool Abstract { get; }
}
/// <summary>
/// StatusIcons for debugging purposes
/// </summary>
[Prototype]
public sealed partial class DebugIconPrototype : StatusIconPrototype, IInheritingPrototype
{
/// <inheritdoc />
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<DebugIconPrototype>))]
public string[]? Parents { get; }
/// <inheritdoc />
[NeverPushInheritance]
[AbstractDataField]
public bool Abstract { get; }
}
/// <summary>
/// StatusIcons for the SSD indicator
/// </summary>
[Prototype]
public sealed partial class SsdIconPrototype : StatusIconPrototype, IInheritingPrototype
{
/// <inheritdoc />
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<SsdIconPrototype>))]
public string[]? Parents { get; }
/// <inheritdoc />
[NeverPushInheritance]
[AbstractDataField]
public bool Abstract { get; }
}
[Serializable, NetSerializable]

View File

@@ -8,5 +8,5 @@ namespace Content.Shared.Zombies;
public sealed partial class InitialInfectedComponent : Component
{
[DataField]
public ProtoId<StatusIconPrototype> StatusIcon = "InitialInfectedFaction";
public ProtoId<FactionIconPrototype> StatusIcon = "InitialInfectedFaction";
}

View File

@@ -89,7 +89,7 @@ public sealed partial class ZombieComponent : Component
public TimeSpan NextTick;
[DataField("zombieStatusIcon")]
public ProtoId<StatusIconPrototype> StatusIcon { get; set; } = "ZombieFaction";
public ProtoId<FactionIconPrototype> StatusIcon { get; set; } = "ZombieFaction";
/// <summary>
/// Healing each second

View File

@@ -47,6 +47,18 @@ job-name-boxer = Boxer
job-name-zookeeper = Zookeeper
job-name-visitor = Visitor
# unused jobs
# these are required for the agent ID job icon tooltips
# I am keeping them for roleplaying opportunities
job-name-geneticist = Geneticist
job-name-no-id = No ID
job-name-prisoner = Prisoner
job-name-roboticist = Roboticist
job-name-syndicate = Syndicate
job-name-unknown = Unknown
job-name-virologist = Virologist
job-name-zombie = Zombie
# Role timers - Make these alphabetical or I cut you
JobAtmosphericTechnician = Atmospheric Technician
JobBartender = Bartender

View File

@@ -599,54 +599,6 @@
- state: default
- state: idpassenger
- 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
- JobIconMedicalDoctor
- JobIconParamedic
- JobIconChef
- JobIconWarden
- JobIconResearchDirector
- JobIconMime
- JobIconMusician
- JobIconReporter
- JobIconPsychologist
- JobIconMedicalIntern
- JobIconTechnicalAssistant
- JobIconServiceWorker
- JobIconSecurityCadet
- JobIconZookeeper
- JobIconVisitor
- type: ActivatableUI
key: enum.AgentIDCardUiKey.Key
inHandsOnly: true

View File

@@ -1,32 +1,32 @@
- type: statusIcon
- type: healthIcon
id: HealthIcon
abstract: true
priority: 3
locationPreference: Left
isShaded: true
- type: statusIcon
- type: healthIcon
parent: HealthIcon
id: HealthIconFine
icon:
sprite: /Textures/Interface/Misc/health_icons.rsi
state: Fine
- type: statusIcon
- type: healthIcon
id: HealthIconCritical
parent: HealthIcon
icon:
sprite: /Textures/Interface/Misc/health_icons.rsi
state: Critical
- type: statusIcon
- type: healthIcon
id: HealthIconDead
parent: HealthIcon
icon:
sprite: /Textures/Interface/Misc/health_icons.rsi
state: Dead
- type: statusIcon
- type: healthIcon
id: HealthIconRotting
parent: HealthIcon
icon:

View File

@@ -1,26 +1,26 @@
#Hunger
- type: statusIcon
- type: satiationIcon
id: HungerIcon
abstract: true
priority: 5
locationPreference: Right
isShaded: true
- type: statusIcon
- type: satiationIcon
id: HungerIconOverfed
parent: HungerIcon
icon:
sprite: /Textures/Interface/Misc/food_icons.rsi
state: overfed
- type: statusIcon
- type: satiationIcon
id: HungerIconPeckish
parent: HungerIcon
icon:
sprite: /Textures/Interface/Misc/food_icons.rsi
state: peckish
- type: statusIcon
- type: satiationIcon
id: HungerIconStarving
parent: HungerIcon
icon:
@@ -28,28 +28,28 @@
state: starving
#Thirst
- type: statusIcon
- type: satiationIcon
id: ThirstIcon
abstract: true
priority: 5
locationPreference: Left
isShaded: true
- type: statusIcon
- type: satiationIcon
id: ThirstIconOverhydrated
parent: ThirstIcon
icon:
sprite: /Textures/Interface/Misc/food_icons.rsi
state: overhydrated
- type: statusIcon
- type: satiationIcon
id: ThirstIconThirsty
parent: ThirstIcon
icon:
sprite: /Textures/Interface/Misc/food_icons.rsi
state: thirsty
- type: statusIcon
- type: satiationIcon
id: ThirstIconParched
parent: ThirstIcon
icon:

View File

@@ -1,4 +1,4 @@
- type: statusIcon
- type: ssdIcon
id: SSDIcon
icon:
sprite: /Textures/Effects/ssd.rsi

View File

@@ -1,17 +1,17 @@
- type: statusIcon
- type: debugIcon
id: DebugStatus
icon:
sprite: /Textures/Interface/Misc/research_disciplines.rsi
state: civilianservices
- type: statusIcon
- type: debugIcon
id: DebugStatus2
priority: 1
icon:
sprite: /Textures/Interface/Misc/research_disciplines.rsi
state: arsenal
- type: statusIcon
- type: debugIcon
id: DebugStatus3
priority: 5
icon:

View File

@@ -1,4 +1,4 @@
- type: statusIcon
- type: factionIcon
id: ZombieFaction
priority: 11
showTo:
@@ -10,7 +10,7 @@
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Zombie
- type: statusIcon
- type: factionIcon
id: InitialInfectedFaction
priority: 11
showTo:
@@ -21,7 +21,7 @@
sprite: /Textures/Interface/Misc/job_icons.rsi
state: InitialInfected
- type: statusIcon
- type: factionIcon
id: RevolutionaryFaction
isShaded: true
priority: 11
@@ -33,7 +33,7 @@
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Revolutionary
- type: statusIcon
- type: factionIcon
id: HeadRevolutionaryFaction
isShaded: true
priority: 11
@@ -45,17 +45,7 @@
sprite: /Textures/Interface/Misc/job_icons.rsi
state: HeadRevolutionary
- type: statusIcon
id: MindShieldIcon
priority: 2
locationPreference: Right
layer: Mod
isShaded: true
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: MindShield
- type: statusIcon
- type: factionIcon
id: SyndicateFaction
priority: 0
locationPreference: Left

View File

@@ -1,384 +1,446 @@
- type: statusIcon
- type: jobIcon
id: JobIcon
abstract: true
priority: 1
locationPreference: Right
isShaded: true
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconDetective
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Detective
jobName: job-name-detective
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconQuarterMaster
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: QuarterMaster
jobName: job-name-qm
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconBorg
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Borg
jobName: job-name-borg
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconBotanist
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Botanist
jobName: job-name-botanist
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconBoxer
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Boxer
jobName: job-name-boxer
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconAtmosphericTechnician
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: AtmosphericTechnician
jobName: job-name-atmostech
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconNanotrasen
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Nanotrasen
jobName: job-name-centcomoff
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconPrisoner
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Prisoner
jobName: job-name-prisoner
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconJanitor
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Janitor
jobName: job-name-janitor
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconChemist
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Chemist
jobName: job-name-chemist
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconStationEngineer
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: StationEngineer
jobName: job-name-engineer
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconSecurityOfficer
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: SecurityOfficer
jobName: job-name-security
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconNoId
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: NoId
jobName: job-name-no-id
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconChiefMedicalOfficer
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: ChiefMedicalOfficer
jobName: job-name-cmo
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconRoboticist
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Roboticist
jobName: job-name-roboticist
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconChaplain
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Chaplain
jobName: job-name-chaplain
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconLawyer
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Lawyer
jobName: job-name-lawyer
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconUnknown
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Unknown
jobName: job-name-unknown
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconLibrarian
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Librarian
jobName: job-name-librarian
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconCargoTechnician
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: CargoTechnician
jobName: job-name-cargotech
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconScientist
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Scientist
jobName: job-name-scientist
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconResearchAssistant
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: ResearchAssistant
jobName: job-name-research-assistant
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconGeneticist
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Geneticist
jobName: job-name-geneticist
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconClown
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Clown
jobName: job-name-clown
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconCaptain
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Captain
jobName: job-name-captain
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconHeadOfPersonnel
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: HeadOfPersonnel
jobName: job-name-hop
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconVirologist
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Virologist
jobName: job-name-virologist
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconShaftMiner
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: ShaftMiner
jobName: job-name-salvagespec
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconPassenger
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Passenger
jobName: job-name-passenger
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconChiefEngineer
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: ChiefEngineer
jobName: job-name-ce
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconBartender
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Bartender
jobName: job-name-bartender
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconHeadOfSecurity
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: HeadOfSecurity
jobName: job-name-hos
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconBrigmedic
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Brigmedic
jobName: job-name-brigmedic
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconMedicalDoctor
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: MedicalDoctor
jobName: job-name-doctor
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconParamedic
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Paramedic
jobName: job-name-paramedic
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconChef
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Chef
jobName: job-name-chef
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconWarden
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Warden
jobName: job-name-warden
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconResearchDirector
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: ResearchDirector
jobName: job-name-rd
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconMime
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Mime
jobName: job-name-mime
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconMusician
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Musician
jobName: job-name-musician
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconReporter
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Reporter
jobName: job-name-reporter
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconPsychologist
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Psychologist
jobName: job-name-psychologist
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconMedicalIntern
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: MedicalIntern
jobName: job-name-intern
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconTechnicalAssistant
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: TechnicalAssistant
jobName: job-name-technical-assistant
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconServiceWorker
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: ServiceWorker
jobName: job-name-serviceworker
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconSecurityCadet
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: SecurityCadet
jobName: job-name-cadet
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconZombie # This is a perfectly legitimate profession to pursue
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Zombie
jobName: job-name-zombie
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconSyndicate # Just in case you want to make it official which side you are on
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Syndicate
jobName: job-name-syndicate
- type: jobIcon
parent: JobIcon
id: JobIconZookeeper
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Zookeeper
jobName: job-name-zookeeper
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconSeniorPhysician
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: SeniorPhysician
allowSelection: false
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconSeniorOfficer
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: SeniorOfficer
allowSelection: false
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconSeniorEngineer
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: SeniorEngineer
allowSelection: false
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconSeniorResearcher
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: SeniorResearcher
allowSelection: false
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconVisitor
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Visitor
jobName: job-name-visitor
- type: statusIcon
- type: jobIcon
parent: JobIcon
id: JobIconAdmin
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Admin
allowSelection: false

View File

@@ -1,4 +1,4 @@
- type: statusIcon
- type: securityIcon
id: SecurityIcon
abstract: true
priority: 3
@@ -6,37 +6,47 @@
locationPreference: Right
isShaded: true
- type: statusIcon
- type: securityIcon
parent: SecurityIcon
id: SecurityIconDischarged
icon:
sprite: /Textures/Interface/Misc/security_icons.rsi
state: hud_discharged
- type: statusIcon
- type: securityIcon
parent: SecurityIcon
id: SecurityIconIncarcerated
icon:
sprite: /Textures/Interface/Misc/security_icons.rsi
state: hud_incarcerated
- type: statusIcon
- type: securityIcon
parent: SecurityIcon
id: SecurityIconParoled
icon:
sprite: /Textures/Interface/Misc/security_icons.rsi
state: hud_paroled
- type: statusIcon
- type: securityIcon
parent: SecurityIcon
id: SecurityIconSuspected
icon:
sprite: /Textures/Interface/Misc/security_icons.rsi
state: hud_suspected
- type: statusIcon
- type: securityIcon
parent: SecurityIcon
id: SecurityIconWanted
icon:
sprite: /Textures/Interface/Misc/security_icons.rsi
state: hud_wanted
- type: securityIcon
id: MindShieldIcon
priority: 2
locationPreference: Right
layer: Mod
isShaded: true
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: MindShield