using System; using ZLinq; namespace Nox.Game { public interface ICharacterFactory { CharacterDefinition CreateProtagonist(CharacterCreationRequest request); CharacterDefinition CreateFromTemplate(CharacterTemplate template, CharacterRole role = CharacterRole.Companion); } [Serializable] public sealed class CharacterTemplate : IEntityDefinition { public Guid Id { get; set; } = Guid.NewGuid(); public string Name { get; set; } = "New Character"; public int PortraitIndex { get; set; } public CharacterRace Race { get; set; } = (CharacterRace)GetRandomInt(1, Enum.GetValues(typeof(CharacterRace)).Length-1); public CharacterClass Class { get; set; } = (CharacterClass)GetRandomInt(1, Enum.GetValues(typeof(CharacterClass)).Length-1); public CharacterRole Role { get; set; } = CharacterRole.Companion; public EntityAttributes Attributes { get; set; } = GetDefaultAttributes(); public EntityStats Stats { get; set; } = new() { stats = Array.Empty() }; public PerksData Perks { get; set; } = new(); public ModifiersData Modifiers { get; set; } = 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 CharacterCreationRequest : IEntityDefinition { public Guid Id { get; set; } = Guid.Empty; public string Name { get; set; } public int PortraitIndex { get; set; } public CharacterRace Race { get; set; } public CharacterClass Class { get; set; } public CharacterRole Role { get; set; } = CharacterRole.Protagonist; public EntityAttributes Attributes { get; set; } public EntityStats Stats { get; set; } = new() { stats = Array.Empty() }; public PerksData Perks { get; set; } = new(); public ModifiersData Modifiers { get; set; } = new(); } public sealed class CharacterFactory : ICharacterFactory { private readonly ICharacterAttributesFactory attributesFactory; private readonly ICharacterStatsFactory statsFactory; private readonly IPerkFactory perkFactory; private readonly IModifiersFactory modifiersFactory; public CharacterFactory( ICharacterAttributesFactory attributesFactory, ICharacterStatsFactory statsFactory, IPerkFactory perkFactory, IModifiersFactory modifiersFactory) { this.attributesFactory = attributesFactory ?? throw new ArgumentNullException(nameof(attributesFactory)); this.statsFactory = statsFactory ?? throw new ArgumentNullException(nameof(statsFactory)); this.perkFactory = perkFactory ?? throw new ArgumentNullException(nameof(perkFactory)); this.modifiersFactory = modifiersFactory ?? throw new ArgumentNullException(nameof(modifiersFactory)); } public CharacterDefinition CreateProtagonist(CharacterCreationRequest request) { if(request == null) { throw new ArgumentNullException(nameof(request)); } var attributes = attributesFactory.Create(request); var stats = statsFactory.Create(request); var character = new CharacterDefinition { Id = request.Id == Guid.Empty ? Guid.NewGuid() : request.Id, Name = request.Name, Race = request.Race, Class = request.Class, Role = CharacterRole.Protagonist, PortraitIndex = request.PortraitIndex, 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.Perks ??= new PerksData(); template.Modifiers ??= new ModifiersData(); var character = new CharacterDefinition { Id = template.Id == Guid.Empty ? Guid.NewGuid() : template.Id, Name = template.Name, Race = template.Race, Class = template.Class, Role = role, Attributes = attributesFactory.Create(template), Stats = statsFactory.Create(template), Perks = template.Perks, Modifiers = template.Modifiers }; AddStartingPerks(character, template.Perks); AddStartingModifiers(character, template.Modifiers); return character; } private void AddStartingPerks(CharacterDefinition character, PerksData perkData) { if(perkData?.perks == null || perkData.perks.Count == 0) { return; } foreach(var perkId in perkData.perks.AsValueEnumerable().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.AsValueEnumerable().Distinct()) { modifiersFactory.TryAddModifier(character, modifierId.Id); } } } }