using System; using System.Linq; namespace Nox.Game { public interface ICharacterFactory { CharacterDefinition CreateCustomProtagonist(CustomCharacterCreationRequest request); CharacterDefinition CreateFromTemplate(CharacterTemplate template, CharacterRole role = CharacterRole.Companion); } [Serializable] public sealed class CharacterTemplate { public Guid id = Guid.NewGuid(); public string displayName = "New Character"; public CharacterRace race = (CharacterRace)GetRandomInt(1, Enum.GetValues(typeof(CharacterRace)).Length-1); public CharacterClass @class = (CharacterClass)GetRandomInt(1, Enum.GetValues(typeof(CharacterClass)).Length-1); public EntityAttributes attributes = GetDefaultAttributes(); public PerksData perksData = new(); public ModifiersData modifiersData = new(); private static int GetRandomInt(int start, int end) => new Random().Next(start, end); private static EntityAttributes GetDefaultAttributes() { var attributes = new EntityAttributes { attributes = new Attribute[] { new (AttributeType.Might, 1), new (AttributeType.Knowledge, 1), new (AttributeType.Perception, 1), new (AttributeType.Reflex, 1) } }; return attributes; } } [Serializable] public sealed class CustomCharacterCreationRequest { public Guid id = Guid.Empty; public string displayName; public CharacterRace race; public CharacterClass @class; public EntityStats stats; public EntityAttributes attributes; public PerksData perks = new(); public ModifiersData modifiers = new(); } public sealed class CharacterFactory : ICharacterFactory { private readonly ICharacterAttributesFactory attributesFactory; private readonly ICharacterStatsFactory statsFactory; private readonly IPerkFactory perkFactory; public CharacterFactory( ICharacterAttributesFactory attributesFactory, ICharacterStatsFactory statsFactory, IPerkFactory perkFactory) { this.attributesFactory = attributesFactory ?? throw new ArgumentNullException(nameof(attributesFactory)); this.statsFactory = statsFactory ?? throw new ArgumentNullException(nameof(statsFactory)); this.perkFactory = perkFactory ?? throw new ArgumentNullException(nameof(perkFactory)); } public CharacterDefinition CreateCustomProtagonist(CustomCharacterCreationRequest request) { if(request == null) { throw new ArgumentNullException(nameof(request)); } var attributes = attributesFactory.Create(request.attributes); var stats = statsFactory.Create(request.attributes); var character = new CharacterDefinition { ID = request.id == Guid.Empty ? Guid.NewGuid() : request.id, Name = request.displayName, Race = request.race, Class = request.@class, Role = CharacterRole.Protagonist, Attributes = attributes, Stats = stats, Perks = request.perks ?? new PerksData(), Modifiers = request.modifiers ?? new ModifiersData() }; AddStartingPerks(character, request.perks); return character; } public CharacterDefinition CreateFromTemplate(CharacterTemplate template, CharacterRole role = CharacterRole.Companion) { if(template == null) { throw new ArgumentNullException(nameof(template)); } template.perksData ??= new PerksData(); template.modifiersData ??= new ModifiersData(); var character = new CharacterDefinition { ID = template.id == Guid.Empty ? Guid.NewGuid() : template.id, Name = template.displayName, Race = template.race, Class = template.@class, Role = role, Attributes = attributesFactory.Create(template.attributes), Stats = statsFactory.Create(template.attributes), Perks = template.perksData, Modifiers = template.modifiersData }; AddStartingPerks(character, template.perksData); AddStartingModifiers(character, template.modifiersData); return character; } private void AddStartingPerks(CharacterDefinition character, PerksData perkData) { if(perkData?.perks == null || perkData.perks.Count == 0) { return; } foreach(var perkId in perkData.perks.Distinct()) { perkFactory.TryAddPerk(character, perkId.Id); } } private void AddStartingModifiers(CharacterDefinition character, ModifiersData modifiersData) { if(modifiersData?.modifiers == null || modifiersData.modifiers.Count == 0) { return; } foreach(var modifierId in modifiersData.modifiers.Distinct()) { perkFactory.TryAddPerk(character, modifierId.Id); } } } }