Wire health capacities to behaviour: filtration→immunity, sight/hearing→perception

The expanded capacities were mostly display-only; make two of them affect the
simulation (Moving→speed and Consciousness→intelligence gating already existed):

- Blood filtration → toxin/disease clearance: AdvanceHediffs takes an immunity
  scale (default 1); AnimalHealthSystem passes the BloodFiltration capacity, so
  damaged kidneys/liver clear Poisoned and diseases slower (RimWorld model).
  Ties the new capacities to the coevolution work — weak filtration makes toxic
  plants deadlier.
- Sight/hearing → perception radius: foraging, hunting and mate search scale by
  Sight; threat detection (flee) scales by max(Sight, Hearing) — you see or hear
  a predator. Injured eyes/ears shrink awareness.

Eating/Talking/Digestion remain indicators for now. Build + --check-content
clean. Not GUI-verified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Leonid Pershin
2026-06-14 14:18:35 +03:00
co-authored by Claude Opus 4.8
parent 8807045303
commit e105938a22
2 changed files with 24 additions and 13 deletions
+4 -2
View File
@@ -224,8 +224,10 @@ public sealed class HealthState
/// <summary> /// <summary>
/// Прогрессирует болезни (тяжесть и иммунитет растут со временем); снимает выздоровевшие /// Прогрессирует болезни (тяжесть и иммунитет растут со временем); снимает выздоровевшие
/// (иммунитет ≥ 1); возвращает true, если какая-то болезнь достигла летальной тяжести. /// (иммунитет ≥ 1); возвращает true, если какая-то болезнь достигла летальной тяжести.
/// <paramref name="immunityScale"/> — множитель набора иммунитета (способность «фильтрация крови»:
/// почки/печень выводят токсины и помогают бороться с болезнью; повреждённые → медленнее).
/// </summary> /// </summary>
public bool AdvanceHediffs(float days) public bool AdvanceHediffs(float days, float immunityScale = 1f)
{ {
var lethal = false; var lethal = false;
for (var i = _hediffs.Count - 1; i >= 0; i--) for (var i = _hediffs.Count - 1; i >= 0; i--)
@@ -237,7 +239,7 @@ public sealed class HealthState
} }
h.Severity += h.Def.SeverityPerDay * days; h.Severity += h.Def.SeverityPerDay * days;
h.Immunity += h.Def.ImmunityPerDay * days; h.Immunity += h.Def.ImmunityPerDay * days * immunityScale;
if (h.Immunity >= 1f) if (h.Immunity >= 1f)
{ {
_hediffs.RemoveAt(i); // иммунитет победил — выздоровление _hediffs.RemoveAt(i); // иммунитет победил — выздоровление
+20 -11
View File
@@ -330,20 +330,24 @@ public sealed class AnimalDecisionSystem : BaseSystem
brain.DecideIn = Interval + _rng.NextSingle() * Interval; // джиттер — расфазировать скан brain.DecideIn = Interval + _rng.NextSingle() * Interval; // джиттер — расфазировать скан
var pos = t[i].Position; var pos = t[i].Position;
var adult = AnimalFactory.IsAdult(_animalSet[o[i].Species], gr[i].Stage); var adult = AnimalFactory.IsAdult(_animalSet[o[i].Species], gr[i].Stage);
var radius = VisionRadius(o[i].Species, o[i].Traits.Vision);
var self = entities.EntityAt(i); var self = entities.EntityAt(i);
var health = self.GetComponent<Health>().State;
// Эффективный интеллект (мозг × сознание) гейтит доступные нужды/действия (фаза A7): // Эффективный интеллект (мозг × сознание) гейтит доступные нужды/действия (фаза A7):
// больной/раненый зверь с упавшим сознанием теряет высшие нужды (сон/секс) → рефлексы. // больной/раненый зверь с упавшим сознанием теряет высшие нужды (сон/секс) → рефлексы.
var intelligence = AnimalFactory.Intelligence( var intelligence = AnimalFactory.Intelligence(o[i].Traits, health);
o[i].Traits, // Радиус восприятия по способностям: зрение ищет корм/партнёра/добычу, угрозу замечаем
self.GetComponent<Health>().State // зрением ИЛИ слухом (повреждённые глаза/уши сужают восприятие).
); var baseRadius = VisionRadius(o[i].Species, o[i].Traits.Vision);
var sight = health?.Capacity(AnimalCapacities.Sight) ?? 1f;
var hearing = health?.Capacity(AnimalCapacities.Hearing) ?? 1f;
var seeRadius = baseRadius * MathF.Max(0.2f, sight);
var senseRadius = baseRadius * MathF.Max(0.2f, MathF.Max(sight, hearing));
// Настроение (A8): стресс/истощение (низкое настроение) подавляет тягу к спариванию. // Настроение (A8): стресс/истощение (низкое настроение) подавляет тягу к спариванию.
var mood = self.GetComponent<Mood>(); var mood = self.GetComponent<Mood>();
// Бегство (предатор-кластер): жертва, заметившая рядом хищника, спасается — это важнее // Бегство (предатор-кластер): жертва, заметившая рядом хищника, спасается — это важнее
// любых нужд (инстинкт выживания). Сам хищник от добычи не бежит (см. IsThreatTo). // любых нужд (инстинкт выживания). Сам хищник от добычи не бежит (см. IsThreatTo).
if (TryFindThreat(pos, radius, o[i].Species, o[i].Traits, out var threatPos)) if (TryFindThreat(pos, senseRadius, o[i].Species, o[i].Traits, out var threatPos))
{ {
brain.Action = AnimalActions.Flee; brain.Action = AnimalActions.Flee;
brain.TargetPlant = -1; brain.TargetPlant = -1;
@@ -352,7 +356,7 @@ public sealed class AnimalDecisionSystem : BaseSystem
var len = away.Length(); var len = away.Length();
brain.Target = brain.Target =
len > 0.001f len > 0.001f
? pos + away / len * (radius + _cellSize) ? pos + away / len * (senseRadius + _cellSize)
: pos + new Vector2(_cellSize, 0f); : pos + new Vector2(_cellSize, 0f);
continue; continue;
} }
@@ -372,7 +376,7 @@ public sealed class AnimalDecisionSystem : BaseSystem
when eatsMeat when eatsMeat
&& TryFindKill( && TryFindKill(
pos, pos,
radius, seeRadius,
o[i].Species, o[i].Species,
o[i].Traits, o[i].Traits,
self.Id, self.Id,
@@ -390,7 +394,7 @@ public sealed class AnimalDecisionSystem : BaseSystem
when eatsPlants when eatsPlants
&& TryFindForage( && TryFindForage(
pos, pos,
radius, seeRadius,
intelligence, intelligence,
o[i].Traits.ToxinTolerance, o[i].Traits.ToxinTolerance,
out var plant, out var plant,
@@ -415,7 +419,7 @@ public sealed class AnimalDecisionSystem : BaseSystem
&& TryFindMate( && TryFindMate(
pos, pos,
o[i].IsMale, o[i].IsMale,
radius, seeRadius,
out var mateId, out var mateId,
out var matePos out var matePos
): ):
@@ -1760,7 +1764,12 @@ public sealed class AnimalHealthSystem : BaseSystem
} }
} }
var lethal = state.AdvanceHediffs(days); // Фильтрация крови (почки/печень) ускоряет вывод токсинов и набор иммунитета: повреждённый
// орган → медленнее выздоровление от яда/болезни (для тела без неё Capacity вернёт 1).
var lethal = state.AdvanceHediffs(
days,
state.Capacity(AnimalCapacities.BloodFiltration)
);
// Кровопотеря от ран (кровотечения), иначе — постепенное восстановление крови в покое. // Кровопотеря от ран (кровотечения), иначе — постепенное восстановление крови в покое.
var bleed = 0f; var bleed = 0f;
foreach (var hd in state.Hediffs) foreach (var hd in state.Hediffs)