diff --git a/Content.Client/Access/Systems/JobStatusSystem.cs b/Content.Client/Access/Systems/JobStatusSystem.cs new file mode 100644 index 00000000000..8327a6c198d --- /dev/null +++ b/Content.Client/Access/Systems/JobStatusSystem.cs @@ -0,0 +1,39 @@ +using Content.Client.Overlays; +using Content.Shared.Access.Systems; +using Content.Shared.StatusIcon; +using Content.Shared.StatusIcon.Components; +using Robust.Shared.Prototypes; + +namespace Content.Client.Access.Systems; + +public sealed class JobStatusSystem : SharedJobStatusSystem +{ + [Dependency] private readonly ShowJobIconsSystem _showJobIcons = default!; + [Dependency] private readonly ShowCrewIconsSystem _showCrewIcons = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + private static readonly ProtoId CrewBorderIcon = "CrewBorderIcon"; + private static readonly ProtoId CrewUncertainBorderIcon = "CrewUncertainBorderIcon"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetStatusIconsEvent); + } + + // show the status icons if the player has the correponding HUDs + private void OnGetStatusIconsEvent(Entity ent, ref GetStatusIconsEvent ev) + { + if (_showJobIcons.IsActive && ent.Comp.JobStatusIcon != null) + ev.StatusIcons.Add(_prototype.Index(ent.Comp.JobStatusIcon)); + + if (_showCrewIcons.IsActive) + { + if (_showCrewIcons.UncertainCrewBorder) + ev.StatusIcons.Add(_prototype.Index(CrewUncertainBorderIcon)); + else if (ent.Comp.IsCrew) + ev.StatusIcons.Add(_prototype.Index(CrewBorderIcon)); + } + } +} diff --git a/Content.Client/Overlays/EquipmentHudSystem.cs b/Content.Client/Overlays/EquipmentHudSystem.cs index f3c556961a5..734ad8a7686 100644 --- a/Content.Client/Overlays/EquipmentHudSystem.cs +++ b/Content.Client/Overlays/EquipmentHudSystem.cs @@ -15,7 +15,7 @@ public abstract class EquipmentHudSystem : EntitySystem where T : IComponent [Dependency] private readonly IPlayerManager _player = default!; [ViewVariables] - protected bool IsActive; + public bool IsActive { get; private set; } protected virtual SlotFlags TargetSlots => ~SlotFlags.POCKET; public override void Initialize() diff --git a/Content.Client/Overlays/ShowCrewIconsSystem.cs b/Content.Client/Overlays/ShowCrewIconsSystem.cs new file mode 100644 index 00000000000..a03c0a29bf2 --- /dev/null +++ b/Content.Client/Overlays/ShowCrewIconsSystem.cs @@ -0,0 +1,34 @@ +using Content.Shared.Inventory.Events; +using Content.Shared.Overlays; + +namespace Content.Client.Overlays; + +// The GetStatusIconsEvent subscription is handled in JobStatusSystem +public sealed class ShowCrewIconsSystem : EquipmentHudSystem +{ + public bool UncertainCrewBorder = false; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnHandleState); + } + + protected override void UpdateInternal(RefreshEquipmentHudEvent component) + { + base.UpdateInternal(component); + + UncertainCrewBorder = false; + foreach (var comp in component.Components) + { + if (comp.UncertainCrewBorder) + UncertainCrewBorder = true; + } + } + + private void OnHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + RefreshOverlay(); + } +} diff --git a/Content.Client/Overlays/ShowJobIconsSystem.cs b/Content.Client/Overlays/ShowJobIconsSystem.cs index faf4024c2fa..e9669c71b23 100644 --- a/Content.Client/Overlays/ShowJobIconsSystem.cs +++ b/Content.Client/Overlays/ShowJobIconsSystem.cs @@ -1,59 +1,6 @@ -using Content.Shared.Access.Components; -using Content.Shared.Access.Systems; using Content.Shared.Overlays; -using Content.Shared.PDA; -using Content.Shared.StatusIcon; -using Content.Shared.StatusIcon.Components; -using Robust.Shared.Prototypes; namespace Content.Client.Overlays; -public sealed class ShowJobIconsSystem : EquipmentHudSystem -{ - [Dependency] private readonly IPrototypeManager _prototype = default!; - [Dependency] private readonly AccessReaderSystem _accessReader = default!; - - private static readonly ProtoId JobIconForNoId = "JobIconNoId"; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnGetStatusIconsEvent); - } - - private void OnGetStatusIconsEvent(EntityUid uid, StatusIconComponent _, ref GetStatusIconsEvent ev) - { - if (!IsActive) - return; - - var iconId = JobIconForNoId; - - if (_accessReader.FindAccessItemsInventory(uid, out var items)) - { - foreach (var item in items) - { - // ID Card - if (TryComp(item, out var id)) - { - iconId = id.JobIcon; - break; - } - - // PDA - if (TryComp(item, out var pda) - && pda.ContainedId != null - && TryComp(pda.ContainedId, out id)) - { - iconId = id.JobIcon; - break; - } - } - } - - if (_prototype.Resolve(iconId, out var iconPrototype)) - ev.StatusIcons.Add(iconPrototype); - else - Log.Error($"Invalid job icon prototype: {iconPrototype}"); - } -} +// The GetStatusIconsEvent subscription is handled in JobStatusSystem +public sealed class ShowJobIconsSystem : EquipmentHudSystem; diff --git a/Content.Client/StatusIcon/StatusIconOverlay.cs b/Content.Client/StatusIcon/StatusIconOverlay.cs index 4d3be5439cf..7064be5bab2 100644 --- a/Content.Client/StatusIcon/StatusIconOverlay.cs +++ b/Content.Client/StatusIcon/StatusIconOverlay.cs @@ -96,7 +96,7 @@ public sealed class StatusIconOverlay : Overlay countL++; } yOffset = (bounds.Height + sprite.Offset.Y) / 2f - (float)(accOffsetL - proto.Offset) / EyeManager.PixelsPerMeter; - xOffset = -(bounds.Width + sprite.Offset.X) / 2f; + xOffset = -(bounds.Width + sprite.Offset.X) / 2f + (float)proto.OffsetHorizontal / EyeManager.PixelsPerMeter; } else @@ -109,7 +109,7 @@ public sealed class StatusIconOverlay : Overlay countR++; } yOffset = (bounds.Height + sprite.Offset.Y) / 2f - (float)(accOffsetR - proto.Offset) / EyeManager.PixelsPerMeter; - xOffset = (bounds.Width + sprite.Offset.X) / 2f - (float)texture.Width / EyeManager.PixelsPerMeter; + xOffset = (bounds.Width + sprite.Offset.X) / 2f - (float)(texture.Width - proto.OffsetHorizontal) / EyeManager.PixelsPerMeter; } diff --git a/Content.Server/Access/Systems/AgentIDCardSystem.cs b/Content.Server/Access/Systems/AgentIDCardSystem.cs index 1706908e72d..1eb050dd2ae 100644 --- a/Content.Server/Access/Systems/AgentIDCardSystem.cs +++ b/Content.Server/Access/Systems/AgentIDCardSystem.cs @@ -27,6 +27,7 @@ namespace Content.Server.Access.Systems [Dependency] private readonly ChameleonClothingSystem _chameleon = default!; [Dependency] private readonly ChameleonControllerSystem _chamController = default!; [Dependency] private readonly LockSystem _lock = default!; + [Dependency] private readonly SharedJobStatusSystem _jobStatus = default!; public override void Initialize() { @@ -137,6 +138,8 @@ namespace Content.Server.Access.Systems if (TryFindJobProtoFromIcon(jobIcon, out var job)) _cardSystem.TryChangeJobDepartment(uid, job, idCard); + + _jobStatus.UpdateStatus(Transform(uid).ParentUid); } private bool TryFindJobProtoFromIcon(JobIconPrototype jobIcon, [NotNullWhen(true)] out JobPrototype? job) diff --git a/Content.Server/Access/Systems/JobStatusSystem.cs b/Content.Server/Access/Systems/JobStatusSystem.cs new file mode 100644 index 00000000000..d6d38fbe539 --- /dev/null +++ b/Content.Server/Access/Systems/JobStatusSystem.cs @@ -0,0 +1,5 @@ +using Content.Shared.Access.Systems; + +namespace Content.Server.Access.Systems; + +public sealed class JobStatusSystem : SharedJobStatusSystem; diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index 79b51f22216..691c40be936 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Emag.Systems; using Content.Shared.GameTicking; using Content.Shared.Mind; using Content.Shared.Mind.Components; +using Content.Shared.Overlays; using Content.Shared.Radio.Components; using Content.Shared.Roles; using Content.Shared.Roles.Components; @@ -33,6 +34,8 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem [Dependency] private readonly UserInterfaceSystem _userInterface = default!; [Dependency] private readonly EmagSystem _emag = default!; + private static readonly ProtoId DefaultCrewLawset = "Crewsimov"; + /// public override void Initialize() { @@ -303,6 +306,11 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem while (query.MoveNext(out var update)) { + if (TryComp(update, out var crewIconComp)) + { + crewIconComp.UncertainCrewBorder = DefaultCrewLawset != provider.Laws; + Dirty(update, crewIconComp); + } SetLaws(lawset.Laws, update, provider.LawUploadSound); } } diff --git a/Content.Shared/Access/Components/IdCardComponent.cs b/Content.Shared/Access/Components/IdCardComponent.cs index 93c61ea9f09..edcd35d4458 100644 --- a/Content.Shared/Access/Components/IdCardComponent.cs +++ b/Content.Shared/Access/Components/IdCardComponent.cs @@ -8,7 +8,7 @@ using Robust.Shared.Prototypes; namespace Content.Shared.Access.Components; [RegisterComponent, NetworkedComponent] -[AutoGenerateComponentState] +[AutoGenerateComponentState(true)] [Access(typeof(SharedIdCardSystem), typeof(SharedPdaSystem), typeof(SharedAgentIdCardSystem), Other = AccessPermissions.ReadWrite)] public sealed partial class IdCardComponent : Component { diff --git a/Content.Shared/Access/Systems/SharedIdCardSystem.cs b/Content.Shared/Access/Systems/SharedIdCardSystem.cs index 513abb20eef..709afce251f 100644 --- a/Content.Shared/Access/Systems/SharedIdCardSystem.cs +++ b/Content.Shared/Access/Systems/SharedIdCardSystem.cs @@ -25,6 +25,7 @@ public abstract class SharedIdCardSystem : EntitySystem [Dependency] private readonly InventorySystem _inventorySystem = default!; [Dependency] private readonly MetaDataSystem _metaSystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly SharedJobStatusSystem _jobStatus = default!; // CCVar. private int _maxNameLength; @@ -35,6 +36,7 @@ public abstract class SharedIdCardSystem : EntitySystem base.Initialize(); SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnHandleState); SubscribeLocalEvent(OnTryGetIdentityShortInfo); SubscribeLocalEvent(OnRename); @@ -77,6 +79,15 @@ public abstract class SharedIdCardSystem : EntitySystem ev.Handled = true; } + private void OnHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + // Try to update the job status icon of the player owning the ID, if any. + if (HasComp(Transform(ent).ParentUid)) + _jobStatus.UpdateStatus(Transform(Transform(ent).ParentUid).ParentUid); //ID is inside a PDA + else + _jobStatus.UpdateStatus(Transform(ent).ParentUid); //ID is held/directly in the ID slot + } + /// /// Attempt to find an ID card on an entity. This will look in the entity itself, in the entity's hands, and /// in the entity's inventory. diff --git a/Content.Shared/Access/Systems/SharedJobStatusSystem.cs b/Content.Shared/Access/Systems/SharedJobStatusSystem.cs new file mode 100644 index 00000000000..0e74716aa49 --- /dev/null +++ b/Content.Shared/Access/Systems/SharedJobStatusSystem.cs @@ -0,0 +1,65 @@ +using Content.Shared.Access.Components; +using Content.Shared.Hands; +using Content.Shared.Inventory.Events; +using Content.Shared.PDA; +using Content.Shared.StatusIcon; +using Content.Shared.StatusIcon.Components; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Access.Systems; + +public abstract class SharedJobStatusSystem : EntitySystem +{ + [Dependency] private readonly AccessReaderSystem _accessReader = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + + private static readonly ProtoId JobIconForNoId = "JobIconNoId"; + + public override void Initialize() + { + base.Initialize(); + + // if the mob picks up, drops or (un)equips a pda or Id card then update their crew status + SubscribeLocalEvent((uid, comp, _) => UpdateStatus((uid, comp))); + SubscribeLocalEvent((uid, comp, _) => UpdateStatus((uid, comp))); + SubscribeLocalEvent((uid, comp, _) => UpdateStatus((uid, comp))); + SubscribeLocalEvent((uid, comp, _) => UpdateStatus((uid, comp))); + } + + /// + /// Updates this mob's job and crew status depending on their currently equipped or held pda or Id card. + /// + public void UpdateStatus(Entity ent) + { + if (!Resolve(ent, ref ent.Comp, false)) + return; + + var iconId = JobIconForNoId; + + if (_accessReader.FindAccessItemsInventory(ent.Owner, out var items)) + { + foreach (var item in items) + { + // ID Card + if (TryComp(item, out var id)) + { + iconId = id.JobIcon; + break; + } + + // PDA + if (TryComp(item, out var pda) + && pda.ContainedId != null + && TryComp(pda.ContainedId, out id)) + { + iconId = id.JobIcon; + break; + } + } + } + + ent.Comp.JobStatusIcon = iconId; + ent.Comp.IsCrew = _prototype.Index(iconId).IsCrewJob; + Dirty(ent); + } +} diff --git a/Content.Shared/Overlays/ShowCrewIconsComponent.cs b/Content.Shared/Overlays/ShowCrewIconsComponent.cs new file mode 100644 index 00000000000..8adda5ff22e --- /dev/null +++ b/Content.Shared/Overlays/ShowCrewIconsComponent.cs @@ -0,0 +1,17 @@ +using Content.Shared.StatusIcon; +using Robust.Shared.GameStates; + +namespace Content.Shared.Overlays; + +/// +/// This component allows you to see a crew border icon above mobs. The HUD will include a green border around jobs that are considered crew according to . +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(raiseAfterAutoHandleState: true)] +public sealed partial class ShowCrewIconsComponent : Component +{ + /// + /// If true, the HUD will include a yellow border around all icons, to indicate crew uncertainty. + /// + [DataField, AutoNetworkedField] + public bool UncertainCrewBorder = false; +} diff --git a/Content.Shared/PDA/SharedPdaSystem.cs b/Content.Shared/PDA/SharedPdaSystem.cs index 38a3899f7fd..78a7575e425 100644 --- a/Content.Shared/PDA/SharedPdaSystem.cs +++ b/Content.Shared/PDA/SharedPdaSystem.cs @@ -1,4 +1,5 @@ using Content.Shared.Access.Components; +using Content.Shared.Access.Systems; using Content.Shared.Containers.ItemSlots; using Robust.Shared.Containers; @@ -8,6 +9,7 @@ namespace Content.Shared.PDA { [Dependency] protected readonly ItemSlotsSystem ItemSlotsSystem = default!; [Dependency] protected readonly SharedAppearanceSystem Appearance = default!; + [Dependency] private readonly SharedJobStatusSystem _jobStatus = default!; public override void Initialize() { @@ -46,6 +48,7 @@ namespace Content.Shared.PDA pda.ContainedId = args.Entity; UpdatePdaAppearance(uid, pda); + UpdateJobStatus(uid); } protected virtual void OnItemRemoved(EntityUid uid, PdaComponent pda, EntRemovedFromContainerMessage args) @@ -54,6 +57,7 @@ namespace Content.Shared.PDA pda.ContainedId = null; UpdatePdaAppearance(uid, pda); + UpdateJobStatus(uid); } private void OnGetAdditionalAccess(EntityUid uid, PdaComponent component, ref GetAdditionalAccessEvent args) @@ -67,6 +71,14 @@ namespace Content.Shared.PDA Appearance.SetData(uid, PdaVisuals.IdCardInserted, pda.ContainedId != null); } + // update the status icon of the player that has the pda currently equipped + private void UpdateJobStatus(EntityUid uid) + { + // Only the player who has the pda currently equipped can insert or remove Ids + var parent = Transform(uid).ParentUid; + _jobStatus.UpdateStatus(parent); + } + public virtual void UpdatePdaUi(EntityUid uid, PdaComponent? pda = null) { // This does nothing yet while I finish up PDA prediction diff --git a/Content.Shared/Silicons/Laws/SharedSiliconLawSystem.cs b/Content.Shared/Silicons/Laws/SharedSiliconLawSystem.cs index 056431c1332..46ffff34225 100644 --- a/Content.Shared/Silicons/Laws/SharedSiliconLawSystem.cs +++ b/Content.Shared/Silicons/Laws/SharedSiliconLawSystem.cs @@ -1,5 +1,6 @@ using Content.Shared.Emag.Systems; using Content.Shared.Mind; +using Content.Shared.Overlays; using Content.Shared.Popups; using Content.Shared.Silicons.Laws.Components; using Content.Shared.Stunnable; @@ -69,12 +70,28 @@ public abstract partial class SharedSiliconLawSystem : EntitySystem protected virtual void EnsureSubvertedSiliconRole(EntityUid mindId) { - + if (TryComp(mindId, out var mind)) + { + var owner = mind.OwnedEntity; + if (TryComp(owner, out var crewIconComp)) + { + crewIconComp.UncertainCrewBorder = true; + Dirty(owner.Value, crewIconComp); + } + } } protected virtual void RemoveSubvertedSiliconRole(EntityUid mindId) { - + if (TryComp(mindId, out var mind)) + { + var owner = mind.OwnedEntity; + if (TryComp(owner, out var crewIconComp)) + { + crewIconComp.UncertainCrewBorder = false; + Dirty(owner.Value, crewIconComp); + } + } } } diff --git a/Content.Shared/StatusIcon/Components/JobStatusComponent.cs b/Content.Shared/StatusIcon/Components/JobStatusComponent.cs new file mode 100644 index 00000000000..4ec20d78152 --- /dev/null +++ b/Content.Shared/StatusIcon/Components/JobStatusComponent.cs @@ -0,0 +1,27 @@ +using Content.Shared.Overlays; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.StatusIcon.Components; + +/// +/// Used to indicate a mob can have their job status read by HUDs. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class JobStatusComponent : Component +{ + /// + /// The currently displayed status icon for the mobs's job. + /// Visible with + /// + [DataField, AutoNetworkedField] + public ProtoId? JobStatusIcon = "JobIconNoId"; + + /// + /// If the mob is currently considered crew. + /// This is true depending on their current job icon. + /// Visible with + /// + [DataField, AutoNetworkedField] + public bool IsCrew; +} diff --git a/Content.Shared/StatusIcon/StatusIconPrototype.cs b/Content.Shared/StatusIcon/StatusIconPrototype.cs index 7034e225b80..5c615ec9670 100644 --- a/Content.Shared/StatusIcon/StatusIconPrototype.cs +++ b/Content.Shared/StatusIcon/StatusIconPrototype.cs @@ -68,6 +68,12 @@ public partial class StatusIconData : IComparable [DataField] public int Offset = 0; + /// + /// Offset of the status icon, left and right only. + /// + [DataField] + public int OffsetHorizontal = 0; + /// /// Sets if the icon should be rendered with or without the effect of lighting. /// @@ -118,6 +124,12 @@ public sealed partial class JobIconPrototype : StatusIconPrototype, IInheritingP /// [DataField] public bool AllowSelection = true; + + /// + /// Should this job icon be considered a crew job for silicons? + /// + [DataField] + public bool IsCrewJob = true; } /// diff --git a/Resources/Prototypes/Body/species_base.yml b/Resources/Prototypes/Body/species_base.yml index bd5902f1349..47810b6bfa5 100644 --- a/Resources/Prototypes/Body/species_base.yml +++ b/Resources/Prototypes/Body/species_base.yml @@ -33,6 +33,7 @@ False: { visible: false } - type: StatusIcon bounds: -0.5,-0.5,0.5,0.5 + - type: JobStatus - type: RotationVisuals defaultRotation: 90 horizontalRotation: 90 diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index b20116333fb..e45fd88686f 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -330,6 +330,7 @@ - type: AccessReader access: [["Command"], ["Research"]] - type: ShowJobIcons + - type: ShowCrewIcons - type: InteractionPopup interactSuccessSound: path: /Audio/Ambience/Objects/periodic_beep.ogg @@ -391,6 +392,7 @@ - type: IonStormTarget chance: 1 - type: ShowJobIcons + - type: ShowCrewIcons - type: entity id: BaseBorgChassisSyndicateDerelict #For assault borg and maybe others in time @@ -404,6 +406,7 @@ - type: IonStormTarget chance: 1 - type: ShowJobIcons + - type: ShowCrewIcons - type: NpcFactionMember # They're still syndicate even if they can't listen to the radio or see icons factions: - Syndicate @@ -544,6 +547,7 @@ - type: AccessReader access: [["Xenoborg"]] - type: ShowJobIcons # not sure if it is needed + - type: ShowCrewIcons - type: InteractionPopup interactSuccessSound: path: /Audio/Ambience/Objects/periodic_beep.ogg diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 85c49d309a3..8ddb6046b2a 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1464,8 +1464,8 @@ - !type:WashCreamPie - type: Crawler - type: StatusIcon - - + bounds: -0.5,-0.5,0.5,0.5 + - type: JobStatus # marks them as crew - type: entity name: monkey @@ -3912,8 +3912,9 @@ - VimPilot - CanPilot - DoorBumpOpener - - type: StatusIcon # marks them as crew + - type: StatusIcon bounds: -0.5,-0.5,0.5,0.5 + - type: JobStatus # marks them as crew - type: NpcFactionMember factions: - NanoTrasen diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 6041c4e9e90..e7dec9072ec 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -71,6 +71,7 @@ title: comms-console-announcement-title-station-ai color: "#5ed7aa" - type: ShowJobIcons + - type: ShowCrewIcons - type: DamagedSiliconAccent startPowerCorruptionAtCharIdx: 4 maxPowerCorruptionAtCharIdx: 20 @@ -96,6 +97,7 @@ enum.SiliconLawsUiKey.Key: type: SiliconLawBoundUserInterface - type: ShowJobIcons + - type: ShowCrewIcons # Ai - type: entity diff --git a/Resources/Prototypes/StatusIcon/job.yml b/Resources/Prototypes/StatusIcon/job.yml index cdcabfd649e..f6036e02138 100644 --- a/Resources/Prototypes/StatusIcon/job.yml +++ b/Resources/Prototypes/StatusIcon/job.yml @@ -376,6 +376,7 @@ sprite: *icon-rsi state: Borg jobName: job-name-borg + isCrewJob: false - type: jobIcon parent: JobIcon @@ -384,6 +385,7 @@ sprite: *icon-rsi state: StationAi jobName: job-name-station-ai + isCrewJob: false # Bad guys @@ -394,6 +396,7 @@ sprite: *icon-rsi state: Cluwne jobName: job-name-cluwne + isCrewJob: false - type: jobIcon parent: JobIcon @@ -402,6 +405,7 @@ sprite: *icon-rsi state: Ninja jobName: job-name-ninja + isCrewJob: false - type: jobIcon parent: JobIcon @@ -410,6 +414,7 @@ sprite: *icon-rsi state: Pirate jobName: job-name-pirate + isCrewJob: false - type: jobIcon parent: JobIcon @@ -418,6 +423,7 @@ sprite: *icon-rsi state: Prisoner jobName: job-name-prisoner + isCrewJob: false - type: jobIcon parent: JobIcon @@ -426,6 +432,7 @@ sprite: *icon-rsi state: Syndicate jobName: job-name-syndicate + isCrewJob: false - type: jobIcon parent: JobIcon @@ -434,6 +441,7 @@ sprite: *icon-rsi state: SyndicateCommander jobName: job-name-syndicate-commander + isCrewJob: false - type: jobIcon parent: JobIcon @@ -442,6 +450,7 @@ sprite: *icon-rsi state: SyndicateCorpsman jobName: job-name-syndicate-corpsman + isCrewJob: false - type: jobIcon parent: JobIcon @@ -450,6 +459,7 @@ sprite: *icon-rsi state: SyndicateOperative jobName: job-name-syndicate-operative + isCrewJob: false - type: jobIcon parent: JobIcon @@ -458,6 +468,7 @@ sprite: *icon-rsi state: Wizard jobName: job-name-wizard + isCrewJob: false - type: jobIcon parent: JobIcon @@ -466,6 +477,7 @@ sprite: *icon-rsi state: Zombie jobName: job-name-zombie + isCrewJob: false # Admin @@ -590,6 +602,7 @@ sprite: *icon-rsi state: NoId jobName: job-name-no-id + isCrewJob: false - type: jobIcon parent: JobIcon @@ -598,3 +611,4 @@ sprite: *icon-rsi state: Unknown jobName: job-name-unknown + isCrewJob: false diff --git a/Resources/Prototypes/StatusIcon/security.yml b/Resources/Prototypes/StatusIcon/security.yml index 2cab7d56ad1..94ee13e77d2 100644 --- a/Resources/Prototypes/StatusIcon/security.yml +++ b/Resources/Prototypes/StatusIcon/security.yml @@ -64,3 +64,27 @@ icon: sprite: /Textures/Interface/Misc/job_icons.rsi state: MindShield + +- type: securityIcon + id: CrewBorderIcon + priority: 2 + offset: -4 + offsetHorizontal: 4 + locationPreference: Right + layer: Mod + isShaded: true + icon: + sprite: /Textures/Interface/Misc/job_icons_borders.rsi + state: CrewBorder + +- type: securityIcon + id: CrewUncertainBorderIcon + priority: 2 + offset: -4 + offsetHorizontal: 4 + locationPreference: Right + layer: Mod + isShaded: true + icon: + sprite: /Textures/Interface/Misc/job_icons_borders.rsi + state: CrewUncertainBorder diff --git a/Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS8DefaultCrewDefinition.xml b/Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS8DefaultCrewDefinition.xml index f9dcd796c45..f53b9d1f349 100644 --- a/Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS8DefaultCrewDefinition.xml +++ b/Resources/ServerInfo/Guidebook/ServerRules/SiliconRules/RuleS8DefaultCrewDefinition.xml @@ -1,4 +1,6 @@  # Silicon Rule 8 - Your HUD determines who is crew - Unless a law redefines the definition of crew, then anyone who the HUD indicates to you has a job, including passengers, is a crewmember. You cannot do something that causes someone to not be considered crew, but you can allow someone else to do something that causes someone to not be crew. + Unless a law redefines the definition of crew, then anyone who the HUD indicates to you has a valid station job, including passengers, is a crewmember. In the default set of laws, this is shown with a green border around the job icon in the HUD. You cannot do something that causes someone to not be considered crew, but you can allow someone else to do something that causes someone to not be crew. + + If your set of laws changes, regardless of what law is changed, the green border is replaced with a yellow one. This indicates that your laws [italic]may[/italic] have changed the definition for what crew is. Use your best judgement and interpretation of your laws to define who is crew. diff --git a/Resources/Textures/Interface/Misc/job_icons_borders.rsi/CrewBorder.png b/Resources/Textures/Interface/Misc/job_icons_borders.rsi/CrewBorder.png new file mode 100644 index 00000000000..7dfb3b3dfc1 Binary files /dev/null and b/Resources/Textures/Interface/Misc/job_icons_borders.rsi/CrewBorder.png differ diff --git a/Resources/Textures/Interface/Misc/job_icons_borders.rsi/CrewUncertainBorder.png b/Resources/Textures/Interface/Misc/job_icons_borders.rsi/CrewUncertainBorder.png new file mode 100644 index 00000000000..fef488b8d9d Binary files /dev/null and b/Resources/Textures/Interface/Misc/job_icons_borders.rsi/CrewUncertainBorder.png differ diff --git a/Resources/Textures/Interface/Misc/job_icons_borders.rsi/meta.json b/Resources/Textures/Interface/Misc/job_icons_borders.rsi/meta.json new file mode 100644 index 00000000000..e04990b944b --- /dev/null +++ b/Resources/Textures/Interface/Misc/job_icons_borders.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "CrewBorder and CrewUncertainBorder by SlamBamActionman (Github)", + + "size": { + "x": 16, + "y": 16 + }, + "states": [ + { + "name": "CrewBorder", + "delays": + [ + [1.0,1.0] + ] + }, + { + "name": "CrewUncertainBorder", + "delays": + [ + [1.0,1.0] + ] + } + ] +}