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

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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<ModifierDefinition> healthModifiers, EntityAttributes attributes) {
throw new NotImplementedException();
}
}
}

View File

@@ -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);

View File

@@ -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()
}
};
}

View File

@@ -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;

View File

@@ -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<PerkDefinition>()
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[] {
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<PerkDefinition>()
}
}

View File

@@ -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) {

View File

@@ -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;