Senescence: aging degrades capacities and fertility
GeneLifespan already set the moment of death from old age; now aging actually manifests before it. RecomputeCapacities takes a capacityScale; AnimalHealthSystem applies SenescenceFactor(age, lifespan) — capacities fade from 60% of lifespan to ~0.55× near the end, so old animals move/see/filter blood worse and are frailer. Fertility falls with the same factor (smaller litters), and past 90% of lifespan females no longer conceive (post-reproductive). Makes GeneLifespan and the Senior stage meaningful. Build clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
249b603497
commit
e6b1367a3a
@@ -191,9 +191,11 @@ public sealed class HealthState
|
||||
|
||||
/// <summary>
|
||||
/// Пересчитывает боль (из хедифов) и способности: базовые из частей/крови/боли, затем модификаторы
|
||||
/// способностей от хедифов (лерп 1→factor по тяжести). Вызывать после изменения частей/крови/хедифов.
|
||||
/// способностей от хедифов (лерп 1→factor по тяжести), затем общий множитель <paramref name="capacityScale"/>
|
||||
/// (старение/сенесценс: дряхлеющий организм слабее по всем способностям). Вызывать после изменения
|
||||
/// частей/крови/хедифов; <paramref name="capacityScale"/>=1 — без возрастного спада.
|
||||
/// </summary>
|
||||
public void RecomputeCapacities()
|
||||
public void RecomputeCapacities(float capacityScale = 1f)
|
||||
{
|
||||
var pain = 0f;
|
||||
foreach (var h in _hediffs)
|
||||
@@ -218,6 +220,15 @@ public sealed class HealthState
|
||||
}
|
||||
}
|
||||
|
||||
if (capacityScale < 1f)
|
||||
{
|
||||
var scale = Math.Clamp(capacityScale, 0f, 1f);
|
||||
foreach (var capacity in new List<string>(caps.Keys))
|
||||
{
|
||||
caps[capacity] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
Capacities = caps;
|
||||
}
|
||||
|
||||
|
||||
@@ -790,6 +790,7 @@ public sealed class AnimalActionSystem : BaseSystem
|
||||
private const float GrazeKillAge = 1f; // трава с возрастом ниже этого после выедания исчезает
|
||||
private const float ThirstReliefBelow = 0.15f; // ниже этого жажда — питьё даёт мысль «напилась»
|
||||
private const float FleeSpeedMult = 1.2f; // страх подгоняет жертву чуть быстрее обычного шага
|
||||
private const float PostReproductiveFrac = 0.9f; // доля жизни, после которой самка уже не зачинает
|
||||
|
||||
private readonly EntityStore _store;
|
||||
private readonly PlantSet _plants;
|
||||
@@ -1216,15 +1217,25 @@ public sealed class AnimalActionSystem : BaseSystem
|
||||
if (!mother.HasComponent<Pregnant>())
|
||||
{
|
||||
ref readonly var mom = ref mother.GetComponent<AnimalOrganism>();
|
||||
// Плодовитость падает со старостью (тот же фактор сенесценса): дряхлая самка приносит
|
||||
// меньший помёт, а после порога пострепродуктивного возраста уже не зачинает.
|
||||
var momAge = mother.HasComponent<AnimalGrowth>()
|
||||
? mother.GetComponent<AnimalGrowth>().AgeDays
|
||||
: 0f;
|
||||
var ageFrac = mom.Traits.Lifespan > 0f ? momAge / mom.Traits.Lifespan : 0f;
|
||||
if (ageFrac <= PostReproductiveFrac)
|
||||
{
|
||||
var fert = AnimalHealthSystem.SenescenceFactor(momAge, mom.Traits.Lifespan);
|
||||
mother.AddComponent(
|
||||
new Pregnant
|
||||
{
|
||||
FatherGenome = father.GetComponent<AnimalOrganism>().Genome,
|
||||
DueInDays = MathF.Max(1f, mom.Traits.GestationDays),
|
||||
Litter = Math.Max(1, (int)MathF.Round(mom.Traits.LitterSize)),
|
||||
Litter = Math.Max(1, (int)MathF.Round(mom.Traits.LitterSize * fert)),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ResetMating(a, mateNeed);
|
||||
ResetMating(b, mateNeed);
|
||||
@@ -1720,10 +1731,15 @@ public sealed class AnimalHealthSystem : BaseSystem
|
||||
private readonly float _secondsPerDay;
|
||||
private readonly HediffDef[] _ambient;
|
||||
private readonly Random _rng;
|
||||
private readonly ArchetypeQuery<Health, AnimalOrganism> _query;
|
||||
private readonly ArchetypeQuery<Health, AnimalOrganism, AnimalGrowth> _query;
|
||||
private readonly List<Entity> _deaths = [];
|
||||
private float _accum;
|
||||
|
||||
// Сенесценс (старение): спад способностей начинается с этой доли продолжительности жизни и достигает
|
||||
// максимума к её концу. Дряхлеющий зверь слабее (медленнее, хуже видит/фильтрует кровь) и уязвимее.
|
||||
private const float SenescenceStart = 0.6f;
|
||||
private const float SenescenceMax = 0.45f;
|
||||
|
||||
public AnimalHealthSystem(
|
||||
EntityStore store,
|
||||
AnimalSet animals,
|
||||
@@ -1741,7 +1757,19 @@ public sealed class AnimalHealthSystem : BaseSystem
|
||||
_secondsPerDay = secondsPerDay;
|
||||
_ambient = ambient;
|
||||
_rng = new Random(seed);
|
||||
_query = store.Query<Health, AnimalOrganism>();
|
||||
_query = store.Query<Health, AnimalOrganism, AnimalGrowth>();
|
||||
}
|
||||
|
||||
/// <summary>Множитель способностей от старения (1 — молод/расцвет, <1 — дряхлеет к концу жизни).</summary>
|
||||
public static float SenescenceFactor(float ageDays, float lifespan)
|
||||
{
|
||||
if (lifespan <= 0f)
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
|
||||
var frac = (ageDays / lifespan - SenescenceStart) / MathF.Max(0.01f, 1f - SenescenceStart);
|
||||
return 1f - SenescenceMax * Math.Clamp(frac, 0f, 1f);
|
||||
}
|
||||
|
||||
protected override void OnUpdateGroup()
|
||||
@@ -1756,9 +1784,11 @@ public sealed class AnimalHealthSystem : BaseSystem
|
||||
_accum = 0f;
|
||||
_deaths.Clear();
|
||||
|
||||
foreach (var (healths, organisms, entities) in _query.Chunks)
|
||||
foreach (var (healths, organisms, growths, entities) in _query.Chunks)
|
||||
{
|
||||
var h = healths.Span;
|
||||
var o = organisms.Span;
|
||||
var g = growths.Span;
|
||||
for (var i = 0; i < h.Length; i++)
|
||||
{
|
||||
var state = h[i].State;
|
||||
@@ -1804,7 +1834,9 @@ public sealed class AnimalHealthSystem : BaseSystem
|
||||
);
|
||||
}
|
||||
|
||||
state.RecomputeCapacities();
|
||||
// Старение: к концу жизни способности дряхлеют (медленнее/слабее, уязвимее к ранам/болезни).
|
||||
var senescence = SenescenceFactor(g[i].AgeDays, o[i].Traits.Lifespan);
|
||||
state.RecomputeCapacities(senescence);
|
||||
if (
|
||||
lethal
|
||||
|| state.BloodLevel <= 0f
|
||||
|
||||
Reference in New Issue
Block a user