Empty layers keep furniture on the map; a known layer set and ColorDef palette reject unknown ids at load. Co-authored-by: Cursor <cursoragent@cursor.com>
155 lines
5.0 KiB
C#
155 lines
5.0 KiB
C#
namespace HSchool.Content;
|
||
|
||
public enum DefKind
|
||
{
|
||
Action,
|
||
Thing,
|
||
Position,
|
||
Work,
|
||
Room,
|
||
Building,
|
||
Floor,
|
||
Territory,
|
||
Skill,
|
||
Trait,
|
||
BodyAttribute,
|
||
Need,
|
||
NameSet,
|
||
Subject,
|
||
Staffing,
|
||
DayFrame,
|
||
Holiday,
|
||
Behavior,
|
||
Color,
|
||
}
|
||
|
||
/// <summary>Shared JSONC fields. Kind comes from the folder under <c>defs/</c>, not from the file.</summary>
|
||
public abstract class Def
|
||
{
|
||
public required string DefName { get; init; }
|
||
|
||
public string? Parent { get; init; }
|
||
|
||
public bool Abstract { get; init; }
|
||
}
|
||
|
||
public sealed class ActionDef : Def
|
||
{
|
||
/// <summary>RoomDef or TerritoryDef where this is done. Required on concrete actions.</summary>
|
||
public string? Room { get; init; }
|
||
|
||
/// <summary>Thing occupied for the duration. Null means the room itself is enough.</summary>
|
||
public string? Thing { get; init; }
|
||
|
||
/// <summary>Game minutes the action takes. Applied in full when it completes.</summary>
|
||
public float Minutes { get; init; }
|
||
|
||
/// <summary>NeedDef refilled on completion. Null for walks and other leisure with no refill.</summary>
|
||
public string? Need { get; init; }
|
||
|
||
/// <summary>Added to the need in one shot when the action finishes, then clamped to min–max.</summary>
|
||
public float NeedGain { get; init; }
|
||
|
||
/// <summary>Empty means every role. Values are <see cref="PersonRoles"/> ids.</summary>
|
||
public IReadOnlyList<string> Roles { get; init; } = [];
|
||
|
||
/// <summary>Leisure weight. Zero means phase 21 will not pick this for fun — only for a need.</summary>
|
||
public float Weight { get; init; }
|
||
|
||
/// <summary>
|
||
/// A sitting rather than something done whenever the need bites: only offered during the
|
||
/// eater's own lunch break (<see cref="DayFrameDef.LunchBreaks"/>). Without it a hungry class
|
||
/// would walk out of a lesson to the canteen, and the whole school would arrive at once.
|
||
/// </summary>
|
||
public bool Lunch { get; init; }
|
||
}
|
||
|
||
public sealed class ThingDef : Def
|
||
{
|
||
public IReadOnlyList<string> Actions { get; init; } = [];
|
||
|
||
/// <summary>
|
||
/// How many pupils this thing hosts for lessons. Zero for teacher's furniture — a chair
|
||
/// must not inflate class size just because someone sits in it.
|
||
/// </summary>
|
||
public int PupilSlots { get; init; }
|
||
|
||
/// <summary>Layers this occupies when worn. Empty — not apparel, so it can sit on the map.</summary>
|
||
public IReadOnlyList<string> Layers { get; init; } = [];
|
||
|
||
/// <summary>Can live in a bag, locker or at home. Furniture stays false.</summary>
|
||
public bool Portable { get; init; }
|
||
|
||
/// <summary>Kilograms. Carried mass sums; worn mass does not in this slice.</summary>
|
||
public float Mass { get; init; }
|
||
|
||
/// <summary>How much it warms — and how much it steams in heat.</summary>
|
||
public float Insulation { get; init; }
|
||
|
||
/// <summary>0–100. Dress-code formality, not a fashion score.</summary>
|
||
public int Formality { get; init; }
|
||
|
||
/// <summary>Allowed age window. Omit for any age.</summary>
|
||
public IntRange? Age { get; init; }
|
||
|
||
/// <summary><c>male</c>, <c>female</c>, or omit for any.</summary>
|
||
public string? Sex { get; init; }
|
||
|
||
/// <summary>ColorDef ids this thing may be. Empty — the instance has no colour.</summary>
|
||
public IReadOnlyList<string> Colors { get; init; } = [];
|
||
|
||
/// <summary><see cref="SkirtLengths"/> id, or omit when there is no hem to measure.</summary>
|
||
public string? SkirtLength { get; init; }
|
||
|
||
/// <summary>PE kit. Worn for that lesson; not a second wardrobe of everyday clothes.</summary>
|
||
public bool Pe { get; init; }
|
||
}
|
||
|
||
public sealed class PositionDef : Def;
|
||
|
||
public sealed class WorkDef : Def;
|
||
|
||
public sealed class RoomSlot
|
||
{
|
||
public required string Key { get; init; }
|
||
|
||
public required string Thing { get; init; }
|
||
|
||
public int Count { get; init; } = 1;
|
||
}
|
||
|
||
public sealed class RoomDef : Def
|
||
{
|
||
public IReadOnlyList<RoomSlot> Slots { get; init; } = [];
|
||
|
||
public IReadOnlyList<string> Positions { get; init; } = [];
|
||
|
||
public IReadOnlyList<string> Works { get; init; } = [];
|
||
|
||
/// <summary>
|
||
/// When true, a map room of this def with pupil slots becomes a roster class.
|
||
/// Labs keep <see cref="ThingDef.PupilSlots"/> for lessons without forming a homeroom.
|
||
/// Homerooms are a seat count of <see cref="SeatThing"/>, not a table of named slots.
|
||
/// </summary>
|
||
public bool Homeroom { get; init; }
|
||
|
||
/// <summary>Thing whose <see cref="ThingDef.PupilSlots"/> × map seats is class capacity.</summary>
|
||
public string? SeatThing { get; init; }
|
||
|
||
/// <summary>Editor default when placing a new homeroom. Vanilla classrooms are 16.</summary>
|
||
public int DefaultSeats { get; init; }
|
||
|
||
/// <summary>Game minutes spent occupying this room when walking through it.</summary>
|
||
public float TravelMinutes { get; init; }
|
||
}
|
||
|
||
public sealed class BuildingDef : Def;
|
||
|
||
public sealed class FloorDef : Def;
|
||
|
||
public sealed class TerritoryDef : Def
|
||
{
|
||
/// <summary>Game minutes spent occupying the yard when walking through it.</summary>
|
||
public float TravelMinutes { get; init; }
|
||
}
|