Moar refactoring

This commit is contained in:
Sebastian Bularca
2026-03-30 01:06:02 +02:00
parent 30f319a52d
commit e7d5acac7c
10 changed files with 134 additions and 83 deletions

View File

@@ -101,7 +101,7 @@ namespace Nox.Core {
var adventureData = new AdventureData(); var adventureData = new AdventureData();
var characterBaseSettings = Addressables.LoadAssetAsync<StarterCharacterSettings>("CharacterBaseSettings").WaitForCompletion(); var characterBaseSettings = Addressables.LoadAssetAsync<StarterCharacterSettings>("CharacterBaseSettings").WaitForCompletion();
var perKRegistry = Addressables.LoadAssetAsync<PerksRegistry>("PerksRegistry ").WaitForCompletion(); var perKRegistry = Addressables.LoadAssetAsync<PerksRegistry>("PerksRegistry").WaitForCompletion();
var characterRegistry = Addressables.LoadAssetAsync<CharacterRegistry>("CharacterRegistry").WaitForCompletion(); var characterRegistry = Addressables.LoadAssetAsync<CharacterRegistry>("CharacterRegistry").WaitForCompletion();
var defaultPartySettings = Addressables.LoadAssetAsync<DefaultPartySettings>("DefaultPartySettings").WaitForCompletion(); var defaultPartySettings = Addressables.LoadAssetAsync<DefaultPartySettings>("DefaultPartySettings").WaitForCompletion();
var modifiersRegistry = Addressables.LoadAssetAsync<ModifiersRegistry>("ModifiersRegistry").WaitForCompletion(); var modifiersRegistry = Addressables.LoadAssetAsync<ModifiersRegistry>("ModifiersRegistry").WaitForCompletion();

View File

@@ -14,7 +14,7 @@ namespace Nox.Game {
} }
public EntityAttributes Create(EntityAttributes entityAttributes) { 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() ); throw new ArgumentOutOfRangeException( "attributes cannot be zero or negative.", new ArgumentException() );
} }
//TODO: Handle attributes modifiers and perks //TODO: Handle attributes modifiers and perks

View File

