using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using ZLinq; using UnityEngine; namespace Nox.Game { public interface IEntityDefinition { Guid Id { get; } string Name { get; } int PortraitIndex { get; } CharacterRace Race { get; } CharacterClass Class { get; } CharacterRole Role { get; } EntityAttributes Attributes { get; } EntityStats Stats { get; } PerksData Perks { get; } ModifiersData Modifiers { get; } } public enum StatType { None, Health, Mana, Level, Experience } public enum AttributeType { None, Might, Reflex, Knowledge, Perception } public enum CombatScoreType { None, ATK, DEF, INIT, SPD, RES } public enum CharacterRole { None, Protagonist, Companion } public enum CharacterClass { None, Warrior, Rogue, Mage, Herald } public enum CharacterRace { None, Human, DarkElf, Tunneler } [Serializable] public sealed record Stat { public StatType stat; public int value; public Stat(StatType stat, int value) { this.stat = stat; this.value = value; } } [Serializable] public sealed record Attribute { public AttributeType attribute; public int value; public Attribute(AttributeType attribute, int value) { this.attribute = attribute; this.value = value; } } [Serializable] public sealed class EntityAttributes { public Attribute[] attributes; public static EntityAttributes operator +(EntityAttributes a, EntityAttributes b) { return new EntityAttributes { attributes = a.attributes.AsValueEnumerable() .Select(attr => { var match = b.attributes?.AsValueEnumerable().FirstOrDefault(attr2 => attr2.attribute == attr.attribute); return new Attribute(attr.attribute, attr.value + (match?.value ?? 0)); }) .ToArray() }; } public int GetValue(AttributeType attributeType) { return attributes.AsValueEnumerable().First(attr => attr.attribute == attributeType).value; } public override string ToString() { return $"Attributes: {string.Join(", ", attributes.Select(attr => $"{attr.attribute}: {attr.value}"))}"; } } [Serializable] public sealed class EntityStats { public Stat[] stats; public int GetValue(StatType statType) { if(stats == null) { return 0; } var match = stats.AsValueEnumerable().FirstOrDefault(stat => stat.stat == statType); return match?.value ?? 0; } public override string ToString() { return $"Stats: {string.Join(", ", stats.Select(stat => $"{stat.stat}: {stat.value}"))}"; } } [Serializable] public class CharacterDefinition : IEntityDefinition { public Guid Id { get; set; } public int PortraitIndex { get; set; } = 0; [field: SerializeField] public string Name { get; set; } [field: SerializeField] public CharacterRace Race { get; set; } [field: SerializeField] public CharacterClass Class { get; set; } [field: SerializeField] public CharacterRole Role { get; set; } [field: SerializeField] public EntityAttributes Attributes { get; set; } [field: SerializeField] public EntityStats Stats { get; set; } [field: SerializeField] public PerksData Perks { get; set; } [field: SerializeField] public ModifiersData Modifiers { get; set; } public CharacterDefinition Clone() { return new CharacterDefinition { Id = Guid.NewGuid(), Name = Name, Role = Role, Race = Race, Class = Class, Attributes = new EntityAttributes { attributes = Attributes?.attributes?.AsValueEnumerable().Select(a => new Attribute(a.attribute, a.value)).ToArray() }, Stats = new EntityStats { stats = Stats?.stats?.AsValueEnumerable().Select(s => new Stat(s.stat, s.value)).ToArray() }, Perks = new PerksData { perks = Perks?.perks?.AsValueEnumerable().Select(p => new PerkDefinition { Id = p.Id, Name = p.Name, Modifiers = p.Modifiers }).ToList() ?? new List() }, Modifiers = new ModifiersData { modifiers = Modifiers?.modifiers?.AsValueEnumerable().Select(m => new ModifierDefinition { Id = m.Id, Name = m.Name, Target = m.Target, ScalingSource = m.ScalingSource, Operation = m.Operation, Value = m.Value, Requirements = m.Requirements?.ToList() ?? new List() }).ToList() ?? new List() } }; } } [Serializable] public sealed class PartyDefinition { public int maxPartySize; public List members = new(); [JsonIgnore] public CharacterDefinition Protagonist => members.AsValueEnumerable().FirstOrDefault(m => m.Role == CharacterRole.Protagonist); [JsonIgnore] public IReadOnlyList Companions => members.AsValueEnumerable().Where(m => m.Role == CharacterRole.Companion).ToList(); } }