forked from Shardstone/trail-into-darkness
160 lines
5.7 KiB
C#
160 lines
5.7 KiB
C#
using Jovian.Logger;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using ZLinq;
|
|
using UnityEngine;
|
|
|
|
namespace Nox.Game {
|
|
public interface IModifier {
|
|
string Name { get; }
|
|
Guid Id { get; }
|
|
ModifierTarget Target { get; }
|
|
ModifierTarget ScalingSource { get; }
|
|
ModifierOperation Operation { get; }
|
|
float Value { get; }
|
|
IReadOnlyList<ModifierRequirement> Requirements { get; }
|
|
}
|
|
|
|
public interface IModifiersFactory {
|
|
IReadOnlyCollection<IModifier> GetAll();
|
|
IModifier GetById(Guid modifierId);
|
|
IReadOnlyCollection<IModifier> GetModifiersFor(IEntityDefinition character);
|
|
bool TryAddModifier(IEntityDefinition character, Guid modiferId);
|
|
}
|
|
|
|
public enum ModifierOperation {
|
|
None,
|
|
Flat,
|
|
Addition,
|
|
Multiplication,
|
|
Percentage
|
|
}
|
|
|
|
public enum ModifierTargetType {
|
|
None,
|
|
Attribute,
|
|
Stat,
|
|
CombatScore
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class ModifierTarget {
|
|
[field: SerializeField] public ModifierTargetType Type { get; set; }
|
|
[field: SerializeField] public AttributeType AttributeType { get; set; }
|
|
[field: SerializeField] public StatType StatType { get; set; }
|
|
[field: SerializeField] public CombatScoreType CombatScoreType { get; set; }
|
|
|
|
public bool Matches(StatType statType) {
|
|
return Type == ModifierTargetType.Stat && StatType == statType;
|
|
}
|
|
|
|
public bool Matches(AttributeType attributeType) {
|
|
return Type == ModifierTargetType.Attribute && AttributeType == attributeType;
|
|
}
|
|
|
|
public bool Matches(CombatScoreType combatScoreType) {
|
|
return Type == ModifierTargetType.CombatScore && CombatScoreType == combatScoreType;
|
|
}
|
|
|
|
public bool IsSet => Type != ModifierTargetType.None;
|
|
|
|
public override string ToString() {
|
|
return Type switch {
|
|
ModifierTargetType.Attribute => AttributeType.ToString(),
|
|
ModifierTargetType.Stat => StatType.ToString(),
|
|
ModifierTargetType.CombatScore => CombatScoreType.ToString(),
|
|
_ => "None"
|
|
};
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class ModifierRequirement {
|
|
[field: SerializeField] public AttributeType Attribute { get; set; }
|
|
[field: SerializeField] public int MinimumValue { get; set; }
|
|
|
|
public bool IsMet(EntityAttributes attributes) {
|
|
if(Attribute == AttributeType.None || attributes?.attributes == null) {
|
|
return true;
|
|
}
|
|
return attributes.GetValue(Attribute) >= MinimumValue;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class ModifierDefinition : IModifier {
|
|
[field: SerializeField] public string Name { get; set; }
|
|
public Guid Id { get; set; } = Guid.NewGuid();
|
|
[field: SerializeField] public ModifierTarget Target { get; set; }
|
|
[field: SerializeField] public ModifierTarget ScalingSource { get; set; }
|
|
[field: SerializeField] public ModifierOperation Operation { get; set; }
|
|
[field: SerializeField] public float Value { get; set; }
|
|
[field: SerializeField] public List<ModifierRequirement> Requirements { get; set; } = new();
|
|
|
|
IReadOnlyList<ModifierRequirement> IModifier.Requirements => Requirements;
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class ModifiersData {
|
|
public List<ModifierDefinition> modifiers = new();
|
|
|
|
public override string ToString() {
|
|
return $"Modifiers: {string.Join(", ", modifiers.Select(modifier => $"{modifier.Name}"))}";
|
|
}
|
|
}
|
|
|
|
public class ModifiersFactory : IModifiersFactory {
|
|
private readonly ModifiersRegistry modifiersRegistry;
|
|
private readonly Dictionary<Guid, IModifier> modifierPool = new();
|
|
|
|
public ModifiersFactory(ModifiersRegistry modifiersRegistry) {
|
|
this.modifiersRegistry = modifiersRegistry;
|
|
var allAvailableModifiers = modifiersRegistry.modifiersData;
|
|
foreach(var modifier in allAvailableModifiers.modifiers) {
|
|
modifierPool.Add(modifier.Id, modifier);
|
|
}
|
|
}
|
|
|
|
public IReadOnlyCollection<IModifier> GetAll() {
|
|
return modifiersRegistry.modifiersData.modifiers;
|
|
}
|
|
public IModifier GetById(Guid modifierId) {
|
|
return modifiersRegistry.modifiersData.modifiers.AsValueEnumerable().FirstOrDefault(m => m.Id == modifierId);
|
|
}
|
|
public IReadOnlyCollection<IModifier> GetModifiersFor(IEntityDefinition character) {
|
|
return character.Modifiers.modifiers;
|
|
}
|
|
public bool TryAddModifier(IEntityDefinition character, Guid modifierId) {
|
|
if(character == null) {
|
|
return false;
|
|
}
|
|
|
|
if(modifierId == Guid.Empty) {
|
|
GlobalLogger.LogException("Cannot add a modifier with an empty ID!", LogCategory.GameLogic);
|
|
return false;
|
|
}
|
|
|
|
if(character.Modifiers.modifiers.AsValueEnumerable().Any(p => p != null && p.Id == modifierId)) {
|
|
return false;
|
|
}
|
|
|
|
if(!modifierPool.TryGetValue(modifierId, out var modifier)) {
|
|
return false;
|
|
}
|
|
|
|
character.Modifiers.modifiers.Add(new ModifierDefinition {
|
|
Id = modifier.Id,
|
|
Name = modifier.Name,
|
|
Target = modifier.Target,
|
|
ScalingSource = modifier.ScalingSource,
|
|
Operation = modifier.Operation,
|
|
Value = modifier.Value,
|
|
Requirements = modifier.Requirements?.ToList() ?? new List<ModifierRequirement>()
|
|
});
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|