diff --git a/Content.Server/Speech/Components/GermanAccentComponent.cs b/Content.Server/Speech/Components/GermanAccentComponent.cs new file mode 100644 index 0000000000..4f387d1e01 --- /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 0000000000..1973d38afb --- /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/Resources/Locale/en-US/accent/german.ftl b/Resources/Locale/en-US/accent/german.ftl new file mode 100644 index 0000000000..ccb57ba714 --- /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/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl index d9f09cc68a..8e3b189216 100644 --- a/Resources/Locale/en-US/traits/traits.ftl +++ b/Resources/Locale/en-US/traits/traits.ftl @@ -48,5 +48,8 @@ trait-liar-desc = You can hardly bring yourself to tell the truth. Sometimes you trait-cowboy-name = Cowboy accent trait-cowboy-desc = You speak with a distinct cowboy accent! +trait-german-name = German accent +trait-german-desc = You seem to come from space Germany. + trait-italian-name = Italian accent -trait-italian-desc = Mamma mia! You seem to have lived in space italy! +trait-italian-desc = Mamma mia! You seem to have lived in space Italy! diff --git a/Resources/Prototypes/Accents/word_replacements.yml b/Resources/Prototypes/Accents/word_replacements.yml index ae42d67da8..b93c2cfd5c 100644 --- a/Resources/Prototypes/Accents/word_replacements.yml +++ b/Resources/Prototypes/Accents/word_replacements.yml @@ -486,6 +486,85 @@ liar-word-41: liar-word-replacement-41 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: @@ -496,4 +575,4 @@ 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 \ No newline at end of file + accent-russian-words-6: accent-russian-words-replace-6 diff --git a/Resources/Prototypes/Traits/speech.yml b/Resources/Prototypes/Traits/speech.yml index 961a53023b..e5869a4afc 100644 --- a/Resources/Prototypes/Traits/speech.yml +++ b/Resources/Prototypes/Traits/speech.yml @@ -23,7 +23,7 @@ category: SpeechTraits cost: 1 components: - - type: SouthernAccent + - type: SouthernAccent - type: trait id: PirateAccent @@ -32,7 +32,7 @@ category: SpeechTraits cost: 1 components: - - type: PirateAccent + - type: PirateAccent - type: trait id: CowboyAccent @@ -41,8 +41,17 @@ category: SpeechTraits cost: 1 components: - - type: ReplacementAccent - accent: cowboy + - type: ReplacementAccent + accent: cowboy + +- type: trait + id: GermanAccent + name: trait-german-name + description: trait-german-desc + category: SpeechTraits + cost: 1 + components: + - type: GermanAccent - type: trait id: ItalianAccent @@ -51,8 +60,8 @@ category: SpeechTraits cost: 1 components: - - type: ReplacementAccent - accent: italian + - type: ReplacementAccent + accent: italian - type: trait id: Liar @@ -61,8 +70,8 @@ category: SpeechTraits cost: 1 components: - - type: ReplacementAccent - accent: liar + - type: ReplacementAccent + accent: liar # 2 Cost @@ -73,11 +82,11 @@ category: SpeechTraits cost: 2 components: - - type: StutteringAccent - matchRandomProb: 0.1 - fourRandomProb: 0 - threeRandomProb: 0 - cutRandomProb: 0 + - type: StutteringAccent + matchRandomProb: 0.1 + fourRandomProb: 0 + threeRandomProb: 0 + cutRandomProb: 0 - type: trait id: FrontalLisp @@ -86,4 +95,4 @@ category: SpeechTraits cost: 2 components: - - type: FrontalLisp + - type: FrontalLisp