using Content.Shared.Access.Systems;
+using Content.Shared.StatusIcon;
using Robust.Client.GameObjects;
+using Robust.Shared.Prototypes;
namespace Content.Client.Access.UI
{
SendMessage(new AgentIDCardJobChangedMessage(newJob));
}
- public void OnJobIconChanged(string newJobIconId)
+ public void OnJobIconChanged(ProtoId<StatusIconPrototype> newJobIconId)
{
SendMessage(new AgentIDCardJobIconChangedMessage(newJobIconId));
}
JobLineEdit.OnFocusExit += e => OnJobChanged?.Invoke(e.Text);
}
- public void SetAllowedIcons(HashSet<string> icons, string currentJobIconId)
+ public void SetAllowedIcons(HashSet<ProtoId<StatusIconPrototype>> icons, string currentJobIconId)
{
IconGrid.DisposeAllChildren();
var i = 0;
foreach (var jobIconId in icons)
{
- if (!_prototypeManager.TryIndex<StatusIconPrototype>(jobIconId, out var jobIcon))
- {
+ if (!_prototypeManager.TryIndex(jobIconId, out var jobIcon))
continue;
- }
String styleBase = StyleBase.ButtonOpenBoth;
var modulo = i % JobIconColumnCount;
};
jobIconButton.AddChild(jobIconTexture);
- jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIcon.ID);
+ jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIconId);
IconGrid.AddChild(jobIconButton);
if (jobIconId.Equals(currentJobIconId))
+++ /dev/null
-using Content.Shared.Antag;
-using Content.Shared.Revolutionary.Components;
-using Content.Shared.StatusIcon;
-using Content.Shared.StatusIcon.Components;
-using Content.Shared.Zombies;
-using Robust.Client.Player;
-using Robust.Shared.Prototypes;
-
-namespace Content.Client.Antag;
-
-/// <summary>
-/// Used for assigning specified icons for antags.
-/// </summary>
-public sealed class AntagStatusIconSystem : SharedStatusIconSystem
-{
- [Dependency] private readonly IPrototypeManager _prototype = default!;
- [Dependency] private readonly IPlayerManager _player = default!;
- public override void Initialize()
- {
- base.Initialize();
-
- SubscribeLocalEvent<RevolutionaryComponent, GetStatusIconsEvent>(GetRevIcon);
- SubscribeLocalEvent<ZombieComponent, GetStatusIconsEvent>(GetIcon);
- SubscribeLocalEvent<HeadRevolutionaryComponent, GetStatusIconsEvent>(GetIcon);
- SubscribeLocalEvent<InitialInfectedComponent, GetStatusIconsEvent>(GetIcon);
- }
-
- /// <summary>
- /// Adds a Status Icon on an entity if the player is supposed to see it.
- /// </summary>
- private void GetIcon<T>(EntityUid uid, T comp, ref GetStatusIconsEvent ev) where T: IAntagStatusIconComponent
- {
- var ent = _player.LocalSession?.AttachedEntity;
-
- var canEv = new CanDisplayStatusIconsEvent(ent);
- RaiseLocalEvent(uid, ref canEv);
-
- if (!canEv.Cancelled)
- ev.StatusIcons.Add(_prototype.Index(comp.StatusIcon));
- }
-
-
- /// <summary>
- /// Adds the Rev Icon on an entity if the player is supposed to see it. This additional function is needed to deal
- /// with a special case where if someone is a head rev we only want to display the headrev icon.
- /// </summary>
- private void GetRevIcon(EntityUid uid, RevolutionaryComponent comp, ref GetStatusIconsEvent ev)
- {
- if (HasComp<HeadRevolutionaryComponent>(uid))
- return;
-
- GetIcon(uid, comp, ref ev);
-
- }
-}
var showHealthBarsComponent = new ShowHealthBarsComponent
{
DamageContainers = args.ToList(),
+ HealthStatusIcon = "",
NetSyncEnabled = false
};
VerticalAlignment = VAlignment.Center
};
- var jobIcon = _prototypeManager.Index<StatusIconPrototype>(prototype.Icon);
+ var jobIcon = _prototypeManager.Index(prototype.Icon);
icon.Texture = _sprites.Frame0(jobIcon.Icon);
jobSelector.AddChild(icon);
TextureScale = new Vector2(2, 2),
VerticalAlignment = VAlignment.Center
};
- var jobIcon = _prototypeManager.Index<StatusIconPrototype>(job.Icon);
+ var jobIcon = _prototypeManager.Index(job.Icon);
icon.Texture = jobIcon.Icon.Frame0();
selector.Setup(items, job.LocalizedName, 200, job.LocalizedDescription, icon);
using System.Numerics;
+using Content.Client.StatusIcon;
using Content.Client.UserInterface.Systems;
using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
+using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
+using Robust.Shared.Prototypes;
using static Robust.Shared.Maths.Color;
namespace Content.Client.Overlays;
public sealed class EntityHealthBarOverlay : Overlay
{
private readonly IEntityManager _entManager;
+ private readonly IPrototypeManager _prototype;
+
private readonly SharedTransformSystem _transform;
private readonly MobStateSystem _mobStateSystem;
private readonly MobThresholdSystem _mobThresholdSystem;
+ private readonly StatusIconSystem _statusIconSystem;
private readonly ProgressColorSystem _progressColor;
+
+
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
public HashSet<string> DamageContainers = new();
+ public ProtoId<StatusIconPrototype> StatusIcon;
- public EntityHealthBarOverlay(IEntityManager entManager)
+ public EntityHealthBarOverlay(IEntityManager entManager, IPrototypeManager prototype)
{
_entManager = entManager;
+ _prototype = prototype;
_transform = _entManager.System<SharedTransformSystem>();
_mobStateSystem = _entManager.System<MobStateSystem>();
_mobThresholdSystem = _entManager.System<MobThresholdSystem>();
+ _statusIconSystem = _entManager.System<StatusIconSystem>();
_progressColor = _entManager.System<ProgressColorSystem>();
}
const float scale = 1f;
var scaleMatrix = Matrix3Helpers.CreateScale(new Vector2(scale, scale));
var rotationMatrix = Matrix3Helpers.CreateRotation(-rotation);
+ _prototype.TryIndex(StatusIcon, out var statusIcon);
var query = _entManager.AllEntityQueryEnumerator<MobThresholdsComponent, MobStateComponent, DamageableComponent, SpriteComponent>();
while (query.MoveNext(out var uid,
out var damageableComponent,
out var spriteComponent))
{
- if (_entManager.TryGetComponent<MetaDataComponent>(uid, out var metaDataComponent) &&
- metaDataComponent.Flags.HasFlag(MetaDataFlags.InContainer))
- {
+ if (statusIcon != null && !_statusIconSystem.IsVisible((uid, _entManager.GetComponent<MetaDataComponent>(uid)), statusIcon))
continue;
- }
+ // We want the stealth user to still be able to see his health bar himself
if (!xformQuery.TryGetComponent(uid, out var xform) ||
xform.MapID != args.MapId)
- {
continue;
- }
if (damageableComponent.DamageContainerID == null || !DamageContainers.Contains(damageableComponent.DamageContainerID))
- {
continue;
- }
// we use the status icon component bounds if specified otherwise use sprite
var bounds = _entManager.GetComponentOrNull<StatusIconComponent>(uid)?.Bounds ?? spriteComponent.Bounds;
var worldPos = _transform.GetWorldPosition(xform, xformQuery);
if (!bounds.Translated(worldPos).Intersects(args.WorldAABB))
- {
continue;
- }
// we are all progressing towards death every day
if (CalcProgress(uid, mobStateComponent, damageableComponent, mobThresholdsComponent) is not { } deathProgress)
private void OnGetStatusIconsEvent(EntityUid uid, CriminalRecordComponent component, ref GetStatusIconsEvent ev)
{
- if (!IsActive || ev.InContainer)
+ if (!IsActive)
return;
- if (_prototype.TryIndex<StatusIconPrototype>(component.StatusIcon.Id, out var iconPrototype))
+ if (_prototype.TryIndex(component.StatusIcon, out var iconPrototype))
ev.StatusIcons.Add(iconPrototype);
}
}
using Content.Shared.Overlays;
using Robust.Client.Graphics;
using System.Linq;
+using Robust.Client.Player;
+using Robust.Shared.Prototypes;
namespace Content.Client.Overlays;
public sealed class ShowHealthBarsSystem : EquipmentHudSystem<ShowHealthBarsComponent>
{
[Dependency] private readonly IOverlayManager _overlayMan = default!;
+ [Dependency] private readonly IPrototypeManager _prototype = default!;
private EntityHealthBarOverlay _overlay = default!;
{
base.Initialize();
- _overlay = new(EntityManager);
+ _overlay = new(EntityManager, _prototype);
}
protected override void UpdateInternal(RefreshEquipmentHudEvent<ShowHealthBarsComponent> component)
{
base.UpdateInternal(component);
- foreach (var damageContainerId in component.Components.SelectMany(x => x.DamageContainers))
+ foreach (var comp in component.Components)
{
- _overlay.DamageContainers.Add(damageContainerId);
+ foreach (var damageContainerId in comp.DamageContainers)
+ {
+ _overlay.DamageContainers.Add(damageContainerId);
+ }
+
+ _overlay.StatusIcon = comp.HealthStatusIcon;
}
if (!_overlayMan.HasOverlay<EntityHealthBarOverlay>())
base.Initialize();
SubscribeLocalEvent<DamageableComponent, GetStatusIconsEvent>(OnGetStatusIconsEvent);
-
}
protected override void UpdateInternal(RefreshEquipmentHudEvent<ShowHealthIconsComponent> component)
private void OnGetStatusIconsEvent(Entity<DamageableComponent> entity, ref GetStatusIconsEvent args)
{
- if (!IsActive || args.InContainer)
+ if (!IsActive)
return;
var healthIcons = DecideHealthIcons(entity);
private void OnGetStatusIconsEvent(EntityUid uid, HungerComponent component, ref GetStatusIconsEvent ev)
{
- if (!IsActive || ev.InContainer)
+ if (!IsActive)
return;
if (_hunger.TryGetStatusIconPrototype(component, out var iconPrototype))
private void OnGetStatusIconsEvent(EntityUid uid, StatusIconComponent _, ref GetStatusIconsEvent ev)
{
- if (!IsActive || ev.InContainer)
+ if (!IsActive)
return;
var iconId = JobIconForNoId;
private void OnGetStatusIconsEvent(EntityUid uid, MindShieldComponent component, ref GetStatusIconsEvent ev)
{
- if (!IsActive || ev.InContainer)
+ if (!IsActive)
return;
- if (_prototype.TryIndex<StatusIconPrototype>(component.MindShieldStatusIcon.Id, out var iconPrototype))
+ if (_prototype.TryIndex(component.MindShieldStatusIcon, out var iconPrototype))
ev.StatusIcons.Add(iconPrototype);
}
}
private void OnGetStatusIconsEvent(EntityUid uid, NukeOperativeComponent component, ref GetStatusIconsEvent ev)
{
- if (!IsActive || ev.InContainer)
+ if (!IsActive)
return;
if (_prototype.TryIndex<StatusIconPrototype>(component.SyndStatusIcon, out var iconPrototype))
ev.StatusIcons.Add(iconPrototype);
}
}
-
private void OnGetStatusIconsEvent(EntityUid uid, ThirstComponent component, ref GetStatusIconsEvent ev)
{
- if (!IsActive || ev.InContainer)
+ if (!IsActive)
return;
if (_thirst.TryGetStatusIconPrototype(component, out var iconPrototype))
-using Content.Shared.Antag;
using Content.Shared.Revolutionary.Components;
-using Content.Shared.Ghost;
+using Content.Shared.Revolutionary;
using Content.Shared.StatusIcon.Components;
+using Robust.Shared.Prototypes;
namespace Content.Client.Revolutionary;
/// <summary>
/// Used for the client to get status icons from other revs.
/// </summary>
-public sealed class RevolutionarySystem : EntitySystem
+public sealed class RevolutionarySystem : SharedRevolutionarySystem
{
+ [Dependency] private readonly IPrototypeManager _prototype = default!;
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent<RevolutionaryComponent, CanDisplayStatusIconsEvent>(OnCanShowRevIcon);
- SubscribeLocalEvent<HeadRevolutionaryComponent, CanDisplayStatusIconsEvent>(OnCanShowRevIcon);
+ SubscribeLocalEvent<RevolutionaryComponent, GetStatusIconsEvent>(GetRevIcon);
+ SubscribeLocalEvent<HeadRevolutionaryComponent, GetStatusIconsEvent>(GetHeadRevIcon);
}
- /// <summary>
- /// Determine whether a client should display the rev icon.
- /// </summary>
- private void OnCanShowRevIcon<T>(EntityUid uid, T comp, ref CanDisplayStatusIconsEvent args) where T : IAntagStatusIconComponent
+ private void GetRevIcon(Entity<RevolutionaryComponent> ent, ref GetStatusIconsEvent args)
{
- args.Cancelled = !CanDisplayIcon(args.User, comp.IconVisibleToGhost);
+ if (HasComp<HeadRevolutionaryComponent>(ent))
+ return;
+
+ if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype))
+ args.StatusIcons.Add(iconPrototype);
}
- /// <summary>
- /// The criteria that determine whether a client should see Rev/Head rev icons.
- /// </summary>
- private bool CanDisplayIcon(EntityUid? uid, bool visibleToGhost)
+ private void GetHeadRevIcon(Entity<HeadRevolutionaryComponent> ent, ref GetStatusIconsEvent args)
{
- if (HasComp<HeadRevolutionaryComponent>(uid) || HasComp<RevolutionaryComponent>(uid))
- return true;
-
- if (visibleToGhost && HasComp<GhostComponent>(uid))
- return true;
-
- return HasComp<ShowRevIconsComponent>(uid);
+ if (_prototype.TryIndex(ent.Comp.StatusIcon, out var iconPrototype))
+ args.StatusIcons.Add(iconPrototype);
}
-
}
{
if (component.IsSSD &&
_cfg.GetCVar(CCVars.ICShowSSDIndicator) &&
- !args.InContainer &&
!_mobState.IsDead(uid) &&
!HasComp<ActiveNPCComponent>(uid) &&
TryComp<MindContainerComponent>(uid, out var mindContainer) &&
mindContainer.ShowExamineInfo)
{
- args.StatusIcons.Add(_prototype.Index<StatusIconPrototype>(component.Icon));
+ args.StatusIcons.Add(_prototype.Index(component.Icon));
}
}
}
var query = _entity.AllEntityQueryEnumerator<StatusIconComponent, SpriteComponent, TransformComponent, MetaDataComponent>();
while (query.MoveNext(out var uid, out var comp, out var sprite, out var xform, out var meta))
{
- if (xform.MapID != args.MapId)
+ if (xform.MapID != args.MapId || !sprite.Visible)
continue;
var bounds = comp.Bounds ?? sprite.Bounds;
foreach (var proto in icons)
{
+ if (!_statusIcon.IsVisible((uid, meta), proto))
+ continue;
var curTime = _timing.RealTime;
var texture = _sprite.GetFrame(proto.Icon, curTime);
using Content.Shared.CCVar;
+using Content.Shared.Ghost;
using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
+using Content.Shared.Stealth.Components;
+using Content.Shared.Whitelist;
using Robust.Client.Graphics;
+using Robust.Client.Player;
using Robust.Shared.Configuration;
namespace Content.Client.StatusIcon;
{
[Dependency] private readonly IConfigurationManager _configuration = default!;
[Dependency] private readonly IOverlayManager _overlay = default!;
+ [Dependency] private readonly IPlayerManager _playerManager = default!;
+ [Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
private bool _globalEnabled;
private bool _localEnabled;
if (meta.EntityLifeStage >= EntityLifeStage.Terminating)
return list;
- var inContainer = (meta.Flags & MetaDataFlags.InContainer) != 0;
- var ev = new GetStatusIconsEvent(list, inContainer);
+ var ev = new GetStatusIconsEvent(list);
RaiseLocalEvent(uid, ref ev);
return ev.StatusIcons;
}
-}
+ /// <summary>
+ /// For overlay to check if an entity can be seen.
+ /// </summary>
+ public bool IsVisible(Entity<MetaDataComponent> ent, StatusIconData data)
+ {
+ var viewer = _playerManager.LocalSession?.AttachedEntity;
+
+ // Always show our icons to our entity
+ if (viewer == ent.Owner)
+ return true;
+
+ if (data.VisibleToGhosts && HasComp<GhostComponent>(viewer))
+ return true;
+
+ if (data.HideInContainer && (ent.Comp.Flags & MetaDataFlags.InContainer) != 0)
+ return false;
+
+ if (data.HideOnStealth && TryComp<StealthComponent>(ent, out var stealth) && stealth.Enabled)
+ return false;
+
+ if (data.ShowTo != null && !_entityWhitelist.IsValid(data.ShowTo, viewer))
+ return false;
+
+ return true;
+ }
+}
using Content.Client.Interactable.Components;
+using Content.Client.StatusIcon;
using Content.Shared.Stealth;
using Content.Shared.Stealth.Components;
using Robust.Client.GameObjects;
base.Initialize();
_shader = _protoMan.Index<ShaderPrototype>("Stealth").InstanceUnique();
+
SubscribeLocalEvent<StealthComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<StealthComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<StealthComponent, BeforePostShaderRenderEvent>(OnShaderRender);
args.Sprite.Color = new Color(visibility, visibility, 1, 1);
}
}
-
using System.Linq;
using Content.Shared.Ghost;
using Content.Shared.Humanoid;
+using Content.Shared.StatusIcon;
using Content.Shared.StatusIcon.Components;
using Content.Shared.Zombies;
using Robust.Client.GameObjects;
+using Robust.Shared.Prototypes;
namespace Content.Client.Zombies;
-public sealed class ZombieSystem : EntitySystem
+public sealed class ZombieSystem : SharedZombieSystem
{
+ [Dependency] private readonly IPrototypeManager _prototype = default!;
+
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ZombieComponent, ComponentStartup>(OnStartup);
- SubscribeLocalEvent<ZombieComponent, CanDisplayStatusIconsEvent>(OnCanDisplayStatusIcons);
- SubscribeLocalEvent<InitialInfectedComponent, CanDisplayStatusIconsEvent>(OnCanDisplayStatusIcons);
+ SubscribeLocalEvent<ZombieComponent, GetStatusIconsEvent>(GetZombieIcon);
+ SubscribeLocalEvent<InitialInfectedComponent, GetStatusIconsEvent>(GetInitialInfectedIcon);
}
- private void OnStartup(EntityUid uid, ZombieComponent component, ComponentStartup args)
+ private void GetZombieIcon(Entity<ZombieComponent> ent, ref GetStatusIconsEvent args)
{
- if (HasComp<HumanoidAppearanceComponent>(uid))
- return;
-
- if (!TryComp<SpriteComponent>(uid, out var sprite))
- return;
-
- for (var i = 0; i < sprite.AllLayers.Count(); i++)
- {
- sprite.LayerSetColor(i, component.SkinColor);
- }
+ var iconPrototype = _prototype.Index(ent.Comp.StatusIcon);
+ args.StatusIcons.Add(iconPrototype);
}
- /// <summary>
- /// Determines whether a player should be able to see the StatusIcon for zombies.
- /// </summary>
- private void OnCanDisplayStatusIcons(EntityUid uid, ZombieComponent component, ref CanDisplayStatusIconsEvent args)
+ private void GetInitialInfectedIcon(Entity<InitialInfectedComponent> ent, ref GetStatusIconsEvent args)
{
- if (HasComp<ZombieComponent>(args.User) || HasComp<InitialInfectedComponent>(args.User) || HasComp<ShowZombieIconsComponent>(args.User))
- return;
-
- if (component.IconVisibleToGhost && HasComp<GhostComponent>(args.User))
+ if (HasComp<ZombieComponent>(ent))
return;
- args.Cancelled = true;
+ var iconPrototype = _prototype.Index(ent.Comp.StatusIcon);
+ args.StatusIcons.Add(iconPrototype);
}
- private void OnCanDisplayStatusIcons(EntityUid uid, InitialInfectedComponent component, ref CanDisplayStatusIconsEvent args)
+ private void OnStartup(EntityUid uid, ZombieComponent component, ComponentStartup args)
{
- if (HasComp<InitialInfectedComponent>(args.User) && !HasComp<ZombieComponent>(args.User))
+ if (HasComp<HumanoidAppearanceComponent>(uid))
return;
- if (component.IconVisibleToGhost && HasComp<GhostComponent>(args.User))
+ if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
- args.Cancelled = true;
+ for (var i = 0; i < sprite.AllLayers.Count(); i++)
+ {
+ sprite.LayerSetColor(i, component.SkinColor);
+ }
}
}
using Content.Shared.StatusIcon;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
+using Robust.Shared.Prototypes;
namespace Content.Server.Access.Components
{
/// <summary>
/// Set of job icons that the agent ID card can show.
/// </summary>
- [DataField("icons", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<StatusIconPrototype>))]
- public HashSet<string> Icons = new();
+ [DataField]
+ public HashSet<ProtoId<StatusIconPrototype>> Icons;
}
}
private void OnJobIconChanged(EntityUid uid, AgentIDCardComponent comp, AgentIDCardJobIconChangedMessage args)
{
if (!TryComp<IdCardComponent>(uid, out var idCard))
- {
return;
- }
- if (!_prototypeManager.TryIndex<StatusIconPrototype>(args.JobIconId, out var jobIcon))
- {
+ if (!_prototypeManager.TryIndex(args.JobIconId, out var jobIcon))
return;
- }
_cardSystem.TryChangeJobIcon(uid, jobIcon, idCard);
{
foreach (var jobPrototype in _prototypeManager.EnumeratePrototypes<JobPrototype>())
{
- if(jobPrototype.Icon == jobIcon.ID)
+ if (jobPrototype.Icon == jobIcon.ID)
{
job = jobPrototype;
return true;
_idCard.TryChangeJobTitle(targetId, newJobTitle, player: player);
if (_prototype.TryIndex<JobPrototype>(newJobProto, out var job)
- && _prototype.TryIndex<StatusIconPrototype>(job.Icon, out var jobIcon))
+ && _prototype.TryIndex(job.Icon, out var jobIcon))
{
_idCard.TryChangeJobIcon(targetId, jobIcon, player: player);
_idCard.TryChangeJobDepartment(targetId, job);
_cardSystem.TryChangeJobTitle(uid, job.LocalizedName);
_cardSystem.TryChangeJobDepartment(uid, job);
- if (_prototypeManager.TryIndex<StatusIconPrototype>(job.Icon, out var jobIcon))
- {
+ if (_prototypeManager.TryIndex(job.Icon, out var jobIcon))
_cardSystem.TryChangeJobIcon(uid, jobIcon);
- }
}
}
--- /dev/null
+using Content.Shared.Revolutionary;
+
+namespace Content.Server.Revolutionary;
+
+public sealed class RevolutionarySystem : SharedRevolutionarySystem;
_cardSystem.TryChangeFullName(cardId, characterName, card);
_cardSystem.TryChangeJobTitle(cardId, jobPrototype.LocalizedName, card);
- if (_prototypeManager.TryIndex<StatusIconPrototype>(jobPrototype.Icon, out var jobIcon))
- {
+ if (_prototypeManager.TryIndex(jobPrototype.Icon, out var jobIcon))
_cardSystem.TryChangeJobIcon(cardId, jobIcon, card);
- }
var extendedAccess = false;
if (station != null)
+using Content.Shared.StatusIcon;
+using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.Access.Systems
[Serializable, NetSerializable]
public sealed class AgentIDCardBoundUserInterfaceState : BoundUserInterfaceState
{
- public readonly HashSet<string> Icons;
+ 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<string> icons)
+ public AgentIDCardBoundUserInterfaceState(string currentName, string currentJob, string currentJobIconId, HashSet<ProtoId<StatusIconPrototype>> icons)
{
Icons = icons;
CurrentName = currentName;
[Serializable, NetSerializable]
public sealed class AgentIDCardJobIconChangedMessage : BoundUserInterfaceMessage
{
- public string JobIconId { get; }
+ public ProtoId<StatusIconPrototype> JobIconId { get; }
- public AgentIDCardJobIconChangedMessage(string jobIconId)
+ public AgentIDCardJobIconChangedMessage(ProtoId<StatusIconPrototype> jobIconId)
{
JobIconId = jobIconId;
}
+++ /dev/null
-using Content.Shared.StatusIcon;
-using Robust.Shared.Prototypes;
-
-namespace Content.Shared.Antag;
-
-public interface IAntagStatusIconComponent
-{
- public ProtoId<StatusIconPrototype> StatusIcon { get; set; }
-
- public bool IconVisibleToGhost { get; set; }
-}
-
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Antag;
+
+/// <summary>
+/// Determines whether Someone can see antags icons
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed partial class ShowAntagIconsComponent: Component;
using Content.Shared.Damage.Prototypes;
+using Content.Shared.StatusIcon;
using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Overlays;
/// </summary>
[DataField("damageContainers", customTypeSerializer: typeof(PrototypeIdListSerializer<DamageContainerPrototype>))]
public List<string> DamageContainers = new();
+
+ [DataField]
+ public ProtoId<StatusIconPrototype> HealthStatusIcon = "HealthIconFine";
}
/// Component used for marking a Head Rev for conversion and winning/losing.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedRevolutionarySystem))]
-public sealed partial class HeadRevolutionaryComponent : Component, IAntagStatusIconComponent
+public sealed partial class HeadRevolutionaryComponent : Component
{
/// <summary>
/// The status icon corresponding to the head revolutionary.
public TimeSpan StunTime = TimeSpan.FromSeconds(3);
public override bool SessionSpecific => true;
-
- [DataField]
- public bool IconVisibleToGhost { get; set; } = true;
}
/// Used for marking regular revs as well as storing icon prototypes so you can see fellow revs.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedRevolutionarySystem))]
-public sealed partial class RevolutionaryComponent : Component, IAntagStatusIconComponent
+public sealed partial class RevolutionaryComponent : Component
{
/// <summary>
/// The status icon prototype displayed for revolutionaries
public SoundSpecifier RevStartSound = new SoundPathSpecifier("/Audio/Ambience/Antag/headrev_start.ogg");
public override bool SessionSpecific => true;
-
- [DataField]
- public bool IconVisibleToGhost { get; set; } = true;
}
+++ /dev/null
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Revolutionary.Components;
-
-/// <summary>
-/// Determines whether Someone can see rev/headrev icons on revs.
-/// </summary>
-[RegisterComponent, NetworkedComponent]
-public sealed partial class ShowRevIconsComponent: Component
-{
-}
-using Content.Shared.Ghost;
using Content.Shared.IdentityManagement;
using Content.Shared.Mindshield.Components;
using Content.Shared.Popups;
using Content.Shared.Stunnable;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
+using Content.Shared.Antag;
namespace Content.Shared.Revolutionary;
-public sealed class SharedRevolutionarySystem : EntitySystem
+public abstract class SharedRevolutionarySystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedStunSystem _sharedStun = default!;
SubscribeLocalEvent<HeadRevolutionaryComponent, ComponentGetStateAttemptEvent>(OnRevCompGetStateAttempt);
SubscribeLocalEvent<RevolutionaryComponent, ComponentStartup>(DirtyRevComps);
SubscribeLocalEvent<HeadRevolutionaryComponent, ComponentStartup>(DirtyRevComps);
- SubscribeLocalEvent<ShowRevIconsComponent, ComponentStartup>(DirtyRevComps);
+ SubscribeLocalEvent<ShowAntagIconsComponent, ComponentStartup>(DirtyRevComps);
}
/// <summary>
/// </summary>
private void OnRevCompGetStateAttempt(EntityUid uid, HeadRevolutionaryComponent comp, ref ComponentGetStateAttemptEvent args)
{
- args.Cancelled = !CanGetState(args.Player, comp.IconVisibleToGhost);
+ args.Cancelled = !CanGetState(args.Player);
}
/// <summary>
/// </summary>
private void OnRevCompGetStateAttempt(EntityUid uid, RevolutionaryComponent comp, ref ComponentGetStateAttemptEvent args)
{
- args.Cancelled = !CanGetState(args.Player, comp.IconVisibleToGhost);
+ args.Cancelled = !CanGetState(args.Player);
}
/// <summary>
/// The criteria that determine whether a Rev/HeadRev component should be sent to a client.
/// </summary>
/// <param name="player"> The Player the component will be sent to.</param>
- /// <param name="visibleToGhosts"> Whether the component permits the icon to be visible to observers. </param>
/// <returns></returns>
- private bool CanGetState(ICommonSession? player, bool visibleToGhosts)
+ private bool CanGetState(ICommonSession? player)
{
//Apparently this can be null in replays so I am just returning true.
- if (player is null)
+ if (player?.AttachedEntity is not {} uid)
return true;
- var uid = player.AttachedEntity;
-
if (HasComp<RevolutionaryComponent>(uid) || HasComp<HeadRevolutionaryComponent>(uid))
return true;
- if (visibleToGhosts && HasComp<GhostComponent>(uid))
- return true;
-
- return HasComp<ShowRevIconsComponent>(uid);
+ return HasComp<ShowAntagIconsComponent>(uid);
}
/// <summary>
/// Dirties all the Rev components so they are sent to clients.
[DataField("jobEntity", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string? JobEntity = null;
- [DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
- public string Icon { get; private set; } = "JobIconUnknown";
+ [DataField]
+ public ProtoId<StatusIconPrototype> Icon { get; private set; } = "JobIconUnknown";
[DataField("special", serverOnly: true)]
public JobSpecial[] Special { get; private set; } = Array.Empty<JobSpecial>();
using Content.Shared.StatusIcon;
using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.SSDIndicator;
public bool IsSSD = true;
[ViewVariables(VVAccess.ReadWrite)]
- [DataField("icon", customTypeSerializer: typeof(PrototypeIdSerializer<StatusIconPrototype>))]
- public string Icon = "SSDIcon";
+ [DataField]
+ public ProtoId<StatusIconPrototype> Icon = "SSDIcon";
}
/// </summary>
/// <param name="StatusIcons"></param>
[ByRefEvent]
-public record struct GetStatusIconsEvent(List<StatusIconData> StatusIcons, bool InContainer);
-
-/// <summary>
-/// Event raised on the Client-side to determine whether to display a status icon on an entity.
-/// </summary>
-/// <param name="User">The player that will see the icons</param>
-[ByRefEvent]
-public record struct CanDisplayStatusIconsEvent(EntityUid? User = null)
-{
- public EntityUid? User = User;
-
- public bool Cancelled = false;
-}
+public record struct GetStatusIconsEvent(List<StatusIconData> StatusIcons);
+using Content.Shared.Stealth.Components;
+using Content.Shared.Whitelist;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
/// <summary>
/// The icon that's displayed on the entity.
/// </summary>
- [DataField("icon", required: true)]
+ [DataField(required: true)]
public SpriteSpecifier Icon = default!;
/// <summary>
/// A priority for the order in which the icons will be displayed.
/// </summary>
- [DataField("priority")]
+ [DataField]
public int Priority = 10;
+ /// <summary>
+ /// Whether or not to hide the icon to ghosts
+ /// </summary>
+ [DataField]
+ public bool VisibleToGhosts = true;
+
+ /// <summary>
+ /// Whether or not to hide the icon when we are inside a container like a locker or a crate.
+ /// </summary>
+ [DataField]
+ public bool HideInContainer = true;
+
+ /// <summary>
+ /// Whether or not to hide the icon when the entity has an active <see cref="StealthComponent"/>
+ /// </summary>
+ [DataField]
+ public bool HideOnStealth = true;
+
+ /// <summary>
+ /// Specifies what entities and components/tags this icon can be shown to.
+ /// </summary>
+ [DataField]
+ public EntityWhitelist? ShowTo;
+
/// <summary>
/// A preference for where the icon will be displayed. None | Left | Right
/// </summary>
- [DataField("locationPreference")]
+ [DataField]
public StatusIconLocationPreference LocationPreference = StatusIconLocationPreference.None;
- public int CompareTo(StatusIconData? other)
- {
- return Priority.CompareTo(other?.Priority ?? int.MaxValue);
- }
-
/// <summary>
/// The layer the icon is displayed on. Mod is drawn above Base. Base | Mod
/// </summary>
/// </summary>
[DataField]
public bool IsShaded = false;
+
+ public int CompareTo(StatusIconData? other)
+ {
+ return Priority.CompareTo(other?.Priority ?? int.MaxValue);
+ }
}
/// <summary>
-using Content.Shared.Antag;
using Content.Shared.StatusIcon;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared.Zombies;
[RegisterComponent, NetworkedComponent]
-public sealed partial class InitialInfectedComponent : Component, IAntagStatusIconComponent
+public sealed partial class InitialInfectedComponent : Component
{
- [DataField("initialInfectedStatusIcon")]
- public ProtoId<StatusIconPrototype> StatusIcon { get; set; } = "InitialInfectedFaction";
-
[DataField]
- public bool IconVisibleToGhost { get; set; } = true;
+ public ProtoId<StatusIconPrototype> StatusIcon = "InitialInfectedFaction";
}
+++ /dev/null
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Zombies;
-
-/// <summary>
-/// Makes it so an entity can view ZombieAntagIcons.
-/// </summary>
-[RegisterComponent, NetworkedComponent]
-public sealed partial class ShowZombieIconsComponent: Component
-{
-
-}
namespace Content.Shared.Zombies;
[RegisterComponent, NetworkedComponent]
-public sealed partial class ZombieComponent : Component, IAntagStatusIconComponent
+public sealed partial class ZombieComponent : Component
{
/// <summary>
/// The baseline infection chance you have if you are completely nude
[DataField("zombieStatusIcon")]
public ProtoId<StatusIconPrototype> StatusIcon { get; set; } = "ZombieFaction";
- [DataField]
- public bool IconVisibleToGhost { get; set; } = true;
-
/// <summary>
/// Healing each second
/// </summary>
- type: Stripping
- type: SolutionScanner
- type: IgnoreUIRange
- - type: ShowRevIcons
- - type: ShowZombieIcons
+ - type: ShowAntagIcons
- type: Inventory
templateId: aghost
- type: InventorySlots
- type: statusIcon
id: ZombieFaction
priority: 11
+ showTo:
+ components:
+ - ShowAntagIcons
+ - Zombie
+ - InitialInfected
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Zombie
- type: statusIcon
id: InitialInfectedFaction
priority: 11
+ showTo:
+ components:
+ - ShowAntagIcons
+ - InitialInfected
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: InitialInfected
- type: statusIcon
id: RevolutionaryFaction
priority: 11
+ showTo:
+ components:
+ - ShowAntagIcons
+ - Revolutionary
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: Revolutionary
- type: statusIcon
id: HeadRevolutionaryFaction
priority: 11
+ showTo:
+ components:
+ - ShowAntagIcons
+ - Revolutionary
icon:
sprite: /Textures/Interface/Misc/job_icons.rsi
state: HeadRevolutionary