using System; using System.Collections.Generic; using System.Linq; namespace Nox.Game { public interface IPerkFactory { IReadOnlyCollection GetAll(); PerkDefinition GetById(Guid perkId); IReadOnlyCollection GetPerksFor(CharacterDefinition character); bool TryAddPerk(CharacterDefinition character, Guid perkId); } [Serializable] public sealed class PerkDefinition { public Guid id; public string name; public ModifiersData modifiers = new (); } [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 PerkDefinition GetById(Guid perkId) { perkPool.TryGetValue(perkId, out var perk); return perk; } public IReadOnlyCollection GetPerksFor(CharacterDefinition character) { if(character == null) { return perkPool.Values.ToList(); } var ownedPerkIds = character.perksData.perks .Select(p => p.id) .ToHashSet(); return perkPool.Values.Where(p => !ownedPerkIds.Contains(p.id)).ToList(); } public bool TryAddPerk(CharacterDefinition character, Guid perkId) { if(character == null) { return false; } if(character.perksData.perks.Any(p => p != null && p.id == perkId)) { return false; } if(!perkPool.TryGetValue(perkId, out var perk)) { return false; } character.perksData.perks.Add(new PerkDefinition { id = perk.id, name = perk.name }); return true; } } }