Skip to content
Open
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7ce8e75
ммм
kerfus-owo Mar 6, 2026
8b2d0be
Merge remote-tracking branch 'upstream/master' into ipc-visuals
kerfus-owo Mar 7, 2026
e20a4ae
Merge remote-tracking branch 'upstream/master' into ipc-visuals
kerfus-owo Mar 13, 2026
4d0471e
Merge remote-tracking branch 'upstream/master' into ipc-visuals
kerfus-owo Mar 17, 2026
57cc08d
ещё посидиииим
kerfus-owo Mar 17, 2026
541ad0d
фиксики
kerfus-owo Mar 17, 2026
3751f3a
Начало
kerfus-owo Mar 17, 2026
728444e
первая часть квирка
kerfus-owo Mar 17, 2026
6cfec86
Merge remote-tracking branch 'upstream/master' into ipc-visuals
kerfus-owo Mar 18, 2026
5dbec6d
Вторая часть
kerfus-owo Mar 18, 2026
b8f2d89
норм
kerfus-owo Mar 18, 2026
5ab63ab
фиксики?
kerfus-owo Mar 18, 2026
f029b64
лишнее
kerfus-owo Mar 18, 2026
ff45375
заготовка
kerfus-owo Mar 18, 2026
730f228
заготовка 2
kerfus-owo Mar 18, 2026
b81d4b0
заготовка 3
kerfus-owo Mar 18, 2026
903e0ac
мужчина
kerfus-owo Mar 18, 2026
34ecf50
женщина
kerfus-owo Mar 18, 2026
6f18774
Merge remote-tracking branch 'upstream/master' into ipc-visuals
kerfus-owo Mar 19, 2026
107f7be
сойдёт
kerfus-owo Mar 19, 2026
c623b9a
норм
kerfus-owo Mar 19, 2026
2594722
ням
kerfus-owo Mar 19, 2026
7b5a61f
финал очка
kerfus-owo Mar 19, 2026
9562c19
мяу
kerfus-owo Mar 19, 2026
ed459d1
норм
kerfus-owo Mar 19, 2026
8a1606a
фикс
kerfus-owo Mar 19, 2026
b55e924
так?
kerfus-owo Mar 19, 2026
5c097ef
фикс 2
kerfus-owo Mar 19, 2026
274fc57
Фиксы 3
kerfus-owo Mar 19, 2026
d791d7f
фикс???
kerfus-owo Mar 19, 2026
e9ce2af
фиксы 4?
kerfus-owo Mar 19, 2026
7f67f71
Правки
kerfus-owo Mar 19, 2026
0f7319a
Посоветовал хуйни
kerfus-owo Mar 19, 2026
cc77566
Merge branch 'master' into ipc-visuals
Darkiich Mar 19, 2026
585e8b9
Merge branch 'master' into ipc-visuals
Darkiich Mar 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Content.Client/ADT/Lobby/UI/QuirksWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ public void Populate(HumanoidCharacterProfile profile)
else
SelectedQuirksLabel.SetMessage(Loc.GetString("quirks-window-selected-none"), null, Color.White);

var protoList = _proto.EnumeratePrototypes<TraitPrototype>().Where(x => x.Quirk && !x.SpeciesBlacklist.Contains(profile.Species)).ToList();
protoList.Sort((x, y) => Loc.GetString(x.Name)[0].CompareTo(Loc.GetString(y.Name)[0]));
protoList.Sort((x, y) => x.Cost.CompareTo(y.Cost));
//ADT-Tweak-Start
var protoList = _proto.EnumeratePrototypes<TraitPrototype>()
.Where(x => x.Quirk
&& (x.SpeciesWhitelist.Count == 0 || x.SpeciesWhitelist.Contains(profile.Species))
&& !x.SpeciesBlacklist.Contains(profile.Species))
.ToList();
//ADT-Tweak-End

foreach (var proto in protoList)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ protected override void Open()
_window.OnSlotColorChanged += args => SendMessage(new MidroundCustomizationChangeColorMessage(args.Category, args.Colors, args.Slot));
_window.OnSlotAdded += args => SendMessage(new MidroundCustomizationAddSlotMessage(args));
_window.OnSlotRemoved += args => SendMessage(new MidroundCustomizationRemoveSlotMessage(args.Category, args.Slot));
_window.OnPointLightColorToggled += enabled => SendMessage(new MidroundCustomizationPointLightColorToggleMessage(enabled));

