using Jovian.Logger; using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Nox.Game { public interface IPerk { Guid Id { get; } string Name { get; } ModifiersData Modifiers { get; } } public interface IPerkFactory { IReadOnlyCollection GetAll(); IPerk GetById(Guid perkId); IReadOnlyCollection GetPerksFor(IEntityDefinition character); bool TryAddPerk(IEntityDefinition character, Guid perkId); } [Serializable] public sealed class PerkDefinition : IPerk { [field: SerializeField] public string Name { get; set; } [field: SerializeField] public ModifiersData Modifiers { get; set; } public Guid Id { get; set; } } [Serializable] public sealed class PerksData { public List perks = new (); } public sealed class PerkFactory : IPerkFactory { private readonly Dictionary perkPool = new (); public PerkFactory(PerksRegistry perksRegistry) { if(!perksRegistry) { throw new ArgumentNullException(nameof(perksRegistry)); } var allAvailablePerks = perksRegistry.perksData; foreach(var perk in allAvailablePerks.perks) { perkPool.Add(perk.Id, perk); } } public IReadOnlyCollection GetAll() { return perkPool.Values.ToList(); } public IPerk GetById(Guid perkId) { perkPool.TryGetValue(perkId, out var perk); return perk; } public IReadOnlyCollection GetPerksFor(IEntityDefinition character) { if(character == null) { return perkPool.Values.ToList(); } var ownedPerkIds = character.Perks.perks .Select(p => p.Id) .ToHashSet(); return perkPool.Values.Where(p => !ownedPerkIds.Contains(p.Id)).ToList(); } public bool TryAddPerk(IEntityDefinition character, Guid perkId) { if(character == null) { return false; } if(perkId == Guid.Empty) { GlobalLogger.LogException("Cannot add a perk with an empty Id!", LogCategory.GameLogic); } if(character.Perks.perks.Any(p => p != null && p.Id == perkId)) { return false; } if(!perkPool.TryGetValue(perkId, out var perk)) { return false; } character.Perks.perks.Add(new PerkDefinition { Id = perk.Id, Name = perk.Name, Modifiers = perk.Modifiers }); return true; } } }