Wire grade trail notices, dress mark factor, and truancy summons weights.

Lesson multipliers stay explicit in tests; poor marks and unexcused absences toast and may auto-summon, while illness stays excused.
This commit is contained in:
Leonid Pershin
2026-08-21 14:18:41 +03:00
parent 975ca4936e
commit 59a7023bc4
23 changed files with 762 additions and 13 deletions
+1
View File
@@ -17,6 +17,7 @@ internal static class EventDefValidator
EventTriggers.DirectorSummon,
EventTriggers.ParentMeeting,
EventTriggers.DiseaseOutbreak,
EventTriggers.PoorGradeTrail,
};
private static readonly HashSet<string> Actions = new(StringComparer.Ordinal)
+3
View File
@@ -15,6 +15,9 @@ public static class EventTriggers
public const string DirectorSummon = "directorSummon";
public const string ParentMeeting = "parentMeeting";
public const string DiseaseOutbreak = "diseaseOutbreak";
/// <summary>Bad recent marks and/or truancy trail (slice 13 phase 76).</summary>
public const string PoorGradeTrail = "poorGradeTrail";
}
public static class EventActions
+30
View File
@@ -752,6 +752,36 @@ internal static class PeopleDefValidator
$"BehaviorDef '{behavior.DefName}' lessonLateMinutes cannot be negative.");
}
if (behavior.LessonDressMarkFactor is < 0f or > 1f)
{
throw new ContentLoadException(
$"BehaviorDef '{behavior.DefName}' lessonDressMarkFactor must be 01.");
}
if (behavior.PoorMarkTrailMaxAverage is < 0f or > 5f)
{
throw new ContentLoadException(
$"BehaviorDef '{behavior.DefName}' poorMarkTrailMaxAverage must be 05.");
}
if (behavior.PoorMarkTrailMinMarks < 0)
{
throw new ContentLoadException(
$"BehaviorDef '{behavior.DefName}' poorMarkTrailMinMarks cannot be negative.");
}
if (behavior.TruancyTrailMinCount < 0)
{
throw new ContentLoadException(
$"BehaviorDef '{behavior.DefName}' truancyTrailMinCount cannot be negative.");
}
if (behavior.GradeTrailSummonChance is < 0f or > 1f)
{
throw new ContentLoadException(
$"BehaviorDef '{behavior.DefName}' gradeTrailSummonChance must be 01.");
}
if (behavior.DiseaseVectorScale < 0f)
{
throw new ContentLoadException(
+28
View File
@@ -619,6 +619,7 @@ public sealed class BehaviorDef : Def
"quarrel",
"fight",
"reprimand",
"truancy",
];
/// <summary>
@@ -655,6 +656,33 @@ public sealed class BehaviorDef : Def
/// </summary>
public bool LessonMarkWhenLate { get; init; } = true;
/// <summary>
/// Multiplier on lesson quality when worn dress fails Appropriateness for this lesson.
/// 1 = log only (no mark hit). Vanilla is a light penalty.
/// </summary>
public float LessonDressMarkFactor { get; init; } = 0.95f;
/// <summary>
/// Mean of recent marks at or below this (and at least <see cref="PoorMarkTrailMinMarks"/>)
/// raises a poor-grade-trail notice. Zero disables the mark half of the trail.
/// </summary>
public float PoorMarkTrailMaxAverage { get; init; } = 2.5f;
/// <summary>How many recent marks are required before the average trail can fire. Zero disables.</summary>
public int PoorMarkTrailMinMarks { get; init; } = 3;
/// <summary>
/// Recent unexcused absences (truancy) at or above this raise the trail notice.
/// Zero disables the truancy half.
/// </summary>
public int TruancyTrailMinCount { get; init; } = 2;
/// <summary>
/// Chance to auto-enqueue a director summons when a poor trail first fires today.
/// Slice 12 must be able to start (principal + office); 0 skips the roll.
/// </summary>
public float GradeTrailSummonChance { get; init; } = 0.35f;
/// <summary>
/// Scales DiseaseDef weather/base onset chances. 0 disables natural onset; missing keeps 1.
/// </summary>