mirror of
https://github.com/space-wizards/space-station-14.git
synced 2026-02-15 03:31:30 +01:00
* Fix hideable humanoid layers * test maintenance coin * clean return * voxes can no longer have human beards * voxes fixes * voxing out --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
265 lines
9.1 KiB
C#
265 lines
9.1 KiB
C#
using System.Linq;
|
|
using Content.Shared.Body;
|
|
using Content.Shared.CCVar;
|
|
using Content.Shared.Humanoid.Markings;
|
|
using Content.Shared.Humanoid;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.Graphics;
|
|
using Robust.Shared.Configuration;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Content.Client.Body;
|
|
|
|
public sealed class VisualBodySystem : SharedVisualBodySystem
|
|
{
|
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
|
[Dependency] private readonly MarkingManager _marking = default!;
|
|
[Dependency] private readonly SpriteSystem _sprite = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<VisualOrganComponent, OrganGotInsertedEvent>(OnOrganGotInserted);
|
|
SubscribeLocalEvent<VisualOrganComponent, OrganGotRemovedEvent>(OnOrganGotRemoved);
|
|
SubscribeLocalEvent<VisualOrganComponent, AfterAutoHandleStateEvent>(OnOrganState);
|
|
|
|
SubscribeLocalEvent<VisualOrganMarkingsComponent, OrganGotInsertedEvent>(OnMarkingsGotInserted);
|
|
SubscribeLocalEvent<VisualOrganMarkingsComponent, OrganGotRemovedEvent>(OnMarkingsGotRemoved);
|
|
SubscribeLocalEvent<VisualOrganMarkingsComponent, AfterAutoHandleStateEvent>(OnMarkingsState);
|
|
|
|
SubscribeLocalEvent<VisualOrganMarkingsComponent, BodyRelayedEvent<HumanoidLayerVisibilityChangedEvent>>(OnMarkingsChangedVisibility);
|
|
|
|
Subs.CVar(_cfg, CCVars.AccessibilityClientCensorNudity, OnCensorshipChanged, true);
|
|
Subs.CVar(_cfg, CCVars.AccessibilityServerCensorNudity, OnCensorshipChanged, true);
|
|
}
|
|
|
|
private void OnCensorshipChanged(bool value)
|
|
{
|
|
var query = AllEntityQuery<OrganComponent, VisualOrganMarkingsComponent>();
|
|
while (query.MoveNext(out var ent, out var organComp, out var markingsComp))
|
|
{
|
|
if (organComp.Body is not { } body)
|
|
continue;
|
|
|
|
RemoveMarkings((ent, markingsComp), body);
|
|
ApplyMarkings((ent, markingsComp), body);
|
|
}
|
|
}
|
|
|
|
private void OnOrganGotInserted(Entity<VisualOrganComponent> ent, ref OrganGotInsertedEvent args)
|
|
{
|
|
ApplyVisual(ent, args.Target);
|
|
}
|
|
|
|
private void OnOrganGotRemoved(Entity<VisualOrganComponent> ent, ref OrganGotRemovedEvent args)
|
|
{
|
|
RemoveVisual(ent, args.Target);
|
|
}
|
|
|
|
private void OnOrganState(Entity<VisualOrganComponent> ent, ref AfterAutoHandleStateEvent args)
|
|
{
|
|
if (Comp<OrganComponent>(ent).Body is not { } body)
|
|
return;
|
|
|
|
ApplyVisual(ent, body);
|
|
}
|
|
|
|
private void ApplyVisual(Entity<VisualOrganComponent> ent, EntityUid target)
|
|
{
|
|
if (!_sprite.LayerMapTryGet(target, ent.Comp.Layer, out var index, true))
|
|
return;
|
|
|
|
_sprite.LayerSetData(target, index, ent.Comp.Data);
|
|
}
|
|
|
|
private void RemoveVisual(Entity<VisualOrganComponent> ent, EntityUid target)
|
|
{
|
|
if (!_sprite.LayerMapTryGet(target, ent.Comp.Layer, out var index, true))
|
|
return;
|
|
|
|
_sprite.LayerSetRsiState(target, index, RSI.StateId.Invalid);
|
|
}
|
|
|
|
private void OnMarkingsGotInserted(Entity<VisualOrganMarkingsComponent> ent, ref OrganGotInsertedEvent args)
|
|
{
|
|
ApplyMarkings(ent, args.Target);
|
|
}
|
|
|
|
private void OnMarkingsGotRemoved(Entity<VisualOrganMarkingsComponent> ent, ref OrganGotRemovedEvent args)
|
|
{
|
|
RemoveMarkings(ent, args.Target);
|
|
}
|
|
|
|
private void OnMarkingsState(Entity<VisualOrganMarkingsComponent> ent, ref AfterAutoHandleStateEvent args)
|
|
{
|
|
if (Comp<OrganComponent>(ent).Body is not { } body)
|
|
return;
|
|
|
|
RemoveMarkings(ent, body);
|
|
ApplyMarkings(ent, body);
|
|
}
|
|
|
|
protected override void SetOrganColor(Entity<VisualOrganComponent> ent, Color color)
|
|
{
|
|
base.SetOrganColor(ent, color);
|
|
|
|
if (Comp<OrganComponent>(ent).Body is not { } body)
|
|
return;
|
|
|
|
ApplyVisual(ent, body);
|
|
}
|
|
|
|
protected override void SetOrganMarkings(Entity<VisualOrganMarkingsComponent> ent, Dictionary<HumanoidVisualLayers, List<Marking>> markings)
|
|
{
|
|
base.SetOrganMarkings(ent, markings);
|
|
|
|
if (Comp<OrganComponent>(ent).Body is not { } body)
|
|
return;
|
|
|
|
RemoveMarkings(ent, body);
|
|
ApplyMarkings(ent, body);
|
|
}
|
|
|
|
protected override void SetOrganAppearance(Entity<VisualOrganComponent> ent, PrototypeLayerData data)
|
|
{
|
|
base.SetOrganAppearance(ent, data);
|
|
|
|
if (Comp<OrganComponent>(ent).Body is not { } body)
|
|
return;
|
|
|
|
ApplyVisual(ent, body);
|
|
}
|
|
|
|
private IEnumerable<Marking> AllMarkings(Entity<VisualOrganMarkingsComponent> ent)
|
|
{
|
|
foreach (var markings in ent.Comp.Markings.Values)
|
|
{
|
|
foreach (var marking in markings)
|
|
{
|
|
yield return marking;
|
|
}
|
|
}
|
|
|
|
var censorNudity = _cfg.GetCVar(CCVars.AccessibilityClientCensorNudity) || _cfg.GetCVar(CCVars.AccessibilityServerCensorNudity);
|
|
if (!censorNudity)
|
|
yield break;
|
|
|
|
var group = _prototype.Index(ent.Comp.MarkingData.Group);
|
|
foreach (var layer in ent.Comp.MarkingData.Layers)
|
|
{
|
|
if (!group.Limits.TryGetValue(layer, out var layerLimits))
|
|
continue;
|
|
|
|
if (layerLimits.NudityDefault.Count < 1)
|
|
continue;
|
|
|
|
var markings = ent.Comp.Markings.GetValueOrDefault(layer) ?? [];
|
|
if (markings.Any(marking => _marking.TryGetMarking(marking, out var proto) && proto.BodyPart == layer))
|
|
continue;
|
|
|
|
foreach (var marking in layerLimits.NudityDefault)
|
|
{
|
|
yield return new(marking, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ApplyMarkings(Entity<VisualOrganMarkingsComponent> ent, EntityUid target)
|
|
{
|
|
var applied = new List<Marking>();
|
|
foreach (var marking in AllMarkings(ent))
|
|
{
|
|
if (!_marking.TryGetMarking(marking, out var proto))
|
|
continue;
|
|
|
|
if (!_sprite.LayerMapTryGet(target, proto.BodyPart, out var index, true))
|
|
continue;
|
|
|
|
for (var i = 0; i < proto.Sprites.Count; i++)
|
|
{
|
|
var sprite = proto.Sprites[i];
|
|
|
|
DebugTools.Assert(sprite is SpriteSpecifier.Rsi);
|
|
if (sprite is not SpriteSpecifier.Rsi rsi)
|
|
continue;
|
|
|
|
var layerId = $"{proto.ID}-{rsi.RsiState}";
|
|
|
|
if (!_sprite.LayerMapTryGet(target, layerId, out _, false))
|
|
{
|
|
var layer = _sprite.AddLayer(target, sprite, index + i + 1);
|
|
_sprite.LayerMapSet(target, layerId, layer);
|
|
_sprite.LayerSetSprite(target, layerId, rsi);
|
|
}
|
|
|
|
if (marking.MarkingColors is not null && i < marking.MarkingColors.Count)
|
|
_sprite.LayerSetColor(target, layerId, marking.MarkingColors[i]);
|
|
else
|
|
_sprite.LayerSetColor(target, layerId, Color.White);
|
|
}
|
|
|
|
applied.Add(marking);
|
|
}
|
|
ent.Comp.AppliedMarkings = applied;
|
|
}
|
|
|
|
private void RemoveMarkings(Entity<VisualOrganMarkingsComponent> ent, EntityUid target)
|
|
{
|
|
foreach (var marking in ent.Comp.AppliedMarkings)
|
|
{
|
|
if (!_marking.TryGetMarking(marking, out var proto))
|
|
continue;
|
|
|
|
foreach (var sprite in proto.Sprites)
|
|
{
|
|
DebugTools.Assert(sprite is SpriteSpecifier.Rsi);
|
|
if (sprite is not SpriteSpecifier.Rsi rsi)
|
|
continue;
|
|
|
|
var layerId = $"{proto.ID}-{rsi.RsiState}";
|
|
|
|
if (!_sprite.LayerMapTryGet(target, layerId, out var index, false))
|
|
continue;
|
|
|
|
_sprite.LayerMapRemove(target, layerId);
|
|
_sprite.RemoveLayer(target, index);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnMarkingsChangedVisibility(Entity<VisualOrganMarkingsComponent> ent, ref BodyRelayedEvent<HumanoidLayerVisibilityChangedEvent> args)
|
|
{
|
|
if (!ent.Comp.HideableLayers.Contains(args.Args.Layer))
|
|
return;
|
|
|
|
foreach (var markings in ent.Comp.Markings.Values)
|
|
{
|
|
foreach (var marking in markings)
|
|
{
|
|
if (!_marking.TryGetMarking(marking, out var proto))
|
|
continue;
|
|
|
|
if (proto.BodyPart != args.Args.Layer && !(ent.Comp.DependentHidingLayers.TryGetValue(args.Args.Layer, out var dependent) && dependent.Contains(proto.BodyPart)))
|
|
continue;
|
|
|
|
foreach (var sprite in proto.Sprites)
|
|
{
|
|
DebugTools.Assert(sprite is SpriteSpecifier.Rsi);
|
|
if (sprite is not SpriteSpecifier.Rsi rsi)
|
|
continue;
|
|
|
|
var layerId = $"{proto.ID}-{rsi.RsiState}";
|
|
|
|
if (!_sprite.LayerMapTryGet(args.Body.Owner, layerId, out var index, true))
|
|
continue;
|
|
|
|
_sprite.LayerSetVisible(args.Body.Owner, index, args.Args.Visible);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|