forked from Shardstone/trail-into-darkness
131 lines
4.4 KiB
C#
131 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using ZLinq;
|
|
|
|
namespace Nox.Game {
|
|
|
|
public interface IModifierResolver {
|
|
int Resolve(int baseValue, IEnumerable<IModifier> modifiers);
|
|
IEnumerable<IModifier> CollectModifiers(IEntityDefinition entity, StatType statType);
|
|
IEnumerable<IModifier> CollectModifiers(IEntityDefinition entity, AttributeType attributeType);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Collects modifiers from an entity's direct modifiers and perk-granted modifiers,
|
|
/// then resolves them against a base value.
|
|
///
|
|
/// Resolution order:
|
|
/// 1. Flat — sum of all flat values replaces the base
|
|
/// 2. Addition — summed and added to the running total
|
|
/// 3. Percentage — summed into a single multiplier applied to the post-addition total
|
|
/// 4. Multiplication — each factor applied sequentially to the running total
|
|
/// </summary>
|
|
public sealed class ModifierResolver : IModifierResolver {
|
|
public int Resolve(int baseValue, IEnumerable<IModifier> modifiers) {
|
|
if(modifiers == null) {
|
|
return baseValue;
|
|
}
|
|
|
|
float flatSum = 0f;
|
|
float addSum = 0f;
|
|
float pctSum = 0f;
|
|
var mulValues = new List<float>();
|
|
var hasFlat = false;
|
|
|
|
foreach(var m in modifiers) {
|
|
if(m == null || m.Operation == ModifierOperation.None) {
|
|
continue;
|
|
}
|
|
|
|
switch(m.Operation) {
|
|
case ModifierOperation.Flat:
|
|
flatSum += m.Value;
|
|
hasFlat = true;
|
|
break;
|
|
case ModifierOperation.Addition:
|
|
addSum += m.Value;
|
|
break;
|
|
case ModifierOperation.Percentage:
|
|
pctSum += m.Value;
|
|
break;
|
|
case ModifierOperation.Multiplication:
|
|
mulValues.Add(m.Value);
|
|
break;
|
|
}
|
|
}
|
|
|
|
float result = hasFlat ? flatSum : baseValue;
|
|
result += addSum;
|
|
result *= 1f + (pctSum / 100f);
|
|
|
|
foreach(var mul in mulValues) {
|
|
result *= mul;
|
|
}
|
|
|
|
return (int)Math.Round(result);
|
|
}
|
|
|
|
public IEnumerable<IModifier> CollectModifiers(IEntityDefinition entity, StatType statType) {
|
|
if(entity == null) {
|
|
return Array.Empty<IModifier>();
|
|
}
|
|
|
|
var result = new List<IModifier>();
|
|
|
|
if(entity.Modifiers?.modifiers != null) {
|
|
foreach(var m in entity.Modifiers.modifiers) {
|
|
if(m != null && m.StatType == statType) {
|
|
result.Add(m);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(entity.Perks?.perks != null) {
|
|
foreach(var p in entity.Perks.perks) {
|
|
if(p?.Modifiers?.modifiers == null) {
|
|
continue;
|
|
}
|
|
foreach(var m in p.Modifiers.modifiers) {
|
|
if(m != null && m.StatType == statType) {
|
|
result.Add(m);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public IEnumerable<IModifier> CollectModifiers(IEntityDefinition entity, AttributeType attributeType) {
|
|
if(entity == null) {
|
|
return Array.Empty<IModifier>();
|
|
}
|
|
|
|
var result = new List<IModifier>();
|
|
|
|
if(entity.Modifiers?.modifiers != null) {
|
|
foreach(var m in entity.Modifiers.modifiers) {
|
|
if(m != null && m.AttributeType == attributeType) {
|
|
result.Add(m);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(entity.Perks?.perks != null) {
|
|
foreach(var p in entity.Perks.perks) {
|
|
if(p?.Modifiers?.modifiers == null) {
|
|
continue;
|
|
}
|
|
foreach(var m in p.Modifiers.modifiers) {
|
|
if(m != null && m.AttributeType == attributeType) {
|
|
result.Add(m);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|