diff --git a/Assets/Code/Core/EntryPoint.cs b/Assets/Code/Core/EntryPoint.cs index 06ba1a8..1b5de39 100644 --- a/Assets/Code/Core/EntryPoint.cs +++ b/Assets/Code/Core/EntryPoint.cs @@ -101,7 +101,7 @@ namespace Nox.Core { var adventureData = new AdventureData(); var characterBaseSettings = Addressables.LoadAssetAsync("CharacterBaseSettings").WaitForCompletion(); - var perKRegistry = Addressables.LoadAssetAsync("PerksRegistry ").WaitForCompletion(); + var perKRegistry = Addressables.LoadAssetAsync("PerksRegistry").WaitForCompletion(); var characterRegistry = Addressables.LoadAssetAsync("CharacterRegistry").WaitForCompletion(); var defaultPartySettings = Addressables.LoadAssetAsync("DefaultPartySettings").WaitForCompletion(); var modifiersRegistry = Addressables.LoadAssetAsync("ModifiersRegistry").WaitForCompletion(); diff --git a/Assets/Code/GameState/Entities/CharacterAttributesFactory.cs b/Assets/Code/GameState/Entities/CharacterAttributesFactory.cs index b1d02d3..d5ae9da 100644 --- a/Assets/Code/GameState/Entities/CharacterAttributesFactory.cs +++ b/Assets/Code/GameState/Entities/CharacterAttributesFactory.cs @@ -14,7 +14,7 @@ namespace Nox.Game { } public EntityAttributes Create(EntityAttributes entityAttributes) { - if(entityAttributes.attributes.All(a => a.value != 0)) { + if(entityAttributes.attributes.Any(a => a.value <= 0)) { throw new ArgumentOutOfRangeException( "attributes cannot be zero or negative.", new ArgumentException() ); } //TODO: Handle attributes modifiers and perks diff --git a/Assets/Code/GameState/Entities/CharacterFactory.cs b/Assets/Code/GameState/Entities/CharacterFactory.cs index 7180b2f..bdc9185 100644 --- a/Assets/Code/GameState/Entities/CharacterFactory.cs +++ b/Assets/Code/GameState/Entities/CharacterFactory.cs @@ -8,14 +8,16 @@ namespace Nox.Game { } [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(); + public sealed class CharacterTemplate : IEntityDefinition { + public Guid Id { get; set; } = Guid.NewGuid(); + public string Name { get; set; } = "New Character"; + 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(); + 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() { @@ -33,29 +35,33 @@ namespace Nox.Game { } [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 CustomCharacterCreationRequest : IEntityDefinition { + public Guid Id { get; set; } + public string Name { get; set; } + public CharacterRace Race { get; set; } + public CharacterClass Class { get; set; } + public CharacterRole Role { get; set; } + public EntityAttributes Attributes { get; set; } + public EntityStats Stats { get; set; } + public PerksData Perks { get; set; } + public ModifiersData Modifiers { get; set; } } 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) { + 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 CreateCustomProtagonist(CustomCharacterCreationRequest request) { @@ -63,22 +69,21 @@ namespace Nox.Game { throw new ArgumentNullException(nameof(request)); } - var attributes = attributesFactory.Create(request.attributes); - var stats = statsFactory.Create(request.attributes); + var attributes = attributesFactory.Create(request.Attributes); + var stats = statsFactory.Create(request); var character = new CharacterDefinition { - ID = request.id == Guid.Empty ? Guid.NewGuid() : request.id, - Name = request.displayName, - Race = request.race, - Class = request.@class, + Id = request.Id == Guid.Empty ? Guid.NewGuid() : request.Id, + Name = request.Name, + Race = request.Race, + Class = request.Class, Role = CharacterRole.Protagonist, Attributes = attributes, - Stats = stats, - Perks = request.perks ?? new PerksData(), - Modifiers = request.modifiers ?? new ModifiersData() + Perks = request.Perks ?? new PerksData(), + Modifiers = request.Modifiers ?? new ModifiersData() }; - AddStartingPerks(character, request.perks); + AddStartingPerks(character, request.Perks); return character; } @@ -87,23 +92,23 @@ namespace Nox.Game { throw new ArgumentNullException(nameof(template)); } - template.perksData ??= new PerksData(); - template.modifiersData ??= new ModifiersData(); + template.Perks ??= new PerksData(); + template.Modifiers ??= new ModifiersData(); var character = new CharacterDefinition { - ID = template.id == Guid.Empty ? Guid.NewGuid() : template.id, - Name = template.displayName, - Race = template.race, - Class = template.@class, + Id = template.Id == Guid.Empty ? Guid.NewGuid() : template.Id, + Name = template.Name, + Race = template.Race, + Class = template.Class, Role = role, - Attributes = attributesFactory.Create(template.attributes), - Stats = statsFactory.Create(template.attributes), - Perks = template.perksData, - Modifiers = template.modifiersData + Attributes = attributesFactory.Create(template.Attributes), + Stats = statsFactory.Create(template), + Perks = template.Perks, + Modifiers = template.Modifiers }; - AddStartingPerks(character, template.perksData); - AddStartingModifiers(character, template.modifiersData); + AddStartingPerks(character, template.Perks); + AddStartingModifiers(character, template.Modifiers); return character; } @@ -123,7 +128,7 @@ namespace Nox.Game { } foreach(var modifierId in modifiersData.modifiers.Distinct()) { - perkFactory.TryAddPerk(character, modifierId.Id); + modifiersFactory.TryAddModifier(character, modifierId.Id); } } } diff --git a/Assets/Code/GameState/Entities/CharacterStatsFactory.cs b/Assets/Code/GameState/Entities/CharacterStatsFactory.cs index de11245..d161043 100644 --- a/Assets/Code/GameState/Entities/CharacterStatsFactory.cs +++ b/Assets/Code/GameState/Entities/CharacterStatsFactory.cs @@ -1,9 +1,10 @@ using System; +using System.Collections.Generic; using System.Linq; namespace Nox.Game { public interface ICharacterStatsFactory { - EntityStats Create(EntityAttributes attributes); + EntityStats Create(IEntityDefinition entityDefinition); } public sealed class CharacterStatsFactory : ICharacterStatsFactory { @@ -13,19 +14,27 @@ namespace Nox.Game { this.characterRegistry = characterRegistry; } - public EntityStats Create(EntityAttributes attributes) { - if(attributes.attributes.All(a => a.value != 0)) { + public EntityStats Create(IEntityDefinition entityDefinition) { + var attributes = entityDefinition.Attributes; + var stats = entityDefinition.Stats; + var perks = entityDefinition.Perks; + var modifiers = entityDefinition.Modifiers; + + if(attributes.attributes.Any(a => a.value <= 0)) { throw new ArgumentOutOfRangeException( "attributes cannot be zero or negative.", new ArgumentException() ); } - //TODO: Create stats based on attributes + var healthModifiers = modifiers.modifiers.Where(m => m.StatType == StatType.Health); + var health = stats.GetValue(StatType.Health) + attributes.GetValue(AttributeType.Might) * ResolveModifiersValue(healthModifiers, attributes); - // int maxHealth = options.baseHealth + attributes.might * options.mightHealthBonus; - // int maxStamina = options.baseStamina + - // attributes.might * options.mightStaminaBonus + - // attributes.knowledge * options.knowledgeStaminaBonus; - - return new EntityStats { }; + return new EntityStats { + stats = new[] { + new Stat(StatType.Health, health) + } + }; + } + private int ResolveModifiersValue(IEnumerable healthModifiers, EntityAttributes attributes) { + throw new NotImplementedException(); } } } diff --git a/Assets/Code/GameState/Entities/DefaultCharacterSystemsFactory.cs b/Assets/Code/GameState/Entities/DefaultCharacterSystemsFactory.cs index a3439b6..68235e7 100644 --- a/Assets/Code/GameState/Entities/DefaultCharacterSystemsFactory.cs +++ b/Assets/Code/GameState/Entities/DefaultCharacterSystemsFactory.cs @@ -11,7 +11,7 @@ namespace Nox.Game { IModifiersFactory modifiersFactory = new ModifiersFactory(modifiersRegistry); ICharacterAttributesFactory attributesFactory = new CharacterAttributesFactory(characterRegistry); ICharacterStatsFactory statsFactory = new CharacterStatsFactory(characterRegistry); - ICharacterFactory characterFactory = new CharacterFactory(attributesFactory, statsFactory, perkFactory); + ICharacterFactory characterFactory = new CharacterFactory(attributesFactory, statsFactory, perkFactory, modifiersFactory); IPartyFactory partyFactory = new PartyFactory(starterCharacterSettings); return new CharacterSystems(perkFactory, modifiersFactory, characterFactory, partyFactory); diff --git a/Assets/Code/GameState/Entities/EntitiesDefinitions.cs b/Assets/Code/GameState/Entities/EntitiesDefinitions.cs index d1d6de7..f135a54 100644 --- a/Assets/Code/GameState/Entities/EntitiesDefinitions.cs +++ b/Assets/Code/GameState/Entities/EntitiesDefinitions.cs @@ -6,7 +6,7 @@ using UnityEngine; namespace Nox.Game { public interface IEntityDefinition { - Guid ID { get; } + Guid Id { get; } string Name { get; } CharacterRace Race { get; } CharacterClass Class { get; } @@ -56,7 +56,7 @@ namespace Nox.Game { } [Serializable] - public sealed class Stat { + public sealed record Stat { public StatType stat; public int value; public Stat(StatType stat, int value) { @@ -82,11 +82,17 @@ namespace Nox.Game { public static EntityAttributes operator +(EntityAttributes a, EntityAttributes b) { return new EntityAttributes { attributes = a.attributes - .Select(attr => new Attribute(attr.attribute, attr.value + b.attributes - .First(attr2 => attr2.attribute == attr.attribute).value)) + .Select(attr => { + var match = b.attributes?.FirstOrDefault(attr2 => attr2.attribute == attr.attribute); + return new Attribute(attr.attribute, attr.value + (match?.value ?? 0)); + }) .ToArray() }; } + + public int GetValue(AttributeType attributeType) { + return attributes.First(attr => attr.attribute == attributeType).value; + } } [Serializable] @@ -100,7 +106,7 @@ namespace Nox.Game { [Serializable] public class CharacterDefinition : IEntityDefinition { - public Guid ID { get; set; } + public Guid Id { get; set; } [field: SerializeField] public string Name { get; set; } [field: SerializeField] public CharacterRace Race { get; set; } [field: SerializeField] public CharacterClass Class { get; set; } @@ -112,15 +118,34 @@ namespace Nox.Game { public CharacterDefinition Clone() { return new CharacterDefinition { - ID = Guid.NewGuid(), + Id = Guid.NewGuid(), Name = Name, Role = Role, Race = Race, Class = Class, - Attributes = Attributes, - Stats = Stats, - Perks = Perks, - Modifiers = Modifiers + Attributes = new EntityAttributes { + attributes = Attributes?.attributes?.Select(a => new Attribute(a.attribute, a.value)).ToArray() + }, + Stats = new EntityStats { + stats = Stats?.stats?.Select(s => new Stat(s.stat, s.value)).ToArray() + }, + Perks = new PerksData { + perks = Perks?.perks?.Select(p => new PerkDefinition { + Id = p.Id, + Name = p.Name, + Modifiers = p.Modifiers + }).ToList() ?? new() + }, + Modifiers = new ModifiersData { + modifiers = Modifiers?.modifiers?.Select(m => new ModifierDefinition { + Id = m.Id, + Name = m.Name, + StatType = m.StatType, + AttributeType = m.AttributeType, + Operation = m.Operation, + Value = m.Value + }).ToList() ?? new() + } }; } diff --git a/Assets/Code/GameState/Entities/ModifiersFactory.cs b/Assets/Code/GameState/Entities/ModifiersFactory.cs index f486279..29f95b2 100644 --- a/Assets/Code/GameState/Entities/ModifiersFactory.cs +++ b/Assets/Code/GameState/Entities/ModifiersFactory.cs @@ -1,6 +1,5 @@ using Jovian.InspectorTools; using Jovian.Logger; -using Mono.Cecil; using System; using System.Collections.Generic; using System.Linq; @@ -85,9 +84,13 @@ namespace Nox.Game { return false; } - character.Perks.perks.Add(new PerkDefinition { + character.Modifiers.modifiers.Add(new ModifierDefinition { Id = modifier.Id, - Name = modifier.Name + Name = modifier.Name, + StatType = modifier.StatType, + AttributeType = modifier.AttributeType, + Operation = modifier.Operation, + Value = modifier.Value }); return true; diff --git a/Assets/Code/GameState/Entities/PartyCreatorModel.cs b/Assets/Code/GameState/Entities/PartyCreatorModel.cs index 554d603..8c2df2c 100644 --- a/Assets/Code/GameState/Entities/PartyCreatorModel.cs +++ b/Assets/Code/GameState/Entities/PartyCreatorModel.cs @@ -4,31 +4,39 @@ namespace Nox.Game { public class PartyCreatorModel { private readonly ICharacterFactory characterFactory; private readonly IPartyFactory partyFactory; + private readonly DefaultPartySettings defaultPartySettings; public PartyCreatorModel(ICharacterFactory characterFactory, IPartyFactory partyFactory, DefaultPartySettings defaultPartySettings) { this.characterFactory = characterFactory; this.partyFactory = partyFactory; + this.defaultPartySettings = defaultPartySettings; } public PartyDefinition CreatePartyForNewRun(int companionCount) { var protagonist = characterFactory.CreateCustomProtagonist(new CustomCharacterCreationRequest { - displayName = "John Doe", - attributes = new EntityAttributes(), - perks = new PerksData(){ - perks = new List() + Name = "John Doe", + Attributes = new EntityAttributes { + attributes = new[] { + new Attribute(AttributeType.Might, 3), + new Attribute(AttributeType.Reflex, 3), + new Attribute(AttributeType.Knowledge, 3), + new Attribute(AttributeType.Perception, 3) + } } }); - var rook_attributes = new EntityAttributes(); - rook_attributes.attributes = new[] { - new Attribute(AttributeType.Might, 6), - new Attribute(AttributeType.Knowledge, 2), - new Attribute(AttributeType.Perception, 2), - new Attribute(AttributeType.Reflex, 4) + var rookAttributes = new EntityAttributes { + attributes = new[] { + new Attribute(AttributeType.Might, 6), + new Attribute(AttributeType.Knowledge, 2), + new Attribute(AttributeType.Perception, 2), + new Attribute(AttributeType.Reflex, 4) + } }; + CharacterTemplate[] companionTemplates = { new() { - displayName = "Rook", - attributes = rook_attributes, - perksData = new PerksData(){ + Name = "Rook", + Attributes = rookAttributes, + Perks = new PerksData(){ perks = new List() } } diff --git a/Assets/Code/GameState/Entities/PartyFactory.cs b/Assets/Code/GameState/Entities/PartyFactory.cs index 1ae7805..b6cab7c 100644 --- a/Assets/Code/GameState/Entities/PartyFactory.cs +++ b/Assets/Code/GameState/Entities/PartyFactory.cs @@ -50,8 +50,8 @@ namespace Nox.Game { } var uniqueIds = party.members - .Where(m => m.ID != Guid.Empty) - .Select(m => m.ID) + .Where(m => m.Id != Guid.Empty) + .Select(m => m.Id) .Distinct() .Count(); if(uniqueIds != party.members.Count) { diff --git a/Assets/Code/GameState/Entities/PerkFactory.cs b/Assets/Code/GameState/Entities/PerkFactory.cs index 52d43c2..999ab91 100644 --- a/Assets/Code/GameState/Entities/PerkFactory.cs +++ b/Assets/Code/GameState/Entities/PerkFactory.cs @@ -84,7 +84,8 @@ namespace Nox.Game { character.Perks.perks.Add(new PerkDefinition { Id = perk.Id, - Name = perk.Name + Name = perk.Name, + Modifiers = perk.Modifiers }); return true;