Scale lesson gain by warmth the same way hunger already did.

The bar was live and drove dressing; a frozen pupil in class still learned as if it were May.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 09:06:50 +03:00
co-authored by Cursor
parent aaf539cacc
commit 274814aecd
10 changed files with 117 additions and 24 deletions
+5 -4
View File
@@ -3,9 +3,8 @@ using HSchool.Content;
namespace HSchool.Ai;
/// <summary>
/// How much a lesson adds to one skill this step. Hungry learns worse; trait offsets and the
/// teacher's subject skill scale the rate. The world stores the running total — this is just
/// the number.
/// How much a lesson adds to one skill this step. Hungry or cold learns worse; trait offsets and
/// the teacher's subject skill scale the rate. Missing warmth is treated as 1.
/// </summary>
public static class LessonLearning
{
@@ -54,13 +53,15 @@ public static class LessonLearning
float hours,
float hunger,
int traitOffset,
float teacherSkill)
float teacherSkill,
float warmth = 1f)
{
ArgumentNullException.ThrowIfNull(skill);
var delta = share
* lessonSkillPerHour
* hours
* NeedFactor(hunger)
* NeedFactor(warmth)
* TraitFactor(traitOffset)
* TeacherFactor(teacherSkill);
return Math.Clamp(current + delta, skill.Range.Min, skill.Range.Max);
@@ -192,5 +192,6 @@
"ApparelReplaced": "got a new {0}",
"ApparelChanged": "changed clothes: {0}",
"LessonNoTeacher": "lesson without a teacher: {0}",
"LessonCold": "too cold in class: {0}",
"core": "Core",
}
@@ -192,5 +192,6 @@
"ApparelReplaced": "получил новую {0}",
"ApparelChanged": "переоделся: {0}",
"LessonNoTeacher": "урок без учителя: {0}",
"LessonCold": "замёрз на уроке: {0}",
"core": "Базовая игра",
}
@@ -84,6 +84,12 @@ internal static class LessonLearningSystem
}
var hunger = needs.Values.GetValueOrDefault("Hunger", 1f);
var warmth = needs.Values.GetValueOrDefault("Warmth", 1f);
if (warmth < rules.NeedThreshold)
{
school.TryLogLessonOnce(personId, PersonLogTypes.LessonCold, lesson.Subject);
}
IReadOnlyDictionary<string, float> taught = teacherSkills.TryGetValue(lesson.TeacherId, out var found)
? found
: new Dictionary<string, float>(StringComparer.Ordinal);
@@ -108,7 +114,8 @@ internal static class LessonLearningSystem
hours,
hunger,
TraitOffset(catalog, traits, share.Skill),
teacherSkill);
teacherSkill,
warmth);
}
});
}
+7 -2
View File
@@ -15,6 +15,7 @@ public static class PersonLogTypes
public const string ApparelReplaced = "apparel-replaced";
public const string ApparelChanged = "apparel-changed";
public const string LessonNoTeacher = "lesson-no-teacher";
public const string LessonCold = "lesson-cold";
}
/// <summary>
@@ -59,12 +60,16 @@ public sealed record PersonLogEvent(string PersonId, DateTime Time, string Type,
return string.Format(CultureInfo.InvariantCulture, catalog.Text(locale, key), name);
}
if (Type.Equals(PersonLogTypes.LessonNoTeacher, StringComparison.Ordinal))
if (Type.Equals(PersonLogTypes.LessonNoTeacher, StringComparison.Ordinal)
|| Type.Equals(PersonLogTypes.LessonCold, StringComparison.Ordinal))
{
var name = catalog.Subjects.TryGetValue(ThingDef, out var subject)
? catalog.Label(locale, subject)
: ThingDef;
return string.Format(CultureInfo.InvariantCulture, catalog.Text(locale, "LessonNoTeacher"), name);
var key = Type.Equals(PersonLogTypes.LessonCold, StringComparison.Ordinal)
? "LessonCold"
: "LessonNoTeacher";
return string.Format(CultureInfo.InvariantCulture, catalog.Text(locale, key), name);
}
return Type;