Animal thermoregulation (insulation) + wound infection
Two health threads finished, both via the existing hediff engine in AnimalHealthSystem (now also takes Climate + the new hediff defs): - Thermoregulation revives the dead GeneInsulation. A comfort band is derived per animal: fur (insulation) widens cold tolerance but worsens heat tolerance, larger body resists cold. Outside it, Hypothermia/Heatstroke severity builds (Poisoned-pattern: Intensify zeroes immunity so it can't recover while still exposed), capacities drop, severity 1 = death; back in comfort it heals. Seasonal/climate mortality and a real cold↔heat adaptation tradeoff. - Wound infection marries the injury and disease systems: while bleeding, a chance (∝ wound severity) to contract Infection, a progressing disease fought by immunity × blood filtration — weak kidneys/liver or many wounds = worse. New hediffs Hypothermia/Heatstroke/Infection (+ru/en). Build + --check-content clean. Not GUI-verified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5b0cf1dd4a
commit
562e365be1
@@ -32,6 +32,29 @@
|
|||||||
"defName": "Poisoned", "label": "hediff.poisoned",
|
"defName": "Poisoned", "label": "hediff.poisoned",
|
||||||
"initialSeverity": 0.0, "immunityPerDay": 0.65, "lethalSeverity": 1.0, "pain": 0.2,
|
"initialSeverity": 0.0, "immunityPerDay": 0.65, "lethalSeverity": 1.0, "pain": 0.2,
|
||||||
"capMods": { "Moving": 0.85, "Consciousness": 0.9, "Digestion": 0.7 }
|
"capMods": { "Moving": 0.85, "Consciousness": 0.9, "Digestion": 0.7 }
|
||||||
|
},
|
||||||
|
|
||||||
|
// Терморегуляция (как Poisoned-паттерн): сами не прогрессируют — тяжесть копится, пока зверю
|
||||||
|
// холодно/жарко (см. AnimalHealthSystem, зависит от GeneInsulation + размера тела), а в комфорте
|
||||||
|
// immunityPerDay их рассасывает. Тяжесть 1 = смерть от переохлаждения/перегрева.
|
||||||
|
{
|
||||||
|
"defName": "Hypothermia", "label": "hediff.hypothermia",
|
||||||
|
"initialSeverity": 0.0, "immunityPerDay": 0.5, "lethalSeverity": 1.0, "pain": 0.15,
|
||||||
|
"capMods": { "Moving": 0.7, "Consciousness": 0.8 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defName": "Heatstroke", "label": "hediff.heatstroke",
|
||||||
|
"initialSeverity": 0.0, "immunityPerDay": 0.5, "lethalSeverity": 1.0, "pain": 0.15,
|
||||||
|
"capMods": { "Moving": 0.75, "Consciousness": 0.8 }
|
||||||
|
},
|
||||||
|
|
||||||
|
// Заражение раны (предатор/шипы → кровотечение → инфекция): прогрессирует, иммунитет (× фильтрация
|
||||||
|
// крови) душит. Слабая фильтрация/много ран → выше риск и хуже исход.
|
||||||
|
{
|
||||||
|
"defName": "Infection", "label": "hediff.infection",
|
||||||
|
"initialSeverity": 0.08, "severityPerDay": 0.2, "immunityPerDay": 0.28,
|
||||||
|
"lethalSeverity": 1.0, "pain": 0.25,
|
||||||
|
"capMods": { "Moving": 0.8, "Consciousness": 0.85, "BloodFiltration": 0.8 }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,9 @@
|
|||||||
"hediff.fever": "fever",
|
"hediff.fever": "fever",
|
||||||
"hediff.bleeding": "bleeding",
|
"hediff.bleeding": "bleeding",
|
||||||
"hediff.poisoned": "poisoned",
|
"hediff.poisoned": "poisoned",
|
||||||
|
"hediff.hypothermia": "hypothermia",
|
||||||
|
"hediff.heatstroke": "heatstroke",
|
||||||
|
"hediff.infection": "infection",
|
||||||
"inspect.hint": "LMB — select · RMB/Esc — clear",
|
"inspect.hint": "LMB — select · RMB/Esc — clear",
|
||||||
"hud.paused": "PAUSED",
|
"hud.paused": "PAUSED",
|
||||||
"menu.title": "LittleSim",
|
"menu.title": "LittleSim",
|
||||||
|
|||||||
@@ -73,6 +73,9 @@
|
|||||||
"hediff.fever": "лихорадка",
|
"hediff.fever": "лихорадка",
|
||||||
"hediff.bleeding": "кровотечение",
|
"hediff.bleeding": "кровотечение",
|
||||||
"hediff.poisoned": "отравление",
|
"hediff.poisoned": "отравление",
|
||||||
|
"hediff.hypothermia": "переохлаждение",
|
||||||
|
"hediff.heatstroke": "тепловой удар",
|
||||||
|
"hediff.infection": "заражение",
|
||||||
"inspect.hint": "ЛКМ — выбрать · ПКМ/Esc — снять",
|
"inspect.hint": "ЛКМ — выбрать · ПКМ/Esc — снять",
|
||||||
"hud.paused": "ПАУЗА",
|
"hud.paused": "ПАУЗА",
|
||||||
"menu.title": "LittleSim",
|
"menu.title": "LittleSim",
|
||||||
|
|||||||
@@ -242,7 +242,11 @@ public sealed class WorldScene : Scene
|
|||||||
CellSize,
|
CellSize,
|
||||||
Context.Clock,
|
Context.Clock,
|
||||||
SecondsPerDay,
|
SecondsPerDay,
|
||||||
|
climate,
|
||||||
content.Defs.All<HediffDef>().Where(h => h.AmbientPerDay > 0f).ToArray(),
|
content.Defs.All<HediffDef>().Where(h => h.AmbientPerDay > 0f).ToArray(),
|
||||||
|
content.Defs.TryGet<HediffDef>("Hypothermia", out var hypo) ? hypo : null,
|
||||||
|
content.Defs.TryGet<HediffDef>("Heatstroke", out var heat) ? heat : null,
|
||||||
|
content.Defs.TryGet<HediffDef>("Infection", out var infe) ? infe : null,
|
||||||
_config.Seed + 0x3EAD
|
_config.Seed + 0x3EAD
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1833,7 +1833,11 @@ public sealed class AnimalHealthSystem : BaseSystem
|
|||||||
private readonly int _cellSize;
|
private readonly int _cellSize;
|
||||||
private readonly GameClock _clock;
|
private readonly GameClock _clock;
|
||||||
private readonly float _secondsPerDay;
|
private readonly float _secondsPerDay;
|
||||||
|
private readonly Climate _climate;
|
||||||
private readonly HediffDef[] _ambient;
|
private readonly HediffDef[] _ambient;
|
||||||
|
private readonly HediffDef? _hypothermia;
|
||||||
|
private readonly HediffDef? _heatstroke;
|
||||||
|
private readonly HediffDef? _infection;
|
||||||
private readonly Random _rng;
|
private readonly Random _rng;
|
||||||
private readonly ArchetypeQuery<Health, AnimalOrganism, AnimalGrowth> _query;
|
private readonly ArchetypeQuery<Health, AnimalOrganism, AnimalGrowth> _query;
|
||||||
private readonly List<Entity> _deaths = [];
|
private readonly List<Entity> _deaths = [];
|
||||||
@@ -1844,13 +1848,28 @@ public sealed class AnimalHealthSystem : BaseSystem
|
|||||||
private const float SenescenceStart = 0.6f;
|
private const float SenescenceStart = 0.6f;
|
||||||
private const float SenescenceMax = 0.45f;
|
private const float SenescenceMax = 0.45f;
|
||||||
|
|
||||||
|
// Термокомфорт (°C) при теплоизоляции 0.5 и размере тела 1; границы сдвигаются мехом и размером тела.
|
||||||
|
private const float ColdComfort = 2f; // ниже — мёрзнет
|
||||||
|
private const float HeatComfort = 30f; // выше — перегревается
|
||||||
|
private const float ColdInsulationBonus = 30f; // мех (insulation 0..1) расширяет холодоустойчивость
|
||||||
|
private const float HeatInsulationPenalty = 14f; // тот же мех ухудшает жароустойчивость
|
||||||
|
private const float ColdBodyBonus = 8f; // крупное тело (тепловая инерция) держит холод лучше
|
||||||
|
private const float ThermalRatePerDegree = 0.06f; // прирост тяжести за °C за пределом комфорта в день
|
||||||
|
|
||||||
|
// Заражение раны: шанс в день при кровотечении тяжести 1 подхватить инфекцию.
|
||||||
|
private const float InfectionChancePerDay = 0.25f;
|
||||||
|
|
||||||
public AnimalHealthSystem(
|
public AnimalHealthSystem(
|
||||||
EntityStore store,
|
EntityStore store,
|
||||||
AnimalSet animals,
|
AnimalSet animals,
|
||||||
int cellSize,
|
int cellSize,
|
||||||
GameClock clock,
|
GameClock clock,
|
||||||
float secondsPerDay,
|
float secondsPerDay,
|
||||||
|
Climate climate,
|
||||||
HediffDef[] ambient,
|
HediffDef[] ambient,
|
||||||
|
HediffDef? hypothermia,
|
||||||
|
HediffDef? heatstroke,
|
||||||
|
HediffDef? infection,
|
||||||
int seed
|
int seed
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -1859,7 +1878,11 @@ public sealed class AnimalHealthSystem : BaseSystem
|
|||||||
_cellSize = cellSize;
|
_cellSize = cellSize;
|
||||||
_clock = clock;
|
_clock = clock;
|
||||||
_secondsPerDay = secondsPerDay;
|
_secondsPerDay = secondsPerDay;
|
||||||
|
_climate = climate;
|
||||||
_ambient = ambient;
|
_ambient = ambient;
|
||||||
|
_hypothermia = hypothermia;
|
||||||
|
_heatstroke = heatstroke;
|
||||||
|
_infection = infection;
|
||||||
_rng = new Random(seed);
|
_rng = new Random(seed);
|
||||||
_query = store.Query<Health, AnimalOrganism, AnimalGrowth>();
|
_query = store.Query<Health, AnimalOrganism, AnimalGrowth>();
|
||||||
}
|
}
|
||||||
@@ -1912,8 +1935,48 @@ public sealed class AnimalHealthSystem : BaseSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Терморегуляция: вне комфорта (зависит от GeneInsulation + размера тела) копится тяжесть
|
||||||
|
// гипотермии/теплового удара; в комфорте immunityPerDay их рассасывает. Мех расширяет
|
||||||
|
// холодоустойчивость, но ухудшает жароустойчивость; крупное тело держит холод.
|
||||||
|
var insul = Math.Clamp(o[i].Traits.Insulation, 0f, 1f);
|
||||||
|
var coldLimit =
|
||||||
|
ColdComfort
|
||||||
|
- ColdInsulationBonus * insul
|
||||||
|
- ColdBodyBonus * MathF.Max(0f, o[i].Traits.BodySize - 1f);
|
||||||
|
var heatLimit = HeatComfort - HeatInsulationPenalty * insul;
|
||||||
|
var temp = _climate.Temperature;
|
||||||
|
if (temp < coldLimit && _hypothermia is not null)
|
||||||
|
{
|
||||||
|
state.Intensify(_hypothermia, (coldLimit - temp) * ThermalRatePerDegree * days);
|
||||||
|
}
|
||||||
|
else if (temp > heatLimit && _heatstroke is not null)
|
||||||
|
{
|
||||||
|
state.Intensify(_heatstroke, (temp - heatLimit) * ThermalRatePerDegree * days);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Заражение раны: пока есть кровотечение, шанс (∝ его тяжести) подхватить инфекцию.
|
||||||
|
if (_infection is not null && !state.Has(_infection.DefName))
|
||||||
|
{
|
||||||
|
var bleedSeverity = 0f;
|
||||||
|
foreach (var hd in state.Hediffs)
|
||||||
|
{
|
||||||
|
if (hd.Def.BloodLossPerDay > 0f && hd.Severity > bleedSeverity)
|
||||||
|
{
|
||||||
|
bleedSeverity = hd.Severity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
bleedSeverity > 0f
|
||||||
|
&& _rng.NextSingle() < InfectionChancePerDay * bleedSeverity * days
|
||||||
|
)
|
||||||
|
{
|
||||||
|
state.Add(_infection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Фильтрация крови (почки/печень) ускоряет вывод токсинов и набор иммунитета: повреждённый
|
// Фильтрация крови (почки/печень) ускоряет вывод токсинов и набор иммунитета: повреждённый
|
||||||
// орган → медленнее выздоровление от яда/болезни (для тела без неё Capacity вернёт 1).
|
// орган → медленнее выздоровление от яда/болезни/инфекции (для тела без неё Capacity вернёт 1).
|
||||||
var lethal = state.AdvanceHediffs(
|
var lethal = state.AdvanceHediffs(
|
||||||
days,
|
days,
|
||||||
state.Capacity(AnimalCapacities.BloodFiltration)
|
state.Capacity(AnimalCapacities.BloodFiltration)
|
||||||
|
|||||||
Reference in New Issue
Block a user