forked from Shardstone/trail-into-darkness
added full characte creation support
This commit is contained in:
@@ -5,9 +5,10 @@ using ZLinq;
|
||||
namespace Nox.Game {
|
||||
|
||||
public interface IModifierResolver {
|
||||
int Resolve(int baseValue, IEnumerable<IModifier> modifiers);
|
||||
int Resolve(int baseValue, IEnumerable<IModifier> modifiers, IEntityDefinition entity = null);
|
||||
IEnumerable<IModifier> CollectModifiers(IEntityDefinition entity, StatType statType);
|
||||
IEnumerable<IModifier> CollectModifiers(IEntityDefinition entity, AttributeType attributeType);
|
||||
IEnumerable<IModifier> CollectModifiers(IEntityDefinition entity, CombatScoreType combatScoreType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -19,9 +20,14 @@ namespace Nox.Game {
|
||||
/// 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
|
||||
///
|
||||
/// If a modifier has a ScalingSource set, its Value is multiplied by the entity's
|
||||
/// current value for that source before being applied. For example, a modifier with
|
||||
/// Target=Health, ScalingSource=Might, Operation=Addition, Value=2 means "+2 Health
|
||||
/// per point of Might".
|
||||
/// </summary>
|
||||
public sealed class ModifierResolver : IModifierResolver {
|
||||
public int Resolve(int baseValue, IEnumerable<IModifier> modifiers) {
|
||||
public int Resolve(int baseValue, IEnumerable<IModifier> modifiers, IEntityDefinition entity = null) {
|
||||
if(modifiers == null) {
|
||||
return baseValue;
|
||||
}
|
||||
@@ -37,19 +43,21 @@ namespace Nox.Game {
|
||||
continue;
|
||||
}
|
||||
|
||||
var effectiveValue = ResolveScaling(m, entity);
|
||||
|
||||
switch(m.Operation) {
|
||||
case ModifierOperation.Flat:
|
||||
flatSum += m.Value;
|
||||
flatSum += effectiveValue;
|
||||
hasFlat = true;
|
||||
break;
|
||||
case ModifierOperation.Addition:
|
||||
addSum += m.Value;
|
||||
addSum += effectiveValue;
|
||||
break;
|
||||
case ModifierOperation.Percentage:
|
||||
pctSum += m.Value;
|
||||
pctSum += effectiveValue;
|
||||
break;
|
||||
case ModifierOperation.Multiplication:
|
||||
mulValues.Add(m.Value);
|
||||
mulValues.Add(effectiveValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -65,34 +73,31 @@ namespace Nox.Game {
|
||||
return (int)Math.Round(result);
|
||||
}
|
||||
|
||||
private static float ResolveScaling(IModifier modifier, IEntityDefinition entity) {
|
||||
var value = modifier.Value;
|
||||
if(entity == null || modifier.ScalingSource == null || !modifier.ScalingSource.IsSet) {
|
||||
return value;
|
||||
}
|
||||
|
||||
var source = modifier.ScalingSource;
|
||||
var sourceValue = source.Type switch {
|
||||
ModifierTargetType.Attribute when entity.Attributes?.attributes != null =>
|
||||
entity.Attributes.GetValue(source.AttributeType),
|
||||
ModifierTargetType.Stat when entity.Stats?.stats != null =>
|
||||
entity.Stats.GetValue(source.StatType),
|
||||
_ => 0
|
||||
};
|
||||
|
||||
return value * sourceValue;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CollectFromEntity(entity, result, m => m.Target != null && m.Target.Matches(statType));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -102,10 +107,37 @@ namespace Nox.Game {
|
||||
}
|
||||
|
||||
var result = new List<IModifier>();
|
||||
CollectFromEntity(entity, result, m => m.Target != null && m.Target.Matches(attributeType));
|
||||
return result;
|
||||
}
|
||||
|
||||
public IEnumerable<IModifier> CollectModifiers(IEntityDefinition entity, CombatScoreType combatScoreType) {
|
||||
if(entity == null) {
|
||||
return Array.Empty<IModifier>();
|
||||
}
|
||||
|
||||
var result = new List<IModifier>();
|
||||
CollectFromEntity(entity, result, m => m.Target != null && m.Target.Matches(combatScoreType));
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool MeetsRequirements(IModifier modifier, IEntityDefinition entity) {
|
||||
var requirements = modifier.Requirements;
|
||||
if(requirements == null || requirements.Count == 0) {
|
||||
return true;
|
||||
}
|
||||
for(int i = 0; i < requirements.Count; i++) {
|
||||
if(!requirements[i].IsMet(entity.Attributes)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void CollectFromEntity(IEntityDefinition entity, List<IModifier> result, Func<IModifier, bool> predicate) {
|
||||
if(entity.Modifiers?.modifiers != null) {
|
||||
foreach(var m in entity.Modifiers.modifiers) {
|
||||
if(m != null && m.AttributeType == attributeType) {
|
||||
if(m != null && predicate(m) && MeetsRequirements(m, entity)) {
|
||||
result.Add(m);
|
||||
}
|
||||
}
|
||||
@@ -117,14 +149,12 @@ namespace Nox.Game {
|
||||
continue;
|
||||
}
|
||||
foreach(var m in p.Modifiers.modifiers) {
|
||||
if(m != null && m.AttributeType == attributeType) {
|
||||
if(m != null && predicate(m)) {
|
||||
result.Add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user