126 lines
4.4 KiB
C#
126 lines
4.4 KiB
C#
using System;
|
|
using Cysharp.Threading.Tasks;
|
|
using Unity.Mathematics;
|
|
using UnityEngine;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
public class PopulationNeedsSystem : GameSystem, IInitializable, IDisposable, IUpdatable
|
|
{
|
|
private const float MaxHappinessScoreChangeRate = 0.1f;
|
|
|
|
[InjectService]
|
|
private ISignalBus _signalBus;
|
|
|
|
[InjectService]
|
|
private IEntityCache _entityCache;
|
|
|
|
[InjectService]
|
|
private World _world;
|
|
|
|
[InjectService]
|
|
private GameConfig _config;
|
|
|
|
public PopulationNeedsSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
|
{
|
|
}
|
|
|
|
public UniTask InitializeAsync()
|
|
{
|
|
_signalBus.Subscribe<EndOfWeekSignal>(OnEndOfWeek);
|
|
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_signalBus.Unsubscribe<EndOfWeekSignal>(OnEndOfWeek);
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (_world.TimeState.DayNightCycleStep != DayNightCycleStep.Day) return;
|
|
|
|
foreach (var house in _entityCache.GetHouses())
|
|
{
|
|
ref var needsState = ref house.GetNeedsStateRW();
|
|
ref var storage = ref house.GetStorageRW();
|
|
|
|
var targetHappiness = 1f;
|
|
var happinessScore = 0;
|
|
var maxHappinessScore = 0;
|
|
needsState.AllNeedsMet = true;
|
|
|
|
for (var i = 0; i < needsState.Needs.Length; i++)
|
|
{
|
|
var need = needsState.Needs[i];
|
|
|
|
if (need.TierIndex > house.TierIndex) break;
|
|
if (need.Type != PopulationNeedType.Product) throw new NotImplementedException();
|
|
|
|
if (need.Current < need.YieldOnFetch)
|
|
{
|
|
var productCount = storage.AvailableNow(need.ProductHandle);
|
|
if (productCount > 0)
|
|
{
|
|
storage.Take(need.ProductHandle, productCount);
|
|
need.Current += (ushort)math.min(productCount * need.YieldOnFetch, ushort.MaxValue);
|
|
}
|
|
}
|
|
|
|
var needMet = need.Current > 0;
|
|
if (needMet) happinessScore += need.HappinessScore;
|
|
|
|
maxHappinessScore += need.HappinessScore;
|
|
|
|
needsState.AllNeedsMet &= needMet;
|
|
needsState.Needs[i] = need;
|
|
}
|
|
|
|
if (maxHappinessScore > 0)
|
|
{
|
|
needsState.MaxHappinessScore += MaxHappinessScoreChangeRate * Time.deltaTime;
|
|
needsState.MaxHappinessScore = math.min(needsState.MaxHappinessScore, maxHappinessScore);
|
|
|
|
targetHappiness = needsState.MaxHappinessScore > 0 ? math.saturate(happinessScore / needsState.MaxHappinessScore) : 1;
|
|
}
|
|
else
|
|
{
|
|
needsState.MaxHappinessScore = 0;
|
|
}
|
|
|
|
needsState.Happiness = Mathf.MoveTowards(needsState.Happiness, targetHappiness, _config.Population.OverallHappinessChangeRate * Time.deltaTime);
|
|
needsState.Happiness = math.saturate(needsState.Happiness);
|
|
needsState.OverallHappinessWeight = math.saturate((float)(_world.TimeState.TotalWeeks - house.WeekCreated) / _config.Population.HouseWeightRampUpWeekCount);
|
|
}
|
|
}
|
|
|
|
private void OnEndOfWeek(EndOfWeekSignal signal)
|
|
{
|
|
foreach (var house in _entityCache.GetHouses())
|
|
{
|
|
ref var needsState = ref house.GetNeedsStateRW();
|
|
|
|
if (needsState.AllNeedsMet)
|
|
needsState.NeedsMetForWeeks++;
|
|
else
|
|
needsState.NeedsMetForWeeks = 0;
|
|
|
|
for (var i = 0; i < needsState.Needs.Length; i++)
|
|
{
|
|
var need = needsState.Needs[i];
|
|
|
|
if (need.TierIndex > house.TierIndex) break;
|
|
if (need.Type != PopulationNeedType.Product) continue;
|
|
|
|
if (need.Current >= need.ConsumptionRate)
|
|
need.Current -= need.ConsumptionRate;
|
|
else
|
|
need.Current = 0;
|
|
|
|
needsState.Needs[i] = need;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |