From 91eb7bff09e7c61896b92fde70ac7c4d47e96a6d Mon Sep 17 00:00:00 2001 From: Peptide90 <78795277+Peptide90@users.noreply.github.com> Date: Tue, 4 Feb 2025 06:36:16 +0000 Subject: [PATCH] International Space Station Update - New Accent Traits (#1712) Ports Russian and German languages from Wizden and adds traits for them. Also adds traits for Italian, French and Spanish since they already exist. Not tested because the game didn't want to build locally. # Changelog :cl: - add: Added traits for accents: Russian, German, French, Italian and Spanish --------- Signed-off-by: Peptide90 <78795277+Peptide90@users.noreply.github.com> --- .../Components/GermanAccentComponent.cs | 4 + .../EntitySystems/GermanAccentSystem.cs | 85 ++++++++ .../EntitySystems/RussianAccentSystem.cs | 6 +- Resources/Locale/en-US/accent/german.ftl | 199 ++++++++++++++++++ Resources/Locale/en-US/accent/russian.ftl | 19 ++ Resources/Locale/en-US/traits/traits.ftl | 15 ++ .../Prototypes/Accents/word_replacements.yml | 93 +++++++- Resources/Prototypes/Traits/neutral.yml | 55 +++++ 8 files changed, 473 insertions(+), 3 deletions(-) create mode 100644 Content.Server/Speech/Components/GermanAccentComponent.cs create mode 100644 Content.Server/Speech/EntitySystems/GermanAccentSystem.cs create mode 100644 Resources/Locale/en-US/accent/german.ftl create mode 100644 Resources/Locale/en-US/accent/russian.ftl diff --git a/Content.Server/Speech/Components/GermanAccentComponent.cs b/Content.Server/Speech/Components/GermanAccentComponent.cs new file mode 100644 index 00000000000..4f387d1e01a --- /dev/null +++ b/Content.Server/Speech/Components/GermanAccentComponent.cs @@ -0,0 +1,4 @@ +namespace Content.Server.Speech.Components; + +[RegisterComponent] +public sealed partial class GermanAccentComponent : Component; diff --git a/Content.Server/Speech/EntitySystems/GermanAccentSystem.cs b/Content.Server/Speech/EntitySystems/GermanAccentSystem.cs new file mode 100644 index 00000000000..1973d38afb6 --- /dev/null +++ b/Content.Server/Speech/EntitySystems/GermanAccentSystem.cs @@ -0,0 +1,85 @@ +using System.Text; +using Content.Server.Speech.Components; +using Robust.Shared.Random; +using System.Text.RegularExpressions; + +namespace Content.Server.Speech.EntitySystems; + +public sealed class GermanAccentSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly ReplacementAccentSystem _replacement = default!; + + private static readonly Regex RegexTh = new(@"(?<=\s|^)th", RegexOptions.IgnoreCase); + private static readonly Regex RegexThe = new(@"(?<=\s|^)the(?=\s|$)", RegexOptions.IgnoreCase); + + public override void Initialize() + { + SubscribeLocalEvent(OnAccent); + } + + public string Accentuate(string message) + { + var msg = message; + + // rarely, "the" should become "das" instead of "ze" + // TODO: The ReplacementAccentSystem should have random replacements this built-in. + foreach (Match match in RegexThe.Matches(msg)) + { + if (_random.Prob(0.3f)) + { + // just shift T, H and E over to D, A and S to preserve capitalization + msg = msg.Substring(0, match.Index) + + (char)(msg[match.Index] - 16) + + (char)(msg[match.Index + 1] - 7) + + (char)(msg[match.Index + 2] + 14) + + msg.Substring(match.Index + 3); + } + } + + // now, apply word replacements + msg = _replacement.ApplyReplacements(msg, "german"); + + // replace th with zh (for zhis, zhat, etc. the => ze is handled by replacements already) + var msgBuilder = new StringBuilder(msg); + foreach (Match match in RegexTh.Matches(msg)) + { + // just shift the T over to a Z to preserve capitalization + msgBuilder[match.Index] = (char) (msgBuilder[match.Index] + 6); + } + + // Random Umlaut Time! (The joke outweighs the emotional damage this inflicts on actual Germans) + var umlautCooldown = 0; + for (var i = 0; i < msgBuilder.Length; i++) + { + if (umlautCooldown == 0) + { + if (_random.Prob(0.1f)) // 10% of all eligible vowels become umlauts) + { + msgBuilder[i] = msgBuilder[i] switch + { + 'A' => 'Ä', + 'a' => 'ä', + 'O' => 'Ö', + 'o' => 'ö', + 'U' => 'Ü', + 'u' => 'ü', + _ => msgBuilder[i] + }; + umlautCooldown = 4; + } + } + else + { + umlautCooldown--; + } + } + + return msgBuilder.ToString(); + } + + private void OnAccent(Entity ent, ref AccentGetEvent args) + { + args.Message = Accentuate(args.Message); + } +} diff --git a/Content.Server/Speech/EntitySystems/RussianAccentSystem.cs b/Content.Server/Speech/EntitySystems/RussianAccentSystem.cs index 33e4513d93f..49aab38e2b7 100644 --- a/Content.Server/Speech/EntitySystems/RussianAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/RussianAccentSystem.cs @@ -5,14 +5,15 @@ namespace Content.Server.Speech.EntitySystems; public sealed class RussianAccentSystem : EntitySystem { + [Dependency] private readonly ReplacementAccentSystem _replacement = default!; public override void Initialize() { SubscribeLocalEvent(OnAccent); } - public static string Accentuate(string message) + public string Accentuate(string message) { - var accentedMessage = new StringBuilder(message); + var accentedMessage = new StringBuilder(_replacement.ApplyReplacements(message, "russian")); for (var i = 0; i < accentedMessage.Length; i++) { @@ -20,6 +21,7 @@ public static string Accentuate(string message) accentedMessage[i] = c switch { + 'A' => 'Д', 'b' => 'в', 'N' => 'И', 'n' => 'и', diff --git a/Resources/Locale/en-US/accent/german.ftl b/Resources/Locale/en-US/accent/german.ftl new file mode 100644 index 00000000000..ccb57ba714c --- /dev/null +++ b/Resources/Locale/en-US/accent/german.ftl @@ -0,0 +1,199 @@ +accent-german-words-1 = yes +accent-german-words-1-2 = yea +accent-german-words-replace-1 = ja + +accent-german-words-2 = no +accent-german-words-replace-2 = nein + +accent-german-words-3 = the +accent-german-words-replace-3 = ze + +accent-german-words-4 = shit +accent-german-words-replace-4 = scheisse + +accent-german-words-5 = sausage +accent-german-words-replace-5 = wurst + +accent-german-words-6 = sausages +accent-german-words-replace-6 = würste + +accent-german-words-7 = man +accent-german-words-replace-7 = mann + +accent-german-words-8 = men +accent-german-words-replace-8 = männer + +accent-german-words-9 = woman +accent-german-words-9-2 = lady +accent-german-words-replace-9 = frau + +accent-german-words-10 = women +accent-german-words-10-2 = ladies +accent-german-words-replace-10 = frauen + +accent-german-words-11 = gentleman +accent-german-words-replace-11 = herr + +accent-german-words-12 = gentlemen +accent-german-words-replace-12 = herren + +accent-german-words-13 = my god +accent-german-words-replace-13 = mein gott + +accent-german-words-14 = my +accent-german-words-replace-14 = mein + +accent-german-words-15 = here +accent-german-words-replace-15 = hier + +accent-german-words-16 = idiot +accent-german-words-replace-16 = dummkopf + +accent-german-words-17 = idiots +accent-german-words-replace-17 = dummköpfe + +accent-german-words-18 = butterfly +accent-german-words-replace-18 = schmetterling + +accent-german-words-19 = machine +accent-german-words-replace-19 = maschine + +accent-german-words-20 = machines +accent-german-words-replace-20 = maschinen + +accent-german-words-21 = watch out +accent-german-words-replace-21 = achtung + +accent-german-words-22 = music +accent-german-words-replace-22 = musik + +accent-german-words-23 = captain +accent-german-words-replace-23 = kapitän + +accent-german-words-24 = kebab +accent-german-words-replace-24 = döner + +accent-german-words-25 = mouse +accent-german-words-replace-25 = maus + +accent-german-words-26 = what +accent-german-words-replace-26 = wat + +accent-german-words-27 = thank you +accent-german-words-replace-27 = dankeschön + +accent-german-words-28 = thanks +accent-german-words-replace-28 = danke + +accent-german-words-29 = bless you +accent-german-words-replace-29 = gesundheit + +accent-german-words-30 = flamethrower +accent-german-words-replace-30 = flammenwerfer + +accent-german-words-31 = ghost +accent-german-words-replace-31 = poltergeist + +accent-german-words-32 = weed +accent-german-words-32-2 = cabbage +accent-german-words-replace-32 = kraut + +accent-german-words-33 = vodka +accent-german-words-replace-33 = wodka + +accent-german-words-34 = backpack +accent-german-words-replace-34 = rucksack + +accent-german-words-35 = medicine +accent-german-words-replace-35 = medizin + +accent-german-words-36 = accent +accent-german-words-replace-36 = akzent + +accent-german-words-37 = anomaly +accent-german-words-replace-37 = anomalie + +accent-german-words-38 = artifact +accent-german-words-38-2 = artefact +accent-german-words-replace-38 = artefakt + +accent-german-words-39 = dumb +accent-german-words-replace-39 = dumm + +accent-german-words-40 = stupid +accent-german-words-replace-40 = doof + +accent-german-words-41 = wonderful +accent-german-words-replace-41 = wunderbar + +accent-german-words-42 = warning +accent-german-words-replace-42 = warnung + +accent-german-words-43 = warnings +accent-german-words-replace-43 = warnungen + +accent-german-words-44 = and +accent-german-words-replace-44 = und + +accent-german-words-45 = carp +accent-german-words-replace-45 = karpfen + +accent-german-words-46 = commander +accent-german-words-replace-46 = kommandant + +accent-german-words-47 = beer +accent-german-words-47-2 = beers +accent-german-words-replace-47 = bier + +accent-german-words-48 = hi +accent-german-words-replace-48 = hallo + +accent-german-words-49 = hello +accent-german-words-replace-49 = guten Tag + +accent-german-words-50 = ambulance +accent-german-words-replace-50 = krankenwagen + +accent-german-words-51 = goodbye +accent-german-words-replace-51 = auf Wiedersehen + +accent-german-words-52 = bye +accent-german-words-replace-52 = tschüss + +accent-german-words-53 = bye bye +accent-german-words-53-2 = bye-bye +accent-german-words-replace-53 = tschau + +accent-german-words-54 = fantastic +accent-german-words-replace-54 = fantastisch + +accent-german-words-55 = changeling +accent-german-words-replace-55 = doppelgänger + +accent-german-words-56 = forbidden +accent-german-words-56-2 = prohibited +accent-german-words-56-3 = banned +accent-german-words-replace-56 = verboten + +accent-german-words-57 = quick +accent-german-words-57-2 = quickly +accent-german-words-replace-57 = schnell + +accent-german-words-58 = hospital +accent-german-words-replace-58 = krankenhaus + +accent-german-words-59 = tesla coil +accent-german-words-replace-59 = tesla coil + +accent-german-words-60 = tesla coils +accent-german-words-replace-60 = tesla coils + +accent-german-words-61 = teslaloose +accent-german-words-61-2 = tesloose +accent-german-words-61-3 = lightning ball +accent-german-words-61-4 = ball lightning +accent-german-words-61-5 = tesla +accent-german-words-replace-61 = kugelblitz + +accent-german-words-62 = car +accent-german-words-replace-62 = auto \ No newline at end of file diff --git a/Resources/Locale/en-US/accent/russian.ftl b/Resources/Locale/en-US/accent/russian.ftl new file mode 100644 index 00000000000..596342dc9f1 --- /dev/null +++ b/Resources/Locale/en-US/accent/russian.ftl @@ -0,0 +1,19 @@ +accent-russian-words-1 = yes +accent-russian-words-replace-1 = da + +accent-russian-words-2 = no +accent-russian-words-replace-2 = nyet + +accent-russian-words-3 = grandma +accent-russian-words-3-2 = grandmother +accent-russian-words-3-3 = granny +accent-russian-words-replace-3 = babushka + +accent-russian-words-4 = friend +accent-russian-words-replace-4 = comrade + +accent-russian-words-5 = friends +accent-russian-words-replace-5 = comrades + +accent-russian-words-6 = cheers +accent-russian-words-replace-6 = na zdorovje \ No newline at end of file diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index 8b4d5d56741..6747e2e1a54 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -80,6 +80,21 @@ trait-description-Stutter = trait-name-Southern = Southern Drawl trait-description-Southern = You have a different way of speakin'. +trait-name-GermanAccent = German accent +trait-description-GermanAccent = You speak with a German accent. + +trait-name-RussianAccent = Russian accent +trait-description-RussianAccent = You speak with a Russian accent. + +trait-name-FrenchAccent = French accent +trait-description-FrenchAccent = You speak with a French accent. + +trait-name-ItalianAccent = Italian accent +trait-description-ItalianAccent = You speak with a Italian accent. + +trait-name-SpanishAccent = Spanish accent +trait-description-SpanishAccent = You speak with a Spanish accent. + trait-name-Snoring = Snoring trait-description-Snoring = You tend to snore loudly while sleeping. diff --git a/Resources/Prototypes/Accents/word_replacements.yml b/Resources/Prototypes/Accents/word_replacements.yml index cb4cdf0683a..edd849bf87c 100644 --- a/Resources/Prototypes/Accents/word_replacements.yml +++ b/Resources/Prototypes/Accents/word_replacements.yml @@ -471,4 +471,95 @@ liar-word-39: liar-word-replacement-39 liar-word-40: liar-word-replacement-40 liar-word-41: liar-word-replacement-41 - liar-word-42: liar-word-replacement-42 \ No newline at end of file + liar-word-42: liar-word-replacement-42 + +- type: accent + id: german + wordReplacements: + accent-german-words-1: accent-german-words-replace-1 + accent-german-words-1-2: accent-german-words-replace-1 + accent-german-words-2: accent-german-words-replace-2 + accent-german-words-3: accent-german-words-replace-3 + accent-german-words-4: accent-german-words-replace-4 + accent-german-words-5: accent-german-words-replace-5 + accent-german-words-6: accent-german-words-replace-6 + accent-german-words-7: accent-german-words-replace-7 + accent-german-words-8: accent-german-words-replace-8 + accent-german-words-9: accent-german-words-replace-9 + accent-german-words-9-2: accent-german-words-replace-9 + accent-german-words-10: accent-german-words-replace-10 + accent-german-words-10-2: accent-german-words-replace-10 + accent-german-words-11: accent-german-words-replace-11 + accent-german-words-12: accent-german-words-replace-12 + accent-german-words-13: accent-german-words-replace-13 + accent-german-words-14: accent-german-words-replace-14 + accent-german-words-15: accent-german-words-replace-15 + accent-german-words-16: accent-german-words-replace-16 + accent-german-words-17: accent-german-words-replace-17 + accent-german-words-18: accent-german-words-replace-18 + accent-german-words-19: accent-german-words-replace-19 + accent-german-words-20: accent-german-words-replace-20 + accent-german-words-21: accent-german-words-replace-21 + accent-german-words-22: accent-german-words-replace-22 + accent-german-words-23: accent-german-words-replace-23 + accent-german-words-24: accent-german-words-replace-24 + accent-german-words-25: accent-german-words-replace-25 + accent-german-words-26: accent-german-words-replace-26 + accent-german-words-27: accent-german-words-replace-27 + accent-german-words-28: accent-german-words-replace-28 + accent-german-words-29: accent-german-words-replace-29 + accent-german-words-30: accent-german-words-replace-30 + accent-german-words-31: accent-german-words-replace-31 + accent-german-words-32: accent-german-words-replace-32 + accent-german-words-32-2: accent-german-words-replace-32 + accent-german-words-33: accent-german-words-replace-33 + accent-german-words-34: accent-german-words-replace-34 + accent-german-words-35: accent-german-words-replace-35 + accent-german-words-36: accent-german-words-replace-36 + accent-german-words-37: accent-german-words-replace-37 + accent-german-words-38: accent-german-words-replace-38 + accent-german-words-38-2: accent-german-words-replace-38 + accent-german-words-39: accent-german-words-replace-39 + accent-german-words-40: accent-german-words-replace-40 + accent-german-words-41: accent-german-words-replace-41 + accent-german-words-42: accent-german-words-replace-42 + accent-german-words-43: accent-german-words-replace-43 + accent-german-words-44: accent-german-words-replace-44 + accent-german-words-45: accent-german-words-replace-45 + accent-german-words-46: accent-german-words-replace-46 + accent-german-words-47: accent-german-words-replace-47 + accent-german-words-47-2: accent-german-words-replace-47 + accent-german-words-48: accent-german-words-replace-48 + accent-german-words-49: accent-german-words-replace-49 + accent-german-words-50: accent-german-words-replace-50 + accent-german-words-51: accent-german-words-replace-51 + accent-german-words-52: accent-german-words-replace-52 + accent-german-words-53: accent-german-words-replace-53 + accent-german-words-53-2: accent-german-words-replace-53 + accent-german-words-54: accent-german-words-replace-54 + accent-german-words-55: accent-german-words-replace-55 + accent-german-words-56: accent-german-words-replace-56 + accent-german-words-56-2: accent-german-words-replace-56 + accent-german-words-56-3: accent-german-words-replace-56 + accent-german-words-57: accent-german-words-replace-57 + accent-german-words-57-2: accent-german-words-replace-57 + accent-german-words-58: accent-german-words-replace-58 + accent-german-words-59: accent-german-words-replace-59 + accent-german-words-60: accent-german-words-replace-60 + accent-german-words-61: accent-german-words-replace-61 + accent-german-words-61-2: accent-german-words-replace-61 + accent-german-words-61-3: accent-german-words-replace-61 + accent-german-words-61-4: accent-german-words-replace-61 + accent-german-words-62: accent-german-words-replace-62 + +- type: accent + id: russian + wordReplacements: + accent-russian-words-1: accent-russian-words-replace-1 + accent-russian-words-2: accent-russian-words-replace-2 + accent-russian-words-3: accent-russian-words-replace-3 + accent-russian-words-3-2: accent-russian-words-replace-3 + accent-russian-words-3-3: accent-russian-words-replace-3 + accent-russian-words-4: accent-russian-words-replace-4 + accent-russian-words-5: accent-russian-words-replace-5 + accent-russian-words-6: accent-russian-words-replace-6 diff --git a/Resources/Prototypes/Traits/neutral.yml b/Resources/Prototypes/Traits/neutral.yml index a13e8ee10e5..d49bc03a8e2 100644 --- a/Resources/Prototypes/Traits/neutral.yml +++ b/Resources/Prototypes/Traits/neutral.yml @@ -41,6 +41,61 @@ - !type:TraitAddComponent components: - type: SouthernAccent + +- type: trait + id: GermanAccent + category: TraitsSpeechAccents + requirements: + - !type:CharacterItemGroupRequirement + group: TraitsAccents + functions: + - !type:TraitAddComponent + components: + - type: GermanAccent + +- type: trait + id: RussianAccent + category: TraitsSpeechAccents + requirements: + - !type:CharacterItemGroupRequirement + group: TraitsAccents + functions: + - !type:TraitAddComponent + components: + - type: RussianAccent + +- type: trait + id: FrenchAccent + category: TraitsSpeechAccents + requirements: + - !type:CharacterItemGroupRequirement + group: TraitsAccents + functions: + - !type:TraitAddComponent + components: + - type: FrenchAccent + +- type: trait + id: ItalianAccent + category: TraitsSpeechAccents + requirements: + - !type:CharacterItemGroupRequirement + group: TraitsAccents + functions: + - !type:TraitAddComponent + components: + - type: MobsterAccent + +- type: trait + id: SpanishAccent + category: TraitsSpeechAccents + requirements: + - !type:CharacterItemGroupRequirement + group: TraitsAccents + functions: + - !type:TraitAddComponent + components: + - type: SpanishAccent - type: trait id: SkeletonAccent