Halve lesson gain when the bag has no textbook for the subject.

Locker and home do not count. A pack without the field keeps vanilla 0.5.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 09:27:46 +03:00
co-authored by Cursor
parent f4a793aca4
commit 1b3479f984
13 changed files with 252 additions and 20 deletions
+29 -3
View File
@@ -1,10 +1,12 @@
using HSchool.Content;
using HSchool.People;
namespace HSchool.Ai;
/// <summary>
/// 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.
/// the teacher's subject skill scale the rate. Missing warmth is treated as 1. A missing textbook
/// uses <see cref="BehaviorDef.LessonNoTextbookFactor"/>.
/// </summary>
public static class LessonLearning
{
@@ -45,6 +47,28 @@ public static class LessonLearning
return count == 0 ? 0f : total / count;
}
/// <summary>
/// True when a bag instance carries this lesson's <see cref="InventoryItem.Subject"/>.
/// Locker and home do not count — the pupil is already in class.
/// </summary>
public static bool HasTextbookInBag(IReadOnlyList<InventoryItem> items, string subject)
{
ArgumentNullException.ThrowIfNull(items);
ArgumentException.ThrowIfNullOrWhiteSpace(subject);
foreach (var item in items)
{
if (item.Location.Equals(ItemLocations.Bag, StringComparison.Ordinal)
&& item.Subject is not null
&& item.Subject.Equals(subject, StringComparison.Ordinal))
{
return true;
}
}
return false;
}
public static float Gain(
float current,
SkillDef skill,
@@ -54,7 +78,8 @@ public static class LessonLearning
float hunger,
int traitOffset,
float teacherSkill,
float warmth = 1f)
float warmth = 1f,
float textbookFactor = 1f)
{
ArgumentNullException.ThrowIfNull(skill);
var delta = share
@@ -63,7 +88,8 @@ public static class LessonLearning
* NeedFactor(hunger)
* NeedFactor(warmth)
* TraitFactor(traitOffset)
* TeacherFactor(teacherSkill);
* TeacherFactor(teacherSkill)
* textbookFactor;
return Math.Clamp(current + delta, skill.Range.Min, skill.Range.Max);
}
}