Enhance school creation and staffing management with native language support
- Updated protocol documentation to include `nativeLanguages` in `nameSets` and added `nativeLanguage` to school creation options. - Enhanced the UI for school creation to allow selection of native languages, improving user experience. - Revised API interfaces to accommodate new native language features, ensuring proper data handling. - Improved localization strings to support new native language functionalities in both English and Russian. - Updated tests to validate the new native language features and ensure robust functionality in staffing scenarios.
This commit is contained in:
@@ -26,7 +26,7 @@ internal static class PeopleDefValidator
|
||||
|
||||
foreach (var names in catalog.NameSets.Values)
|
||||
{
|
||||
ValidateNameSet(names);
|
||||
ValidateNameSet(names, catalog);
|
||||
}
|
||||
|
||||
foreach (var subject in catalog.Subjects.Values)
|
||||
@@ -171,6 +171,11 @@ internal static class PeopleDefValidator
|
||||
throw new ContentLoadException($"SkillDef '{skill.DefName}' has a negative stdDev.");
|
||||
}
|
||||
|
||||
if (skill.AdultChance is < 0 or > 1)
|
||||
{
|
||||
throw new ContentLoadException($"SkillDef '{skill.DefName}' adultChance must be 0–1.");
|
||||
}
|
||||
|
||||
foreach (var limit in skill.BodyLimits)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(limit.Attribute))
|
||||
@@ -500,13 +505,41 @@ internal static class PeopleDefValidator
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateNameSet(NameSetDef names)
|
||||
private static void ValidateNameSet(NameSetDef names, DefCatalog catalog)
|
||||
{
|
||||
if (!NameGrammar.IsKnownPatronymic(names.PatronymicRule))
|
||||
{
|
||||
throw new ContentLoadException($"NameSetDef '{names.DefName}' has unknown patronymicRule '{names.PatronymicRule}'.");
|
||||
}
|
||||
|
||||
foreach (var native in names.Spoken)
|
||||
{
|
||||
if (!catalog.Skills.TryGetValue(native, out var language) || language.Abstract)
|
||||
{
|
||||
throw new ContentLoadException($"NameSetDef '{names.DefName}' native language '{native}' is not a SkillDef.");
|
||||
}
|
||||
}
|
||||
|
||||
if (names.RelatedLanguageChance is < 0 or > 1)
|
||||
{
|
||||
throw new ContentLoadException($"NameSetDef '{names.DefName}' relatedLanguageChance must be 0–1.");
|
||||
}
|
||||
|
||||
if (names.RelatedLanguageStdDev < 0)
|
||||
{
|
||||
throw new ContentLoadException($"NameSetDef '{names.DefName}' relatedLanguageStdDev must not be negative.");
|
||||
}
|
||||
|
||||
if (names.RelatedLanguageMean < 0)
|
||||
{
|
||||
throw new ContentLoadException($"NameSetDef '{names.DefName}' relatedLanguageMean must not be negative.");
|
||||
}
|
||||
|
||||
if (names.RelatedLanguageMax < 0)
|
||||
{
|
||||
throw new ContentLoadException($"NameSetDef '{names.DefName}' relatedLanguageMax must not be negative.");
|
||||
}
|
||||
|
||||
if (!NameGrammar.IsKnownGiven(names.DefaultGivenDeclension))
|
||||
{
|
||||
throw new ContentLoadException($"NameSetDef '{names.DefName}' has unknown defaultGivenDeclension.");
|
||||
|
||||
@@ -120,6 +120,18 @@ public sealed class SkillDef : Def
|
||||
public IReadOnlyList<AgeMeanPoint> AgeMeans { get; init; } = [];
|
||||
|
||||
public IReadOnlyList<BodySkillLimit> BodyLimits { get; init; } = [];
|
||||
|
||||
/// <summary>Everyone has this: body, speech, the floor under a profession.</summary>
|
||||
public bool Always { get; init; }
|
||||
|
||||
/// <summary>Adult extras: cook, nurse, secretary. Not rolled for pupils.</summary>
|
||||
public bool Work { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Probability that an adult also has this, on top of the native language. 0 means never
|
||||
/// by chance — pupils still get it when a subject of their year points here.
|
||||
/// </summary>
|
||||
public float AdultChance { get; init; }
|
||||
}
|
||||
|
||||
public sealed class SubjectSkillShare
|
||||
@@ -338,6 +350,34 @@ public sealed class NameSetDef : Def
|
||||
|
||||
public string DefaultSurnameDeclension { get; init; } = NameGrammar.Ov;
|
||||
|
||||
/// <summary>
|
||||
/// Languages this set can speak natively. Slavic names cover Russian, Belarusian and
|
||||
/// Ukrainian; the school picks one at create. Singular <see cref="NativeLanguage"/> is still
|
||||
/// accepted in JSONC for a one-language pack.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> NativeLanguages { get; init; } = [];
|
||||
|
||||
/// <summary>One-language form. Folded into <see cref="Spoken"/> when the list is empty.</summary>
|
||||
public string? NativeLanguage { get; init; }
|
||||
|
||||
public IReadOnlyList<string> Spoken =>
|
||||
NativeLanguages.Count > 0
|
||||
? NativeLanguages
|
||||
: string.IsNullOrWhiteSpace(NativeLanguage) ? [] : [NativeLanguage];
|
||||
|
||||
/// <summary>
|
||||
/// Chance each other language in <see cref="Spoken"/> is present at a low level — a Russian
|
||||
/// speaker who understands Belarusian. 0 leaves relatives off the card.
|
||||
/// </summary>
|
||||
public float RelatedLanguageChance { get; init; }
|
||||
|
||||
public float RelatedLanguageMean { get; init; } = 22f;
|
||||
|
||||
public float RelatedLanguageStdDev { get; init; } = 8f;
|
||||
|
||||
/// <summary>Cap so a related roll cannot look like a native speaker.</summary>
|
||||
public int RelatedLanguageMax { get; init; } = 40;
|
||||
|
||||
public IReadOnlyList<GivenNameEntry> MaleGiven { get; init; } = [];
|
||||
|
||||
public IReadOnlyList<GivenNameEntry> FemaleGiven { get; init; } = [];
|
||||
|
||||
Reference in New Issue
Block a user