Protocol v8 adds tenths of a °C and precipitation to the clock frame; warmth drains from insulation versus place temperature. Co-authored-by: Cursor <cursoragent@cursor.com>
82 lines
2.6 KiB
C#
82 lines
2.6 KiB
C#
using Arch.Core;
|
|
using HSchool.Ai;
|
|
using HSchool.Content;
|
|
|
|
namespace HSchool.Simulation;
|
|
|
|
/// <summary>
|
|
/// Drains <c>Warmth</c> from the gap between clothing insulation and the temperature of the
|
|
/// place the person is in. Off campus the generic need restore already snaps it to max.
|
|
/// </summary>
|
|
public static class WarmthDecay
|
|
{
|
|
private static readonly QueryDescription People =
|
|
new QueryDescription().WithAll<PersonNeeds, PersonTraits, PersonInsulation, Presence>();
|
|
|
|
public static void Apply(School school, double gameMinutes)
|
|
{
|
|
if (gameMinutes <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var catalog = school.Catalog;
|
|
if (catalog is null || !catalog.Needs.TryGetValue("Warmth", out var warmth) || warmth.Abstract)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var preset = Preset(school, catalog);
|
|
var hours = gameMinutes / 60d;
|
|
var world = school.World;
|
|
world.Query(
|
|
in People,
|
|
(ref PersonNeeds needs, ref PersonTraits traits, ref PersonInsulation insulation, ref Presence presence) =>
|
|
{
|
|
if (!presence.IsOnCampus || !needs.Values.ContainsKey(warmth.DefName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var place = PlaceClimate.TemperatureC(school, presence.NodeId);
|
|
var felt = place + insulation.Value * (preset?.InsulationPerC ?? 1f);
|
|
var center = (preset?.ComfortC ?? 21f) + TraitOffset(catalog, traits);
|
|
var halfWidth = preset?.ComfortHalfWidthC ?? 3f;
|
|
var mismatch = Math.Abs(felt - center) - halfWidth;
|
|
if (mismatch <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var next = needs.Values[warmth.DefName] - (float)(mismatch * warmth.DecayPerHour * hours);
|
|
needs.Values[warmth.DefName] = Math.Clamp(next, warmth.Min, warmth.Max);
|
|
});
|
|
}
|
|
|
|
private static ClimatePresetDef? Preset(School school, DefCatalog catalog)
|
|
{
|
|
if (school.ClimatePresetId is { } id
|
|
&& catalog.ClimatePresets.TryGetValue(id, out var preset)
|
|
&& !preset.Abstract)
|
|
{
|
|
return preset;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static float TraitOffset(DefCatalog catalog, PersonTraits traits)
|
|
{
|
|
var offset = 0f;
|
|
foreach (var id in traits.Ids)
|
|
{
|
|
if (catalog.Traits.TryGetValue(id, out var trait))
|
|
{
|
|
offset += trait.ComfortTemperatureOffset;
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
}
|