riversong code showcase
This commit is contained in:
155
Source/Riversong/Game/Unlocks/UnlocksManagerSystem.cs
Normal file
155
Source/Riversong/Game/Unlocks/UnlocksManagerSystem.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user