@@ -8,14 +8,16 @@ namespace Nox.Game {
} }
[Serializable] [Serializable]
public sealed class CharacterTemplate { public sealed class CharacterTemplate : IEntityDefinition {
public Guid id = Guid.NewGuid(); public Guid Id { get; set; } = Guid.NewGuid();
public string displayName = "New Character"; public string Name { get; set; } = "New Character";
public CharacterRace race = (CharacterRace)GetRandomInt(1, Enum.GetValues(typeof(CharacterRace)).Length-1); public CharacterRace Race { get; set; } = (CharacterRace)GetRandomInt(1, Enum.GetValues(typeof(CharacterRace)).Length-1);
public CharacterClass @class = (CharacterClass)GetRandomInt(1, Enum.GetValues(typeof(CharacterClass)).Length-1); public CharacterClass Class { get; set; } = (CharacterClass)GetRandomInt(1, Enum.GetValues(typeof(CharacterClass)).Length-1);
public EntityAttributes attributes = GetDefaultAttributes(); public CharacterRole Role { get; set; } = CharacterRole.Companion;
public PerksData perksData = new(); public EntityAttributes Attributes { get; set; } = GetDefaultAttributes();
public ModifiersData modifiersData = new(); 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 int GetRandomInt(int start, int end) => new Random().Next(start, end);
private static EntityAttributes GetDefaultAttributes() { private static EntityAttributes GetDefaultAttributes() {
@@ -33,29 +35,33 @@ namespace Nox.Game {
} }
[Serializable] [Serializable]
public sealed class CustomCharacterCreationRequest { public sealed class CustomCharacterCreationRequest : IEntityDefinition {
public Guid id = Guid.Empty; public Guid Id { get; set; }
public string displayName; public string Name { get; set; }
public CharacterRace race; public CharacterRace Race { get; set; }
public CharacterClass @class; public CharacterClass Class { get; set; }
public EntityStats stats; public CharacterRole Role { get; set; }
public EntityAttributes attributes; public EntityAttributes Attributes { get; set; }
public PerksData perks = new(); public EntityStats Stats { get; set; }
public ModifiersData modifiers = new(); public PerksData Perks { get; set; }
public ModifiersData Modifiers { get; set; }
} }
public sealed class CharacterFactory : ICharacterFactory { public sealed class CharacterFactory : ICharacterFactory {
private readonly ICharacterAttributesFactory attributesFactory; private readonly ICharacterAttributesFactory attributesFactory;
private readonly ICharacterStatsFactory statsFactory; private readonly ICharacterStatsFactory statsFactory;
private readonly IPerkFactory perkFactory; private readonly IPerkFactory perkFactory;
private readonly IModifiersFactory modifiersFactory;
public CharacterFactory( public CharacterFactory(
ICharacterAttributesFactory attributesFactory, ICharacterAttributesFactory attributesFactory,
ICharacterStatsFactory statsFactory, ICharacterStatsFactory statsFactory,
IPerkFactory perkFactory) { IPerkFactory perkFactory,
IModifiersFactory modifiersFactory) {
this.attributesFactory = attributesFactory ?? throw new ArgumentNullException(nameof(attributesFactory)); this.attributesFactory = attributesFactory ?? throw new ArgumentNullException(nameof(attributesFactory));
this.statsFactory = statsFactory ?? throw new ArgumentNullException(nameof(statsFactory)); this.statsFactory = statsFactory ?? throw new ArgumentNullException(nameof(statsFactory));
this.perkFactory = perkFactory ?? throw new ArgumentNullException(nameof(perkFactory)); this.perkFactory = perkFactory ?? throw new ArgumentNullException(nameof(perkFactory));
this.modifiersFactory = modifiersFactory ?? throw new ArgumentNullException(nameof(modifiersFactory));
} }
public CharacterDefinition CreateCustomProtagonist(CustomCharacterCreationRequest request) { public CharacterDefinition CreateCustomProtagonist(CustomCharacterCreationRequest request) {
@@ -63,22 +69,21 @@ namespace Nox.Game {
throw new ArgumentNullException(nameof(request)); throw new ArgumentNullException(nameof(request));
} }
var attributes = attributesFactory.Create(request.attributes); var attributes = attributesFactory.Create(request.Attributes);
var stats = statsFactory.Create(request.attributes); var stats = statsFactory.Create(request);
var character = new CharacterDefinition { var character = new CharacterDefinition {
ID = request.id == Guid.Empty ? Guid.NewGuid() : request.id, Id = request.Id == Guid.Empty ? Guid.NewGuid() : request.Id,
Name = request.displayName, Name = request.Name,
Race = request.race, Race = request.Race,
Class = request.@class, Class = request.Class,
Role = CharacterRole.Protagonist, Role = CharacterRole.Protagonist,
Attributes = attributes, Attributes = attributes,
Stats = stats, Perks = request.Perks ?? new PerksData(),
Perks = request.perks ?? new PerksData(), Modifiers = request.Modifiers ?? new ModifiersData()
Modifiers = request.modifiers ?? new ModifiersData()
}; };
AddStartingPerks(character, request.perks); AddStartingPerks(character, request.Perks);
return character; return character;
} }
@@ -87,23 +92,23 @@ namespace Nox.Game {
throw new ArgumentNullException(nameof(template)); throw new ArgumentNullException(nameof(template));
} }
template.perksData ??= new PerksData(); template.Perks ??= new PerksData();
template.modifiersData ??= new ModifiersData(); template.Modifiers ??= new ModifiersData();
var character = new CharacterDefinition { var character = new CharacterDefinition {
ID = template.id == Guid.Empty ? Guid.NewGuid() : template.id, Id = template.Id == Guid.Empty ? Guid.NewGuid() : template.Id,
Name = template.displayName, Name = template.Name,
Race = template.race, Race = template.Race,
Class = template.@class, Class = template.Class,
Role = role, Role = role,
Attributes = attributesFactory.Create(template.attributes), Attributes = attributesFactory.Create(template.Attributes),
Stats = statsFactory.Create(template.attributes), Stats = statsFactory.Create(template),
Perks = template.perksData, Perks = template.Perks,
Modifiers = template.modifiersData Modifiers = template.Modifiers
}; };
AddStartingPerks(character, template.perksData); AddStartingPerks(character, template.Perks);
AddStartingModifiers(character, template.modifiersData); AddStartingModifiers(character, template.Modifiers);
return character; return character;
} }
@@ -123,7 +128,7 @@ namespace Nox.Game {
} }
foreach(var modifierId in modifiersData.modifiers.Distinct()) { foreach(var modifierId in modifiersData.modifiers.Distinct()) {
perkFactory.TryAddPerk(character, modifierId.Id); modifiersFactory.TryAddModifier(character, modifierId.Id);
} }
} }
} }

