Рефактор: зрение/скорость/выедание животного — из дефа вида
Завершает вынос баланса в данные: AnimalDecisionSystem.VisionRadius берёт дальность из AnimalDef.VisionCells (× ген), TryFindPlant/TryFindMate принимают готовый радиус; AnimalActionSystem берёт BaseSpeed и ForageBiteDays из дефа вида (через AnimalSet). Убраны хардкод-константы скорости/зрения/выедания. Сборка чистая, --check-content (9 типов дефов). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5d0cbd2115
commit
cbc74c0794
@@ -170,7 +170,6 @@ public sealed class AnimalRutSystem(AnimalSet animals, Climate climate, HediffDe
|
||||
public sealed class AnimalDecisionSystem : BaseSystem
|
||||
{
|
||||
private const float Interval = 0.6f;
|
||||
private const float VisionCells = 14f; // базовый радиус зрения в клетках (× ген vision)
|
||||
|
||||
private readonly UtilityAi<AnimalContext> _brain;
|
||||
private readonly GameClock _clock;
|
||||
@@ -257,6 +256,7 @@ public sealed class AnimalDecisionSystem : BaseSystem
|
||||
brain.DecideIn = Interval + _rng.NextSingle() * Interval; // джиттер — расфазировать скан
|
||||
var pos = t[i].Position;
|
||||
var adult = AnimalFactory.IsAdult(_animalSet[o[i].Species], gr[i].Stage);
|
||||
var radius = VisionRadius(o[i].Species, o[i].Traits.Vision);
|
||||
var name =
|
||||
_brain.Select(new AnimalContext(n[i].Values))?.Name ?? AnimalActions.Wander;
|
||||
|
||||
@@ -264,7 +264,7 @@ public sealed class AnimalDecisionSystem : BaseSystem
|
||||
{
|
||||
case AnimalActions.Eat
|
||||
when EatsPlants(o[i].Species)
|
||||
&& TryFindPlant(pos, o[i].Traits.Vision, out var plant, out var pp):
|
||||
&& TryFindPlant(pos, radius, out var plant, out var pp):
|
||||
brain.Action = AnimalActions.Eat;
|
||||
brain.TargetPlant = plant;
|
||||
brain.Target = pp;
|
||||
@@ -280,13 +280,7 @@ public sealed class AnimalDecisionSystem : BaseSystem
|
||||
break;
|
||||
case AnimalActions.Mate
|
||||
when adult
|
||||
&& TryFindMate(
|
||||
pos,
|
||||
o[i].IsMale,
|
||||
o[i].Traits.Vision,
|
||||
out var mateId,
|
||||
out var matePos
|
||||
):
|
||||
&& TryFindMate(pos, o[i].IsMale, radius, out var mateId, out var matePos):
|
||||
brain.Action = AnimalActions.Mate;
|
||||
brain.TargetPlant = -1;
|
||||
brain.TargetMate = mateId;
|
||||
@@ -306,6 +300,10 @@ public sealed class AnimalDecisionSystem : BaseSystem
|
||||
}
|
||||
}
|
||||
|
||||
// Радиус восприятия особи: базовая дальность вида (данные) × ген зрения × размер клетки.
|
||||
private float VisionRadius(int species, float vision) =>
|
||||
MathF.Max(1f, _animalSet[species].Def.VisionCells) * MathF.Max(0.2f, vision) * _cellSize;
|
||||
|
||||
// Ест ли вид растения (диета данными) — гейт поиска корма; хищники (meat) появятся на горизонте.
|
||||
private bool EatsPlants(int species)
|
||||
{
|
||||
@@ -321,10 +319,9 @@ public sealed class AnimalDecisionSystem : BaseSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ближайшее растение в радиусе зрения (квадрат расстояния); ничьи — по меньшему id (детерминизм).
|
||||
private bool TryFindPlant(Vector2 from, float vision, out int plantId, out Vector2 position)
|
||||
// Ближайшее растение в радиусе (квадрат расстояния); ничьи — по меньшему id (детерминизм).
|
||||
private bool TryFindPlant(Vector2 from, float radius, out int plantId, out Vector2 position)
|
||||
{
|
||||
var radius = VisionCells * MathF.Max(0.2f, vision) * _cellSize;
|
||||
var bestSq = radius * radius;
|
||||
plantId = -1;
|
||||
position = default;
|
||||
@@ -374,12 +371,11 @@ public sealed class AnimalDecisionSystem : BaseSystem
|
||||
private bool TryFindMate(
|
||||
Vector2 from,
|
||||
bool selfMale,
|
||||
float vision,
|
||||
float radius,
|
||||
out int mateId,
|
||||
out Vector2 position
|
||||
)
|
||||
{
|
||||
var radius = VisionCells * MathF.Max(0.2f, vision) * _cellSize;
|
||||
var bestSq = radius * radius;
|
||||
mateId = -1;
|
||||
position = default;
|
||||
@@ -428,12 +424,11 @@ public sealed class AnimalDecisionSystem : BaseSystem
|
||||
/// </summary>
|
||||
public sealed class AnimalActionSystem : BaseSystem
|
||||
{
|
||||
private const float BaseSpeed = 28f; // мировых единиц в секунду при moveSpeed 1
|
||||
private const float GrazePerDay = 40f; // на сколько игровых дней роста убавляется выеденное растение
|
||||
private const float GrazeKillAge = 1f; // трава с возрастом ниже этого после выедания исчезает
|
||||
|
||||
private readonly EntityStore _store;
|
||||
private readonly PlantSet _plants;
|
||||
private readonly AnimalSet _animalSet;
|
||||
private readonly NeedSet _needs;
|
||||
private readonly GameClock _clock;
|
||||
private readonly float _secondsPerDay;
|
||||
@@ -445,6 +440,7 @@ public sealed class AnimalActionSystem : BaseSystem
|
||||
public AnimalActionSystem(
|
||||
EntityStore store,
|
||||
PlantSet plants,
|
||||
AnimalSet animals,
|
||||
NeedSet needs,
|
||||
GameClock clock,
|
||||
float secondsPerDay,
|
||||
@@ -453,6 +449,7 @@ public sealed class AnimalActionSystem : BaseSystem
|
||||
{
|
||||
_store = store;
|
||||
_plants = plants;
|
||||
_animalSet = animals;
|
||||
_needs = needs;
|
||||
_clock = clock;
|
||||
_secondsPerDay = secondsPerDay;
|
||||
@@ -483,7 +480,8 @@ public sealed class AnimalActionSystem : BaseSystem
|
||||
ref var brain = ref b[i];
|
||||
var values = n[i].Values;
|
||||
ref var pos = ref t[i].Position;
|
||||
var speed = BaseSpeed * MathF.Max(0.2f, o[i].Traits.MoveSpeed);
|
||||
var def = _animalSet[o[i].Species].Def;
|
||||
var speed = def.BaseSpeed * MathF.Max(0.2f, o[i].Traits.MoveSpeed);
|
||||
|
||||
switch (brain.Action)
|
||||
{
|
||||
@@ -495,7 +493,7 @@ public sealed class AnimalActionSystem : BaseSystem
|
||||
if (MoveTo(ref pos, brain.Target, speed * seconds))
|
||||
{
|
||||
Refill(values, AnimalActions.Eat, days);
|
||||
Graze(brain.TargetPlant, days);
|
||||
Graze(brain.TargetPlant, days, def.ForageBiteDays);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -571,7 +569,7 @@ public sealed class AnimalActionSystem : BaseSystem
|
||||
}
|
||||
|
||||
// Выедание: убавляет рост растения; траву (без ствола), выеденную до нуля, помечает на гибель.
|
||||
private void Graze(int plantId, float days)
|
||||
private void Graze(int plantId, float days, float bitePerDay)
|
||||
{
|
||||
if (
|
||||
plantId < 0
|
||||
@@ -584,7 +582,7 @@ public sealed class AnimalActionSystem : BaseSystem
|
||||
}
|
||||
|
||||
ref var grow = ref plant.GetComponent<PlantGrowth>();
|
||||
grow.AgeDays = MathF.Max(0f, grow.AgeDays - GrazePerDay * days);
|
||||
grow.AgeDays = MathF.Max(0f, grow.AgeDays - bitePerDay * days);
|
||||
var isGrass = _plants[grow.Species].Def.TrunkRadiusCells <= 0f;
|
||||
if (isGrass && grow.AgeDays <= GrazeKillAge && !_eaten.Contains(plant))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user