diff --git a/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalComponent.cs b/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalComponent.cs new file mode 100644 index 0000000000..06f4f9edb7 --- /dev/null +++ b/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.Chat.Prototypes; +using Content.Shared.Humanoid; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; + +namespace Content.Server._Sunrise.ReplacementVocal; + +/// +/// Компонент для замены вокальных звуков и эмоций сущности. +/// Сохраняет предыдущие настройки для возможности восстановления. +/// +[RegisterComponent] +public sealed partial class ReplacementVocalComponent : Component +{ + [DataField(customTypeSerializer: typeof(PrototypeIdValueDictionarySerializer), required: true)] + public Dictionary Vocal; + + [DataField] + public HashSet AddedEmotes = new(); + + [DataField(customTypeSerializer: typeof(PrototypeIdValueDictionarySerializer))] + public Dictionary? PreviousVocal; +} diff --git a/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalSystem.cs b/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalSystem.cs new file mode 100644 index 0000000000..b975161c3a --- /dev/null +++ b/Content.Server/_Sunrise/ReplacementVocal/ReplacementVocalSystem.cs @@ -0,0 +1,72 @@ +using Content.Shared.Humanoid; +using Content.Shared.Speech; +using Content.Shared.Speech.Components; +using Robust.Shared.Prototypes; + +namespace Content.Server._Sunrise.ReplacementVocal; + +public sealed class ReplacementVocalSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + public override void Initialize() + { + SubscribeLocalEvent(OnComponentInit); + SubscribeLocalEvent(OnComponentShutdown); + } + + private void OnComponentInit(EntityUid uid, ReplacementVocalComponent component, ComponentInit args) + { + if (!TryComp(uid, out var vocalComponent)) + return; + + if (component.Vocal.Keys == vocalComponent.Sounds?.Keys) + return; + + if (!TryComp(uid, out var speechComponent)) + return; + + component.PreviousVocal = vocalComponent.Sounds; + + vocalComponent.Sounds = component.Vocal; + + LoadEmotes(uid, vocalComponent); + + foreach (var emote in vocalComponent.EmoteSounds!.Sounds.Keys) + { + if (speechComponent.AllowedEmotes.Contains(emote)) + continue; + + speechComponent.AllowedEmotes.Add(emote); + component.AddedEmotes.Add(emote); + } + } + + private void OnComponentShutdown(EntityUid uid, ReplacementVocalComponent component, ComponentShutdown args) + { + if (!TryComp(uid, out var speech)) + return; + + if (!TryComp(uid, out var vocal)) + return; + + if (component.PreviousVocal != null) + vocal.Sounds = component.PreviousVocal; + + LoadEmotes(uid, vocal); + + foreach (var emote in component.AddedEmotes) + { + speech.AllowedEmotes.Remove(emote); + } + + component.AddedEmotes.Clear(); + } + + private void LoadEmotes(EntityUid uid, VocalComponent vocalComponent) + { + var sex = CompOrNull(uid)?.Sex ?? Sex.Unsexed; + + if (vocalComponent.Sounds?.TryGetValue(sex, out var protoId) == true) + _proto.TryIndex(protoId, out vocalComponent.EmoteSounds); + } +} diff --git a/Resources/Locale/ru-RU/_strings/_sunrise/traits/traits.ftl b/Resources/Locale/ru-RU/_strings/_sunrise/traits/traits.ftl index 6d3842e941..c66885b3a3 100644 --- a/Resources/Locale/ru-RU/_strings/_sunrise/traits/traits.ftl +++ b/Resources/Locale/ru-RU/_strings/_sunrise/traits/traits.ftl @@ -1,3 +1,5 @@ +trait-category-height = Рост +trait-category-vocal = Голос trait-colorblindness-name = Дальтонизм trait-colorblindness-desc = Вы видите мир не так, как все. trait-OwOAccent-name = акцент OwO @@ -16,4 +18,5 @@ trait-tall-quirk-name = высокий trait-tall-quirk-desc = Делает вас немного выше (Только визуально!). trait-short-quirk-name = низкий trait-short-quirk-desc = Делает вас немного ниже (Только визуально!). -trait-category-height = Рост +trait-felinid-vocal-name = мурлыкание +trait-felinid-vocal-desc = Заменяет ваши звуки эмоций фелинидскими. Ня! diff --git a/Resources/Prototypes/_Sunrise/Traits/categories.yml b/Resources/Prototypes/_Sunrise/Traits/categories.yml index f80cad0556..ca19cd9576 100644 --- a/Resources/Prototypes/_Sunrise/Traits/categories.yml +++ b/Resources/Prototypes/_Sunrise/Traits/categories.yml @@ -2,3 +2,9 @@ id: HeightTraits name: trait-category-height maxTraitPoints: 1 + +- type: traitCategory + id: VocalTraits + name: trait-category-vocal + maxTraitPoints: 1 + diff --git a/Resources/Prototypes/_Sunrise/Traits/quirks.yml b/Resources/Prototypes/_Sunrise/Traits/quirks.yml index e4298d23b4..e2193cc350 100644 --- a/Resources/Prototypes/_Sunrise/Traits/quirks.yml +++ b/Resources/Prototypes/_Sunrise/Traits/quirks.yml @@ -25,3 +25,16 @@ components: - type: RescaleSprite scale: 1,0.9 + +- type: trait + id: FelinidVocal + name: trait-felinid-vocal-name + description: trait-felinid-vocal-desc + category: VocalTraits + cost: 1 + components: + - type: ReplacementVocal + vocal: + Male: MaleFelinid + Female: FemaleFelinid + Unsexed: MaleFelinid