_window.OnVoiceChanged += voiceId => SendMessage(new MidroundCustomizationChangeVoiceMessage(voiceId, voiceId));
_window.OnBarkProtoChanged += proto => SendMessage(new MidroundCustomizationChangeBarkProtoMessage(proto));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" HScrollEnabled="False">
<BoxContainer Name="VoiceContainer" Orientation="Vertical" Margin="8">
<BoxContainer Orientation="Vertical" Margin="4" >
<Label Text="{Loc 'humanoid-profile-editor-voice-label'}" />
<Label Text="{Loc 'humanoid-profile-editor-voice-tab'}" />
<BoxContainer Orientation="Horizontal" Margin="0 4 0 0">
<OptionButton Name="VoiceButton" HorizontalExpand="True" />
<Button Name="VoicePlayButton" Text="{Loc 'humanoid-profile-editor-voice-play'}" MaxWidth="80" />
Expand All @@ -19,6 +19,7 @@
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" VScrollEnabled="False" HScrollEnabled="True">
<BoxContainer Name="MarkingsContainer" VerticalExpand="True" HorizontalExpand="True" Orientation="Horizontal" Margin="4"/>
</ScrollContainer>
<CheckBox Name="PointLightColorCheckBox" Text="{Loc 'midround-customization-pointlight-color'}" Margin="8 12 8 8"/>
</BoxContainer>
</ScrollContainer>
</DefaultWindow>
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public sealed partial class MidroundCustomizationWindow : DefaultWindow
public Action<(MarkingCategories Category, int Slot, List<Color> Colors)>? OnSlotColorChanged;
public Action<(MarkingCategories Category, int Slot)>? OnSlotRemoved;
public Action<MarkingCategories>? OnSlotAdded;
public Action<bool>? OnPointLightColorToggled;

public Action<string>? OnVoiceChanged;
public Action<string>? OnBarkProtoChanged;
Expand Down Expand Up @@ -75,6 +76,10 @@ public MidroundCustomizationWindow()

BarkProtoButton.OnPressed += _ => OpenBarkWindow();
BarkPlayButton.OnPressed += _ => PlayPreviewBark();
PointLightColorCheckBox.OnToggled += args =>
{
OnPointLightColorToggled?.Invoke(args.Pressed);
};

_voiceList = _prototypeManager
.EnumeratePrototypes<TTSVoicePrototype>()
Expand Down Expand Up @@ -177,6 +182,12 @@ public void UpdateState(MidroundCustomizationUiState state)
MarkingsContainer.AddChild(picker);
}

PointLightColorCheckBox.Visible = state.PointLightColor;
if (state.PointLightColor)
{
PointLightColorCheckBox.Pressed = state.PointLightColorEnabled;
}

