Slavic Accent character trait (#5264)
* port slavic accent * change some replacements * bobr * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * eliminate redundant regex * bozhe moy * order matters * Merge branch 'master' into slavicAccent Signed-off-by: zelezniciar1 <39102800+zelezniciar1@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review Co-authored-by: Tobias Berger <toby@tobot.dev> Signed-off-by: zelezniciar1 <39102800+zelezniciar1@users.noreply.github.com> * Update Content.Server/_DV/Speech/EntitySystems/SlavicAccentSystem.cs Co-authored-by: BarryNorfolk <barrynorfolkman@protonmail.com> Signed-off-by: zelezniciar1 <39102800+zelezniciar1@users.noreply.github.com> * tryfix * Merge branch 'slavicAccent' of https://github.com/zelezniciar1/Delta-v into slavicAccent
This commit is contained in:
parent
c4d8441791
commit
22b3945a86
|
|
@ -0,0 +1,17 @@
|
|||
namespace Content.Server.Speech.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class SlavicAccentComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The chance (0.0 to 1.0) that articles like "the", "a", "an" will be removed from sentences, default is 80%.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float ArticleRemovalChance = 0.8f;
|
||||
|
||||
/// <summary>
|
||||
/// The chance (0.0 to 1.0) that "tovarisch" will be replaced with "komrade" (comrade) instead, default is 20%.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float KomradeReplacementChance = 0.2f;
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using Content.Server.Speech.Components;
|
||||
using Content.Shared.Speech;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Speech.EntitySystems;
|
||||
|
||||
public sealed class SlavicAccentSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
// Sound replacement regexes
|
||||
private static readonly Regex ThToZVowelRegex = new(@"\bTh(?=[aeiou])", RegexOptions.Compiled);
|
||||
private static readonly Regex ThToZWordsRegex = new(@"Th(?=at|is|ese|ose|ey|em|an)", RegexOptions.Compiled);
|
||||
private static readonly Regex AllCapsThToZVowelRegex = new(@"\bTH(?=[AEIOU])", RegexOptions.Compiled);
|
||||
private static readonly Regex AllCapsThToZWordsRegex = new(@"TH(?=AT|IS|ESE|OSE|EY|EM|AN)", RegexOptions.Compiled);
|
||||
private static readonly Regex LowercaseThToZVowelRegex = new(@"\bth(?=[aeiou])", RegexOptions.Compiled);
|
||||
private static readonly Regex LowercaseThToZWordsRegex = new(@"th(?=at|is|ese|ose|ey|em|an)", RegexOptions.Compiled);
|
||||
private static readonly Regex CToKCapitalRegex = new(@"\bC", RegexOptions.Compiled);
|
||||
private static readonly Regex CToKLowercaseRegex = new(@"\bc", RegexOptions.Compiled);
|
||||
private static readonly Regex WToVCapitalRegex = new(@"\bW", RegexOptions.Compiled);
|
||||
private static readonly Regex WToVLowercaseRegex = new(@"\bw", RegexOptions.Compiled);
|
||||
private static readonly Regex DentalTInVowelsRegex = new(@"(?<=[aeiouAEIOU])t(?=[aeiouAEIOU])", RegexOptions.Compiled);
|
||||
private static readonly Regex EeRegex = new(@"ee", RegexOptions.Compiled);
|
||||
|
||||
// Grammar replacement regexes
|
||||
private static readonly Regex TheLowercaseRegex = new(@"\bthe\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex ALowercaseRegex = new(@"\ba\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex AnLowercaseRegex = new(@"\ban\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex IsLowercaseRegex = new(@"\bis\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex AreLowercaseRegex = new(@"\bare\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex IAmLowercaseRegex = new(@"\bI am\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
private static readonly Regex WhitespaceRegex = new(@" +", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex TovarischRegex = new(@"\btovarisch\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<SlavicAccentComponent, AccentGetEvent>(OnAccent);
|
||||
}
|
||||
|
||||
// Applies Slavic accent to a message
|
||||
public string Accentuate(string message, SlavicAccentComponent component)
|
||||
{
|
||||
var accentedMessage = _replacement.ApplyReplacements(message, "slavic");
|
||||
accentedMessage = ApplyKomradeReplacement(accentedMessage, component);
|
||||
accentedMessage = ApplyGrammarRules(accentedMessage, component);
|
||||
accentedMessage = ApplySoundReplacements(accentedMessage);
|
||||
return accentedMessage;
|
||||
}
|
||||
|
||||
// Randomly replaces 'tovarisch' with 'Komrade' while preserving capitalization.
|
||||
// TODO: The ReplacementAccentSystem REALLY should have random replacements built-in.
|
||||
private string ApplyKomradeReplacement(string message, SlavicAccentComponent component)
|
||||
{
|
||||
return TovarischRegex.Replace(message, match =>
|
||||
{
|
||||
if (!_random.Prob(component.KomradeReplacementChance))
|
||||
return match.Value;
|
||||
var original = match.Value;
|
||||
if (IsAllUpperCase(original))
|
||||
return "KOMRADE";
|
||||
if (IsCapitalized(original))
|
||||
return "Komrade";
|
||||
return "komrade";
|
||||
});
|
||||
}
|
||||
|
||||
private static bool IsAllUpperCase(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return false;
|
||||
foreach (var c in text)
|
||||
if (char.IsLetter(c) && !char.IsUpper(c)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsCapitalized(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text) || !char.IsLetter(text[0])) return false;
|
||||
if (!char.IsUpper(text[0])) return false;
|
||||
for (int i = 1; i < text.Length; i++)
|
||||
if (char.IsLetter(text[i]) && !char.IsLower(text[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies sound-level replacements to simulate Slavic accent phonetics.
|
||||
/// </summary>
|
||||
private static string ApplySoundReplacements(string message)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
return message;
|
||||
|
||||
var result = message;
|
||||
|
||||
// Apply TH replacements (grouped by case)
|
||||
result = ThToZVowelRegex.Replace(result, "Z");
|
||||
result = ThToZWordsRegex.Replace(result, "Z");
|
||||
result = AllCapsThToZVowelRegex.Replace(result, "Z");
|
||||
result = AllCapsThToZWordsRegex.Replace(result, "Z");
|
||||
result = LowercaseThToZVowelRegex.Replace(result, "z");
|
||||
result = LowercaseThToZWordsRegex.Replace(result, "z");
|
||||
|
||||
// Apply other consonant replacements
|
||||
result = CToKCapitalRegex.Replace(result, "K");
|
||||
result = CToKLowercaseRegex.Replace(result, "k");
|
||||
result = WToVCapitalRegex.Replace(result, "V");
|
||||
result = WToVLowercaseRegex.Replace(result, "v");
|
||||
|
||||
// Apply vowel and other sound changes
|
||||
result = DentalTInVowelsRegex.Replace(result, "th");
|
||||
result = EeRegex.Replace(result, "i");
|
||||
|
||||
// Restore capitalization
|
||||
if (result.Length > 0 && message.Length > 0 &&
|
||||
char.IsLetter(message[0]) && char.IsLower(result[0]) && char.IsUpper(message[0]))
|
||||
{
|
||||
result = char.ToUpper(result[0]) + result[1..];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Applies grammar rules typical of Slavic-accented English, such as article and verb removal.
|
||||
private string ApplyGrammarRules(string message, SlavicAccentComponent component)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
return message;
|
||||
|
||||
var wasFirstLetterCapitalized = char.IsUpper(message[0]);
|
||||
|
||||
// Early exit if its not long enough
|
||||
var wordCount = message.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
|
||||
if (wordCount <= 3)
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
// Instead of checking per word we're just gonna check for the whole message.
|
||||
if (!_random.Prob(component.ArticleRemovalChance))
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
var result = message;
|
||||
|
||||
// If a message starts with any of these we remove em if ArticalRemovalChance passes. This is more optimized than doing a regex check.
|
||||
if (result.StartsWith("The ", StringComparison.Ordinal))
|
||||
result = result.Substring(4);
|
||||
else if (result.StartsWith("THE ", StringComparison.Ordinal))
|
||||
result = result.Substring(4);
|
||||
else if (result.StartsWith("A ", StringComparison.Ordinal))
|
||||
result = result.Substring(2);
|
||||
else if (result.StartsWith("An ", StringComparison.Ordinal))
|
||||
result = result.Substring(3);
|
||||
else
|
||||
{
|
||||
// Apply regex replacements for articles elsewhere in the message
|
||||
result = TheLowercaseRegex.Replace(result, "");
|
||||
result = ALowercaseRegex.Replace(result, "");
|
||||
result = AnLowercaseRegex.Replace(result, "");
|
||||
}
|
||||
|
||||
// Remove verbs
|
||||
result = IsLowercaseRegex.Replace(result, "");
|
||||
result = AreLowercaseRegex.Replace(result, "");
|
||||
|
||||
// Simplify "I am" to "I"
|
||||
result = IAmLowercaseRegex.Replace(result, "I");
|
||||
|
||||
// Clean up whitespace
|
||||
result = WhitespaceRegex.Replace(result.Trim(), " ");
|
||||
|
||||
// Restore capitalization
|
||||
if (wasFirstLetterCapitalized && !string.IsNullOrEmpty(result) && char.IsLetter(result[0]) && char.IsLower(result[0]))
|
||||
{
|
||||
result = char.ToUpper(result[0]) + result.Substring(1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void OnAccent(Entity<SlavicAccentComponent> entity, ref AccentGetEvent args)
|
||||
{
|
||||
args.Message = Accentuate(args.Message, entity.Comp);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
accent-slavic-words-1 = yes
|
||||
accent-slavic-words-replace-1 = da
|
||||
|
||||
accent-slavic-words-2 = no
|
||||
accent-slavic-words-replace-2 = nyet
|
||||
|
||||
accent-slavic-words-3 = grandma
|
||||
accent-slavic-words-3-2 = grandmother
|
||||
accent-slavic-words-3-3 = granny
|
||||
accent-slavic-words-replace-3 = babushka
|
||||
|
||||
accent-slavic-words-4 = grandfather
|
||||
accent-slavic-words-4-2 = grandpa
|
||||
accent-slavic-words-4-3 = gramps
|
||||
accent-slavic-words-replace-4 = dedushka
|
||||
|
||||
accent-slavic-words-5 = friend
|
||||
accent-slavic-words-5-2 = buddy
|
||||
accent-slavic-words-replace-5 = tovarisch
|
||||
|
||||
accent-slavic-words-6 = idiot
|
||||
accent-slavic-words-6-2 = fool
|
||||
accent-slavic-words-replace-6 = durak
|
||||
|
||||
accent-slavic-words-7 = idiots
|
||||
accent-slavic-words-7-2 = fools
|
||||
accent-slavic-words-replace-7 = duraki
|
||||
|
||||
accent-slavic-words-8 = friends
|
||||
accent-slavic-words-replace-8 = tovarisch
|
||||
|
||||
accent-slavic-words-9 = cheers
|
||||
accent-slavic-words-replace-9 = na zdorovje
|
||||
|
||||
accent-slavic-words-10 = damn
|
||||
accent-slavic-words-10-2 = dammit
|
||||
accent-slavic-words-replace-10 = blin
|
||||
|
||||
accent-slavic-words-11 = shit
|
||||
accent-slavic-words-replace-11 = blyat
|
||||
|
||||
accent-slavic-words-12 = hello
|
||||
accent-slavic-words-replace-12 = privet
|
||||
|
||||
accent-slavic-words-13 = goodbye
|
||||
accent-slavic-words-replace-13 = do svidaniya
|
||||
|
||||
accent-slavic-words-14 = thank you
|
||||
accent-slavic-words-14-2 = thanks
|
||||
accent-slavic-words-replace-14 = spasibo
|
||||
|
||||
accent-slavic-words-15 = good
|
||||
accent-slavic-words-replace-15 = dobro
|
||||
|
||||
accent-slavic-words-16 = fuck
|
||||
accent-slavic-words-16-2 = bitch
|
||||
accent-slavic-words-replace-16 = kurwa
|
||||
|
||||
accent-slavic-words-17 = beautiful
|
||||
accent-slavic-words-replace-17 = krasivaya
|
||||
|
||||
accent-slavic-words-18 = goddammit
|
||||
accent-slavic-words-18-2 = fucking hell
|
||||
accent-slavic-words-18-3 = shit fuck
|
||||
accent-slavic-words-18-4 = what the fuck
|
||||
accent-slavic-words-18-5 = motherfucker
|
||||
accent-slavic-words-18-6 = son of a bitch
|
||||
accent-slavic-words-replace-18 = cyka blyat
|
||||
|
||||
accent-slavic-words-19 = oh my god
|
||||
accent-slavic-words-19-2 = oh my
|
||||
accent-slavic-words-19-3 = my god
|
||||
accent-slavic-words-replace-19 = bozhe moy
|
||||
|
||||
accent-slavic-words-20 = oh no
|
||||
accent-slavic-words-20-2 = uh oh
|
||||
accent-slavic-words-replace-20 = oy blin
|
||||
|
||||
accent-slavic-words-21 = coffee
|
||||
accent-slavic-words-replace-21 = kofye
|
||||
|
||||
accent-slavic-words-22 = tea
|
||||
accent-slavic-words-replace-22 = chai
|
||||
|
||||
accent-slavic-words-23 = mom
|
||||
accent-slavic-words-23-2 = mother
|
||||
accent-slavic-words-replace-23 = mama
|
||||
|
||||
accent-slavic-words-24 = dad
|
||||
accent-slavic-words-24-2 = father
|
||||
accent-slavic-words-replace-24 = papa
|
||||
|
||||
accent-slavic-words-25 = bye
|
||||
accent-slavic-words-replace-25 = ciao
|
||||
|
||||
accent-slavic-words-26 = small
|
||||
accent-slavic-words-replace-26 = maly
|
||||
|
||||
accent-slavic-words-27 = big
|
||||
accent-slavic-words-27-2 = large
|
||||
accent-slavic-words-replace-27 = veliky
|
||||
|
|
@ -67,3 +67,6 @@ trait-anglish-desc = Your tung is of the Saxons, and say unlike others aboard th
|
|||
|
||||
trait-protected-name = Marked as Protected
|
||||
trait-protected-desc = Due to your position, value, or circumstances, your survival is considered preferable. You won't be targeted by kill objectives.
|
||||
|
||||
trait-slavic-name = Slavic accent
|
||||
trait-slavic-desc = You kome from ze East, and speak vith strong Slavic accent!
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
- UltraVision
|
||||
- Unborgable
|
||||
- AnglishAccent
|
||||
- SlavicAccent
|
||||
# End DeltaV Additions
|
||||
blacklist:
|
||||
components:
|
||||
|
|
|
|||
|
|
@ -1564,3 +1564,56 @@
|
|||
accent-anglish-words-1165: accent-anglish-replacement-1165
|
||||
accent-anglish-words-1166: accent-anglish-replacement-1166
|
||||
accent-anglish-words-1167: accent-anglish-replacement-1167
|
||||
|
||||
#Slavic Accent
|
||||
- type: accent
|
||||
id: slavic
|
||||
wordReplacements:
|
||||
accent-slavic-words-1: accent-slavic-words-replace-1
|
||||
accent-slavic-words-2: accent-slavic-words-replace-2
|
||||
accent-slavic-words-3: accent-slavic-words-replace-3
|
||||
accent-slavic-words-3-2: accent-slavic-words-replace-3
|
||||
accent-slavic-words-3-3: accent-slavic-words-replace-3
|
||||
accent-slavic-words-4: accent-slavic-words-replace-4
|
||||
accent-slavic-words-4-2: accent-slavic-words-replace-4
|
||||
accent-slavic-words-4-3: accent-slavic-words-replace-4
|
||||
accent-slavic-words-5: accent-slavic-words-replace-5
|
||||
accent-slavic-words-5-2: accent-slavic-words-replace-5
|
||||
accent-slavic-words-6: accent-slavic-words-replace-6
|
||||
accent-slavic-words-6-2: accent-slavic-words-replace-6
|
||||
accent-slavic-words-7: accent-slavic-words-replace-7
|
||||
accent-slavic-words-7-2: accent-slavic-words-replace-7
|
||||
accent-slavic-words-8: accent-slavic-words-replace-8
|
||||
accent-slavic-words-9: accent-slavic-words-replace-9
|
||||
accent-slavic-words-10: accent-slavic-words-replace-10
|
||||
accent-slavic-words-10-2: accent-slavic-words-replace-10
|
||||
accent-slavic-words-11: accent-slavic-words-replace-11
|
||||
accent-slavic-words-12: accent-slavic-words-replace-12
|
||||
accent-slavic-words-13: accent-slavic-words-replace-13
|
||||
accent-slavic-words-14: accent-slavic-words-replace-14
|
||||
accent-slavic-words-14-2: accent-slavic-words-replace-14
|
||||
accent-slavic-words-15: accent-slavic-words-replace-15
|
||||
accent-slavic-words-16: accent-slavic-words-replace-16
|
||||
accent-slavic-words-16-2: accent-slavic-words-replace-16
|
||||
accent-slavic-words-17: accent-slavic-words-replace-17
|
||||
accent-slavic-words-18: accent-slavic-words-replace-18
|
||||
accent-slavic-words-18-2: accent-slavic-words-replace-18
|
||||
accent-slavic-words-18-3: accent-slavic-words-replace-18
|
||||
accent-slavic-words-18-4: accent-slavic-words-replace-18
|
||||
accent-slavic-words-18-5: accent-slavic-words-replace-18
|
||||
accent-slavic-words-18-6: accent-slavic-words-replace-18
|
||||
accent-slavic-words-19: accent-slavic-words-replace-19
|
||||
accent-slavic-words-19-2: accent-slavic-words-replace-19
|
||||
accent-slavic-words-19-3: accent-slavic-words-replace-19
|
||||
accent-slavic-words-20: accent-slavic-words-replace-20
|
||||
accent-slavic-words-20-2: accent-slavic-words-replace-20
|
||||
accent-slavic-words-21: accent-slavic-words-replace-21
|
||||
accent-slavic-words-22: accent-slavic-words-replace-22
|
||||
accent-slavic-words-23: accent-slavic-words-replace-23
|
||||
accent-slavic-words-23-2: accent-slavic-words-replace-23
|
||||
accent-slavic-words-24: accent-slavic-words-replace-24
|
||||
accent-slavic-words-24-2: accent-slavic-words-replace-24
|
||||
accent-slavic-words-25: accent-slavic-words-replace-25
|
||||
accent-slavic-words-26: accent-slavic-words-replace-26
|
||||
accent-slavic-words-27: accent-slavic-words-replace-27
|
||||
accent-slavic-words-27-2: accent-slavic-words-replace-27
|
||||
|
|
|
|||
|
|
@ -185,3 +185,14 @@
|
|||
- !type:AddCompsEffect
|
||||
components:
|
||||
- type: AnglishAccent
|
||||
|
||||
- type: trait
|
||||
id: SlavicAccent
|
||||
name: trait-slavic-name
|
||||
description: trait-slavic-desc
|
||||
category: Accents
|
||||
cost: 2
|
||||
effects:
|
||||
- !type:AddCompsEffect
|
||||
components:
|
||||
- type: SlavicAccent
|
||||
|
|
|
|||
Loading…
Reference in New Issue