155 lines
4.9 KiB
C#
155 lines
4.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
[Service(typeof(IUnlocksService))]
|
|
[InitializeAfter(typeof(HouseTierCountTrackingSystem))]
|
|
public class UnlocksManagerSystem : GameSystem, IInitializable, IDisposable, IUnlocksService
|
|
{
|
|
[InjectService]
|
|
private IGameDatabase _gameDatabase;
|
|
|
|
[InjectService]
|
|
private ISignalBus _signalBus;
|
|
|
|
[InjectService]
|
|
private IEntityCollection _entityCollection;
|
|
|
|
[InjectService]
|
|
private World _world;
|
|
|
|
private List<UnlockDefinition> _unlocks;
|
|
|
|
public UnlocksManagerSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
|
{
|
|
}
|
|
|
|
public UniTask InitializeAsync()
|
|
{
|
|
_unlocks = _gameDatabase.OfType<UnlockDefinition>();
|
|
|
|
foreach (var unlock in _unlocks)
|
|
if (unlock.Building)
|
|
_world.UnlocksState.AddBuildingUnlock(unlock.Building, unlock.RuntimeId);
|
|
|
|
_signalBus.Subscribe<WorldReadySignal>(OnWorldReady);
|
|
_signalBus.Subscribe<BuildingCreatedSignal>(OnBuildingCreated);
|
|
_signalBus.Subscribe<BuildingUpgradedSignal>(OnBuildingUpgraded);
|
|
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_signalBus.Unsubscribe<WorldReadySignal>(OnWorldReady);
|
|
_signalBus.Unsubscribe<BuildingCreatedSignal>(OnBuildingCreated);
|
|
_signalBus.Unsubscribe<BuildingUpgradedSignal>(OnBuildingUpgraded);
|
|
}
|
|
|
|
private void OnWorldReady(WorldReadySignal signal)
|
|
{
|
|
_ = GrantFreeUnlocksWithDelayAsync();
|
|
}
|
|
|
|
private async UniTask GrantFreeUnlocksWithDelayAsync()
|
|
{
|
|
await UniTask.WaitForSeconds(2, true);
|
|
|
|
foreach (var unlock in _unlocks)
|
|
if (unlock.Conditions.Count <= 0)
|
|
Unlock(unlock);
|
|
}
|
|
|
|
private void OnBuildingCreated(BuildingCreatedSignal signal)
|
|
{
|
|
TryUnlockAvailableUnlocks();
|
|
}
|
|
|
|
private void OnBuildingUpgraded(BuildingUpgradedSignal signal)
|
|
{
|
|
TryUnlockAvailableUnlocks();
|
|
}
|
|
|
|
private void TryUnlockAvailableUnlocks()
|
|
{
|
|
foreach (var unlock in _unlocks)
|
|
if (CanUnlock(unlock))
|
|
Unlock(unlock);
|
|
}
|
|
|
|
private bool CanUnlock(UnlockDefinition unlock)
|
|
{
|
|
if (_world.UnlocksState.Unlocked.Contains(unlock.RuntimeId)) return false;
|
|
|
|
foreach (var condition in unlock.Conditions)
|
|
if (!IsConditionSatisfied(condition))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public void Unlock(UnlockDefinition unlock)
|
|
{
|
|
if (!_world.UnlocksState.Unlocked.Add(unlock.RuntimeId)) return;
|
|
|
|
switch (unlock.Type)
|
|
{
|
|
case UnlockType.UnlockBuilding:
|
|
UnlockBuilding(unlock);
|
|
break;
|
|
|
|
case UnlockType.None:
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
_signalBus.Raise(new UnlockUnlockedSignal(unlock));
|
|
}
|
|
|
|
public void UnlockAll()
|
|
{
|
|
foreach (var unlock in _unlocks) Unlock(unlock);
|
|
}
|
|
|
|
private void UnlockBuilding(UnlockDefinition unlock)
|
|
{
|
|
var unlocksState = _world.UnlocksState;
|
|
var unlockedId = unlock.Building.RuntimeId;
|
|
|
|
unlocksState.UnlockedBuildings.Add(unlockedId);
|
|
unlocksState.TeasedBuildings.Remove(unlockedId);
|
|
|
|
foreach (var teased in unlock.TeasedBuildings)
|
|
{
|
|
if (unlocksState.UnlockedBuildings.Contains(teased.RuntimeId)) continue;
|
|
|
|
unlocksState.TeasedBuildings.Add(teased.RuntimeId);
|
|
}
|
|
}
|
|
|
|
private bool IsConditionSatisfied(UnlockCondition condition)
|
|
{
|
|
switch (condition.Type)
|
|
{
|
|
case UnlockConditionType.BuildingPlaced:
|
|
foreach (Building building in _entityCollection.GetInternalEntityList(typeof(Building)))
|
|
if (building.Definition.RuntimeId == condition.Building.RuntimeId)
|
|
return true;
|
|
return false;
|
|
|
|
case UnlockConditionType.HouseCountAtTierOrAbove:
|
|
var houseCount = 0;
|
|
var houseCountsByTier = _world.PopulationState.HouseCountsByTier;
|
|
for (var i = condition.MinHouseTierIndex; i < WorldPopulationState.MaxBuildingTier; i++) houseCount += houseCountsByTier[i];
|
|
|
|
return houseCount >= condition.HouseCount;
|
|
|
|
case UnlockConditionType.None:
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
}
|
|
} |