if (state.TTS != null)
{
_currentVoice = state.TTS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,32 @@
using Content.Shared.Humanoid.Markings;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using Content.Shared.Mobs;

namespace Content.Server.ADT.MidroundCustomization;

/// <summary>
/// Allows humanoids to change their appearance mid-round.
/// </summary>
[DataDefinition]
public sealed partial class ChangeSlotOnStateEntry
{
[DataField(required: true)]
public MobState State { get; set; }

[DataField(required: true)]
public MarkingCategories Category { get; set; }

[DataField(required: true)]
public int Slot { get; set; }

[DataField(required: true)]
public string Marking { get; set; } = string.Empty;

[DataField]
public List<Color> Colors { get; set; } = new();
}

[RegisterComponent]
public sealed partial class MidroundCustomizationComponent : Component
{
Expand Down Expand Up @@ -74,4 +94,20 @@ public sealed partial class MidroundCustomizationComponent : Component
[DataField, AutoNetworkedField]
public EntityUid? ActionEntity;

/// <summary>
/// Changes slot on state.
/// </summary>
[DataField]
public List<ChangeSlotOnStateEntry> ChangeSlotOnState { get; set; } = new();

[DataField]
public bool PointLightColor = false;

[DataField, AutoNetworkedField]
public bool PointLightColorEnabled;

public Color OriginalPointLightColor = Color.White;

public Dictionary<MarkingCategories, (string Marking, List<Color> Colors)> RemovedMarkingsBuffer { get; set; } = new();
public Dictionary<(MarkingCategories Category, int Slot), (string Marking, List<Color> Colors)> OriginalMarkings = new();
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Robust.Shared.GameObjects;

namespace Content.Server.ADT.MidroundCustomization;

Expand All @@ -31,6 +34,7 @@ public sealed partial class MidroundCustomizationSystem : EntitySystem
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly ActionsSystem _action = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SharedPointLightSystem _pointLight = default!;

public override void Initialize()
{
Expand All @@ -48,11 +52,14 @@ public override void Initialize()
subs.Event<MidroundCustomizationChangeBarkPitchMessage>(OnTryChangeBarkPitch);
subs.Event<MidroundCustomizationChangeBarkMinVarMessage>(OnTryChangeBarkMinVar);
subs.Event<MidroundCustomizationChangeBarkMaxVarMessage>(OnTryChangeBarkMaxVar);
subs.Event<MidroundCustomizationPointLightColorToggleMessage>(OnPointLightColorToggle);
});

SubscribeLocalEvent<MidroundCustomizationComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<MidroundCustomizationComponent, ComponentShutdown>(OnShutdown);

SubscribeLocalEvent<MidroundCustomizationComponent, MobStateChangedEvent>(OnMobStateChanged);

SubscribeLocalEvent<MidroundCustomizationComponent, SlimeHairSelectDoAfterEvent>(OnSelectSlotDoAfter);
SubscribeLocalEvent<MidroundCustomizationComponent, SlimeHairChangeColorDoAfterEvent>(OnChangeColorDoAfter);
SubscribeLocalEvent<MidroundCustomizationComponent, SlimeHairRemoveSlotDoAfterEvent>(OnRemoveSlotDoAfter);
Expand Down Expand Up @@ -152,6 +159,9 @@ private void OnChangeColorDoAfter(EntityUid uid, MidroundCustomizationComponent

_humanoid.SetMarkingColor(uid, args.Category, args.Slot, args.Colors, force: false);

if (args.Category == MarkingCategories.FacialHair && component.PointLightColorEnabled)
UpdatePointLightColorIfEnabled(uid, component);

// using this makes the UI feel like total ass
// que
// UpdateInterface(uid, component.Target, message.Session);
Expand Down Expand Up @@ -182,7 +192,17 @@ private void OnRemoveSlotDoAfter(EntityUid uid, MidroundCustomizationComponent c
if (args.Handled || args.Target == null || args.Cancelled)
return;

if (TryComp<HumanoidAppearanceComponent>(uid, out var humanoid) &&
humanoid.MarkingSet.TryGetCategory(args.Category, out var markings) &&
args.Slot < markings.Count)
{
var current = markings[args.Slot];
component.RemovedMarkingsBuffer[args.Category] = (current.MarkingId, current.MarkingColors.ToList());
}

_humanoid.RemoveMarking(uid, args.Category, args.Slot);
if (args.Category == MarkingCategories.FacialHair)
UpdatePointLightColorIfEnabled(uid, component);

_audio.PlayPvs(component.ChangeMarkingSound, uid);
UpdateInterface(uid, component);
Expand Down Expand Up @@ -211,15 +231,40 @@ private void OnAddSlotDoAfter(EntityUid uid, MidroundCustomizationComponent comp
if (args.Handled || args.Target == null || args.Cancelled || !TryComp(uid, out HumanoidAppearanceComponent? humanoid))
return;

var marking = _markings.MarkingsByCategoryAndSpecies(args.Category, humanoid.Species).Keys.FirstOrDefault();
string markingId;
List<Color> colors;

if (string.IsNullOrEmpty(marking))
return;
if (component.RemovedMarkingsBuffer.TryGetValue(args.Category, out var removed) &&
!string.IsNullOrEmpty(removed.Marking))
{
markingId = removed.Marking;
colors = removed.Colors;
component.RemovedMarkingsBuffer.Remove(args.Category);
}
else
{
markingId = _markings.MarkingsByCategoryAndSpecies(args.Category, humanoid.Species).Keys.FirstOrDefault() ?? string.Empty;
if (string.IsNullOrEmpty(markingId))
return;

var defaultColor = component.DefaultSkinColoring ? humanoid.SkinColor : Color.White;
colors = new List<Color> { defaultColor };
}

Color color = component.DefaultSkinColoring ? humanoid.SkinColor : Color.White;
if (string.IsNullOrEmpty(markingId))
return;

_audio.PlayPvs(component.ChangeMarkingSound, uid);
_humanoid.AddMarking(uid, marking, color);

int newSlotIndex = 0;
if (humanoid.MarkingSet.TryGetCategory(args.Category, out var currentList))
newSlotIndex = currentList.Count;

_humanoid.AddMarking(uid, markingId, colors.Count > 0 ? colors[0] : Color.White);
_humanoid.SetMarkingColor(uid, args.Category, newSlotIndex, colors, force: false);
if (args.Category == MarkingCategories.FacialHair)
UpdatePointLightColorIfEnabled(uid, component);

UpdateInterface(uid, component);
}

Expand Down Expand Up @@ -429,14 +474,159 @@ private void UpdateInterface(EntityUid uid, MidroundCustomizationComponent compo
humanoid.Bark.MinVar,
humanoid.Bark.MaxVar,
markingDict,
slotsDict);
slotsDict,
component.PointLightColor,
component.PointLightColorEnabled);

_uiSystem.SetUiState(uid, MidroundCustomizationUiKey.Key, state);
}

private void OnMapInit(EntityUid uid, MidroundCustomizationComponent component, MapInitEvent args)
{
_action.AddAction(uid, ref component.ActionEntity, component.Action);

if (component.ChangeSlotOnState.Count == 0)
return;

if (!TryComp<MobStateComponent>(uid, out var mobState) ||
!TryComp<HumanoidAppearanceComponent>(uid, out var humanoid))
return;

var current = mobState.CurrentState;
if (component.ChangeSlotOnState.Any(e => e.State == current))
{
RecordOriginals(uid, component, humanoid);
ApplyStateChanges(uid, component, current, humanoid);
}
}

private void OnPointLightColorToggle(EntityUid uid, MidroundCustomizationComponent component, MidroundCustomizationPointLightColorToggleMessage args)
{
if (!component.PointLightColor)
return;

if (component.PointLightColorEnabled == args.Enabled)
return;

if (args.Enabled)
{
// сохраняем оригинальный цвет при первом включении
if (!component.PointLightColorEnabled)
{
if (_pointLight.TryGetLight(uid, out var light))
component.OriginalPointLightColor = light.Color;
}

component.PointLightColorEnabled = true;
UpdatePointLightColorIfEnabled(uid, component);
}
else
{
if (component.PointLightColorEnabled)
{
_pointLight.SetColor(uid, component.OriginalPointLightColor);
}
component.PointLightColorEnabled = false;
}

UpdateInterface(uid, component);
}

private void UpdatePointLightColorIfEnabled(EntityUid uid, MidroundCustomizationComponent component)
{
if (!component.PointLightColorEnabled)
return;

if (!TryComp<HumanoidAppearanceComponent>(uid, out var humanoid) ||
!humanoid.MarkingSet.TryGetCategory(MarkingCategories.FacialHair, out var markings) ||
markings.Count == 0 || markings[0].MarkingColors.Count == 0)
{
_pointLight.SetColor(uid, component.OriginalPointLightColor);
return;
}

var facialColor = markings[0].MarkingColors[0];
_pointLight.SetColor(uid, facialColor);
}

private void OnMobStateChanged(EntityUid uid, MidroundCustomizationComponent component, MobStateChangedEvent args)
{
if (component.ChangeSlotOnState.Count == 0)
return;

if (!TryComp<HumanoidAppearanceComponent>(uid, out var humanoid))
return;

var oldManaged = component.ChangeSlotOnState.Any(e => e.State == args.OldMobState);
var newManaged = component.ChangeSlotOnState.Any(e => e.State == args.NewMobState);

if (!oldManaged && newManaged)
{
RecordOriginals(uid, component, humanoid);
}

if (newManaged)
{
ApplyStateChanges(uid, component, args.NewMobState, humanoid);
}

if (oldManaged && !newManaged)
{
RevertToOriginals(uid, component, humanoid);
}
}

private void RecordOriginals(EntityUid uid, MidroundCustomizationComponent component, HumanoidAppearanceComponent humanoid)
{
component.OriginalMarkings.Clear();

var managedSlots = component.ChangeSlotOnState
.Select(e => (e.Category, e.Slot))
.Distinct()
.ToList();

foreach (var (category, slot) in managedSlots)
{
if (!humanoid.MarkingSet.TryGetCategory(category, out var list) || slot >= list.Count)
continue;

var current = list[slot];
component.OriginalMarkings[(category, slot)] = (current.MarkingId, current.MarkingColors.ToList());
}
}

private void ApplyStateChanges(EntityUid uid, MidroundCustomizationComponent component, MobState state, HumanoidAppearanceComponent humanoid)
{
var defaultColor = component.DefaultSkinColoring ? humanoid.SkinColor : Color.White;

foreach (var entry in component.ChangeSlotOnState)
{
if (entry.State != state) continue;

_humanoid.SetMarkingId(uid, entry.Category, entry.Slot, entry.Marking, force: false, defaultColor: defaultColor);

if (entry.Colors.Count > 0)
{
_humanoid.SetMarkingColor(uid, entry.Category, entry.Slot, entry.Colors, force: false);
}
}

UpdatePointLightColorIfEnabled(uid, component);
}

private void RevertToOriginals(EntityUid uid, MidroundCustomizationComponent component, HumanoidAppearanceComponent humanoid)
{
var defaultColor = component.DefaultSkinColoring ? humanoid.SkinColor : Color.White;

foreach (var ((cat, slot), (origMarking, origColors)) in component.OriginalMarkings)
{
if (string.IsNullOrEmpty(origMarking)) continue;

_humanoid.SetMarkingId(uid, cat, slot, origMarking, force: false, defaultColor: defaultColor);
_humanoid.SetMarkingColor(uid, cat, slot, origColors, force: false);
}

UpdatePointLightColorIfEnabled(uid, component);
}

private void OnShutdown(EntityUid uid, MidroundCustomizationComponent component, ComponentShutdown args)
Expand Down
Loading
Loading