View File

@@ -1,9 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace Nox.Game { namespace Nox.Game {
public interface ICharacterStatsFactory { public interface ICharacterStatsFactory {
EntityStats Create(EntityAttributes attributes); EntityStats Create(IEntityDefinition entityDefinition);
} }
public sealed class CharacterStatsFactory : ICharacterStatsFactory { public sealed class CharacterStatsFactory : ICharacterStatsFactory {
@@ -13,19 +14,27 @@ namespace Nox.Game {
this.characterRegistry = characterRegistry; this.characterRegistry = characterRegistry;
} }
public EntityStats Create(EntityAttributes attributes) { public EntityStats Create(IEntityDefinition entityDefinition) {
if(attributes.attributes.All(a => a.value != 0)) { 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() ); 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; return new EntityStats {
// int maxStamina = options.baseStamina + stats = new[] {
// attributes.might * options.mightStaminaBonus + new Stat(StatType.Health, health)
// attributes.knowledge * options.knowledgeStaminaBonus; }
};
return new EntityStats { }; }
private int ResolveModifiersValue(IEnumerable<ModifierDefinition> healthModifiers, EntityAttributes attributes) {
throw new NotImplementedException();
} }
} }
} }

View File

@@ -11,7 +11,7 @@ namespace Nox.Game {
IModifiersFactory modifiersFactory = new ModifiersFactory(modifiersRegistry); IModifiersFactory modifiersFactory = new ModifiersFactory(modifiersRegistry);
ICharacterAttributesFactory attributesFactory = new CharacterAttributesFactory(characterRegistry); ICharacterAttributesFactory attributesFactory = new CharacterAttributesFactory(characterRegistry);
ICharacterStatsFactory statsFactory = new CharacterStatsFactory(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); IPartyFactory partyFactory = new PartyFactory(starterCharacterSettings);
return new CharacterSystems(perkFactory, modifiersFactory, characterFactory, partyFactory); return new CharacterSystems(perkFactory, modifiersFactory, characterFactory, partyFactory);

View File

@@ -6,7 +6,7 @@ using UnityEngine;
namespace Nox.Game { namespace Nox.Game {
public interface IEntityDefinition { public interface IEntityDefinition {
Guid ID { get; } Guid Id { get; }
string Name { get; } string Name { get; }
CharacterRace Race { get; } CharacterRace Race { get; }
CharacterClass Class { get; } CharacterClass Class { get; }
@@ -56,7 +56,7 @@ namespace Nox.Game {
} }
[Serializable] [Serializable]
public sealed class Stat { public sealed record Stat {
public StatType stat; public StatType stat;
public int value; public int value;
public Stat(StatType stat, int value) { public Stat(StatType stat, int value) {
@@ -82,11 +82,17 @@ namespace Nox.Game {
public static EntityAttributes operator +(EntityAttributes a, EntityAttributes b) { public static EntityAttributes operator +(EntityAttributes a, EntityAttributes b) {
return new EntityAttributes { return new EntityAttributes {
attributes = a.attributes attributes = a.attributes
.Select(attr => new Attribute(attr.attribute, attr.value + b.attributes .Select(attr => {
.First(attr2 => attr2.attribute == attr.attribute).value)) var match = b.attributes?.FirstOrDefault(attr2 => attr2.attribute == attr.attribute);
return new Attribute(attr.attribute, attr.value + (match?.value ?? 0));
})
.ToArray() .ToArray()
}; };
} }
public int GetValue(AttributeType attributeType) {
return attributes.First(attr => attr.attribute == attributeType).value;
}
} }
[Serializable] [Serializable]
@@ -100,7 +106,7 @@ namespace Nox.Game {
[Serializable] [Serializable]
public class CharacterDefinition : IEntityDefinition { public class CharacterDefinition : IEntityDefinition {
public Guid ID { get; set; } public Guid Id { get; set; }
[field: SerializeField] public string Name { get; set; } [field: SerializeField] public string Name { get; set; }
[field: SerializeField] public CharacterRace Race { get; set; } [field: SerializeField] public CharacterRace Race { get; set; }
[field: SerializeField] public CharacterClass Class { get; set; } [field: SerializeField] public CharacterClass Class { get; set; }
@@ -112,15 +118,34 @@ namespace Nox.Game {
public CharacterDefinition Clone() { public CharacterDefinition Clone() {
return new CharacterDefinition { return new CharacterDefinition {
ID = Guid.NewGuid(), Id = Guid.NewGuid(),
Name = Name, Name = Name,
Role = Role, Role = Role,
Race = Race, Race = Race,
Class = Class, Class = Class,
Attributes = Attributes, Attributes = new EntityAttributes {
Stats = Stats, attributes = Attributes?.attributes?.Select(a => new Attribute(a.attribute, a.value)).ToArray()
Perks = Perks, },
Modifiers = Modifiers 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()
}
}; };
} }

View File

@@ -1,6 +1,5 @@
using Jovian.InspectorTools; using Jovian.InspectorTools;
using Jovian.Logger; using Jovian.Logger;
using Mono.Cecil;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -85,9 +84,13 @@ namespace Nox.Game {
return false; return false;
} }
character.Perks.perks.Add(new PerkDefinition { character.Modifiers.modifiers.Add(new ModifierDefinition {
Id = modifier.Id, Id = modifier.Id,
Name = modifier.Name Name = modifier.Name,
StatType = modifier.StatType,
AttributeType = modifier.AttributeType,
Operation = modifier.Operation,
Value = modifier.Value
}); });
return true; return true;

View File

@@ -4,31 +4,39 @@ namespace Nox.Game {
public class PartyCreatorModel { public class PartyCreatorModel {
private readonly ICharacterFactory characterFactory; private readonly ICharacterFactory characterFactory;
private readonly IPartyFactory partyFactory; private readonly IPartyFactory partyFactory;
private readonly DefaultPartySettings defaultPartySettings;
public PartyCreatorModel(ICharacterFactory characterFactory, IPartyFactory partyFactory, DefaultPartySettings defaultPartySettings) { public PartyCreatorModel(ICharacterFactory characterFactory, IPartyFactory partyFactory, DefaultPartySettings defaultPartySettings) {
this.characterFactory = characterFactory; this.characterFactory = characterFactory;
this.partyFactory = partyFactory; this.partyFactory = partyFactory;
this.defaultPartySettings = defaultPartySettings;
} }
public PartyDefinition CreatePartyForNewRun(int companionCount) { public PartyDefinition CreatePartyForNewRun(int companionCount) {
var protagonist = characterFactory.CreateCustomProtagonist(new CustomCharacterCreationRequest { var protagonist = characterFactory.CreateCustomProtagonist(new CustomCharacterCreationRequest {
displayName = "John Doe", Name = "John Doe",
attributes = new EntityAttributes(), Attributes = new EntityAttributes {
perks = new PerksData(){ attributes = new[] {
perks = new List<PerkDefinition>() 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(); var rookAttributes = new EntityAttributes {
rook_attributes.attributes = new[] { attributes = new[] {
new Attribute(AttributeType.Might, 6), new Attribute(AttributeType.Might, 6),
new Attribute(AttributeType.Knowledge, 2), new Attribute(AttributeType.Knowledge, 2),
new Attribute(AttributeType.Perception, 2), new Attribute(AttributeType.Perception, 2),
new Attribute(AttributeType.Reflex, 4) new Attribute(AttributeType.Reflex, 4)
}
}; };
CharacterTemplate[] companionTemplates = { CharacterTemplate[] companionTemplates = {
new() { new() {
displayName = "Rook", Name = "Rook",
attributes = rook_attributes, Attributes = rookAttributes,
perksData = new PerksData(){ Perks = new PerksData(){
perks = new List<PerkDefinition>() perks = new List<PerkDefinition>()
} }
} }

View File

@@ -50,8 +50,8 @@ namespace Nox.Game {
} }
var uniqueIds = party.members var uniqueIds = party.members
.Where(m => m.ID != Guid.Empty) .Where(m => m.Id != Guid.Empty)
.Select(m => m.ID) .Select(m => m.Id)
.Distinct() .Distinct()
.Count(); .Count();
if(uniqueIds != party.members.Count) { if(uniqueIds != party.members.Count) {

View File

@@ -84,7 +84,8 @@ namespace Nox.Game {
character.Perks.perks.Add(new PerkDefinition { character.Perks.perks.Add(new PerkDefinition {
Id = perk.Id, Id = perk.Id,
Name = perk.Name Name = perk.Name,
Modifiers = perk.Modifiers
}); });
return true; return true;