mirror of
https://github.com/DeltaV-Station/Delta-v.git
synced 2026-09-30 08:07:28 +00:00
* initial visual nubody * oops overlay * im so pheeming rn * conversion... * tests * comeback of the underwear * oops eyes * blabbl * zeds * yaml linted * search and visible count constraints * reordering * preserve previously selected markings colors * fix test * some ui niceties * ordering * make DB changes backwards-compatible/downgrade-friendly * fix things again * fix migration * vulpkanin markings limit increase * wrapping * code cleanup and more code cleanup and more code cleanup and more code cleanup and * fix slop ports * better sampling API * make filter work + use the method i made for its intended purpose * fix test fails real quick * magic mirror cleanup, remove TODO * don't 0-init the organ profile data * remove deltastates --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> # Conflicts: # Content.Server/Humanoid/Components/RandomHumanoidAppearanceComponent.cs # Content.Server/Humanoid/Systems/RandomHumanoidAppearanceSystem.cs # Conflicts: # Resources/Prototypes/Species/diona.yml # Conflicts: # Content.Server/Zombies/ZombieSystem.Transform.cs
262 lines
8.9 KiB
C#
262 lines
8.9 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)
|
|
{
|
|
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)
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|