Wear worn clothes on campus and replace rags at the work morning.
Condition drops from catalog hours only while the person is at school; skip through the night issues the same fresh set as a lived night so the school does not walk in in rags. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -526,6 +526,18 @@ internal static class PeopleDefValidator
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' optionalApparelChance must be 0–1.");
|
||||
}
|
||||
|
||||
if (behavior.ApparelWearPerHour < 0f)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' apparelWearPerHour cannot be negative.");
|
||||
}
|
||||
|
||||
if (behavior.ApparelReplaceBelow is < 0f or > 1f)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' apparelReplaceBelow must be 0–1.");
|
||||
}
|
||||
|
||||
ValidateConditionBands(behavior);
|
||||
|
||||
// A pack may invert this on purpose — lunch then pulls the class out of the lesson.
|
||||
// The warning is the catch; refusing to load would make the number unmoddable.
|
||||
if (behavior.LunchWeight > behavior.DutyLessonWeight)
|
||||
@@ -535,6 +547,47 @@ internal static class PeopleDefValidator
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateConditionBands(BehaviorDef behavior)
|
||||
{
|
||||
var bands = behavior.ApparelConditionBands;
|
||||
if (bands.Count == 0)
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' apparelConditionBands cannot be empty.");
|
||||
}
|
||||
|
||||
var ids = new HashSet<string>(StringComparer.Ordinal);
|
||||
var sawZero = false;
|
||||
foreach (var band in bands)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(band.Id))
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' apparel condition band is missing an id.");
|
||||
}
|
||||
|
||||
if (band.Min is < 0f or > 1f)
|
||||
{
|
||||
throw new ContentLoadException(
|
||||
$"BehaviorDef '{behavior.DefName}' apparel condition '{band.Id}' min must be 0–1.");
|
||||
}
|
||||
|
||||
if (!ids.Add(band.Id))
|
||||
{
|
||||
throw new ContentLoadException($"BehaviorDef '{behavior.DefName}' repeats apparel condition '{band.Id}'.");
|
||||
}
|
||||
|
||||
if (band.Min == 0f)
|
||||
{
|
||||
sawZero = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sawZero)
|
||||
{
|
||||
throw new ContentLoadException(
|
||||
$"BehaviorDef '{behavior.DefName}' apparelConditionBands must include a min of 0 so rags have a caption.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateHoliday(HolidayDef holiday)
|
||||
{
|
||||
if (holiday.Abstract)
|
||||
|
||||
@@ -262,6 +262,40 @@ public sealed class BehaviorDef : Def
|
||||
|
||||
/// <summary>Chance each optional layer (sweater, coat, hat, accessory) is worn at generation.</summary>
|
||||
public float OptionalApparelChance { get; init; } = 0.4f;
|
||||
|
||||
/// <summary>
|
||||
/// Condition lost per game hour while the thing is worn on campus. Bag, locker and home do
|
||||
/// not wear. The number lives here so a pack can make clothes last a term or a week.
|
||||
/// </summary>
|
||||
public float ApparelWearPerHour { get; init; } = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// Worn apparel below this stays home: morning replacement issues a fresh instance.
|
||||
/// At the threshold they still go out, even when the caption already says torn.
|
||||
/// </summary>
|
||||
public float ApparelReplaceBelow { get; init; } = 0.15f;
|
||||
|
||||
/// <summary>
|
||||
/// Caption bands for a 0–1 condition bar. Highest <see cref="ApparelConditionBand.Min"/>
|
||||
/// the value still meets wins. Empty falls back to <see cref="DefaultConditionBands"/>.
|
||||
/// </summary>
|
||||
public IReadOnlyList<ApparelConditionBand> ApparelConditionBands { get; init; } = DefaultConditionBands;
|
||||
|
||||
public static IReadOnlyList<ApparelConditionBand> DefaultConditionBands { get; } =
|
||||
[
|
||||
new() { Min = 0.75f, Id = "ApparelConditionIntact" },
|
||||
new() { Min = 0.4f, Id = "ApparelConditionWorn" },
|
||||
new() { Min = 0.15f, Id = "ApparelConditionTorn" },
|
||||
new() { Min = 0f, Id = "ApparelConditionRags" },
|
||||
];
|
||||
}
|
||||
|
||||
/// <summary>One caption on the condition bar. <see cref="Id"/> is a locale key, not a Def.</summary>
|
||||
public sealed class ApparelConditionBand
|
||||
{
|
||||
public float Min { get; init; }
|
||||
|
||||
public required string Id { get; init; }
|
||||
}
|
||||
|
||||
public enum BodyAttributeKind
|
||||
|
||||
Reference in New Issue
Block a user