Skip to content

Add dark horse options & major dmg calcs refactoring #586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/AttributeSystem/AggregateType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public enum AggregateType
AddRaw,

/// <summary>
/// Multiplicates the value.
/// Multiplicates by the raw value.
/// </summary>
Multiplicate,

Expand Down
50 changes: 39 additions & 11 deletions src/AttributeSystem/AttributeRelationship.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,34 @@ namespace MUnique.OpenMU.AttributeSystem;
public enum InputOperator
{
/// <summary>
/// The <see cref="AttributeRelationship.InputAttribute"/> is multiplied with the <see cref="AttributeRelationship.InputOperand"/> before adding to the <see cref="AttributeRelationship.TargetAttribute"/>.
/// The <see cref="AttributeRelationship.InputAttribute"/> is multiplied with the <see cref="AttributeRelationship.InputOperand"/> before effecting the <see cref="AttributeRelationship.TargetAttribute"/>.
/// </summary>
Multiply,

/// <summary>
/// The <see cref="AttributeRelationship.InputAttribute"/> is increased by the <see cref="AttributeRelationship.InputOperand"/> before adding to the <see cref="AttributeRelationship.TargetAttribute"/>.
/// The <see cref="AttributeRelationship.InputAttribute"/> is increased by the <see cref="AttributeRelationship.InputOperand"/> before effecting the <see cref="AttributeRelationship.TargetAttribute"/>.
/// </summary>
Add,

/// <summary>
/// The <see cref="AttributeRelationship.InputAttribute"/> is exponentiated by the <see cref="AttributeRelationship.InputOperand"/> before adding to the <see cref="AttributeRelationship.TargetAttribute"/>.
/// The <see cref="AttributeRelationship.InputAttribute"/> is exponentiated by the <see cref="AttributeRelationship.InputOperand"/> before effecting the <see cref="AttributeRelationship.TargetAttribute"/>.
/// </summary>
Exponentiate,

/// <summary>
/// The <see cref="AttributeRelationship.InputOperand"/> is exponentiated by the <see cref="AttributeRelationship.InputAttribute"/> before adding to the <see cref="AttributeRelationship.TargetAttribute"/>.
/// The <see cref="AttributeRelationship.InputOperand"/> is exponentiated by the <see cref="AttributeRelationship.InputAttribute"/> before effecting the <see cref="AttributeRelationship.TargetAttribute"/>.
/// </summary>
ExponentiateByAttribute,

/// <summary>
/// The minimum between <see cref="AttributeRelationship.InputAttribute"/> and <see cref="AttributeRelationship.InputOperand"/> is taken before effecting the <see cref="AttributeRelationship.TargetAttribute"/>.
/// </summary>
Minimum,

/// <summary>
/// The maximum between <see cref="AttributeRelationship.InputAttribute"/> and <see cref="AttributeRelationship.InputOperand"/> is taken before effecting the <see cref="AttributeRelationship.TargetAttribute"/>.
/// </summary>
Maximum,
}

/// <summary>
Expand All @@ -54,8 +64,10 @@ public AttributeRelationship()
/// <param name="targetAttribute">The target attribute.</param>
/// <param name="inputOperand">The multiplier.</param>
/// <param name="inputAttribute">The input attribute.</param>
public AttributeRelationship(AttributeDefinition targetAttribute, float inputOperand, AttributeDefinition inputAttribute)
: this(targetAttribute, inputOperand, inputAttribute, InputOperator.Multiply)
/// <param name="aggregateType">The type of the aggregate on the <paramref name="targetAttribute"/>.</param>
/// <param name="stage">The calculation stage on the <paramref name="targetAttribute"/>.</param>
public AttributeRelationship(AttributeDefinition targetAttribute, float inputOperand, AttributeDefinition inputAttribute, AggregateType aggregateType, byte stage)
: this(targetAttribute, inputOperand, inputAttribute, InputOperator.Multiply, default, aggregateType, stage)
{
}

Expand All @@ -65,8 +77,10 @@ public AttributeRelationship(AttributeDefinition targetAttribute, float inputOpe
/// <param name="targetAttribute">The target attribute.</param>
/// <param name="inputOperand">The multiplier.</param>
/// <param name="inputAttribute">The input attribute.</param>
public AttributeRelationship(AttributeDefinition targetAttribute, AttributeDefinition inputOperand, AttributeDefinition inputAttribute)
: this(targetAttribute, 1, inputAttribute, InputOperator.Multiply, inputOperand)
/// <param name="aggregateType">The type of the aggregate on the <paramref name="targetAttribute"/>.</param>
/// <param name="stage">The calculation stage on the <paramref name="targetAttribute"/>.</param>
public AttributeRelationship(AttributeDefinition targetAttribute, AttributeDefinition inputOperand, AttributeDefinition inputAttribute, AggregateType aggregateType, byte stage)
: this(targetAttribute, 1, inputAttribute, InputOperator.Multiply, inputOperand, aggregateType, stage)
{
}

Expand All @@ -78,10 +92,14 @@ public AttributeRelationship(AttributeDefinition targetAttribute, AttributeDefin
/// <param name="inputAttribute">The input attribute.</param>
/// <param name="inputOperator">The input operator.</param>
/// <param name="operandAttribute">The operand attribute.</param>
public AttributeRelationship(AttributeDefinition targetAttribute, float inputOperand, AttributeDefinition inputAttribute, InputOperator inputOperator, AttributeDefinition? operandAttribute = null)
/// <param name="aggregateType">The type of the aggregate on the <paramref name="targetAttribute"/>.</param>
/// <param name="stage">The calculation stage on the <paramref name="targetAttribute"/>.</param>
public AttributeRelationship(AttributeDefinition targetAttribute, float inputOperand, AttributeDefinition inputAttribute, InputOperator inputOperator, AttributeDefinition? operandAttribute = null, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0)
{
this.InputOperand = inputOperand;
this.InputOperator = inputOperator;
this.AggregateType = aggregateType;
this.Stage = stage;
this._targetAttribute = targetAttribute;
this._inputAttribute = inputAttribute;
this._operandAttribute = operandAttribute;
Expand Down Expand Up @@ -125,6 +143,16 @@ public virtual AttributeDefinition? OperandAttribute
/// </summary>
public float InputOperand { get; set; }

/// <summary>
/// Gets or sets the aggregate type with which the relationship should effect the target attribute.
/// </summary>
public AggregateType AggregateType { get; set; }

/// <summary>
/// Gets or sets the calculation stage at which the relationship should effect the target attribute.
/// </summary>
public byte Stage { get; set; }

Comment on lines +146 to +155
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these needed? Which use cases do you try to solve with them?

/// <inheritdoc/>
public override string ToString()
{
Expand All @@ -135,9 +163,9 @@ public override string ToString()

if (this.InputOperator == InputOperator.ExponentiateByAttribute)
{
return $"{this.TargetAttribute} += {this.OperandAttribute?.ToString() ?? this.InputOperand.ToString(CultureInfo.InvariantCulture)} {this.InputOperator.AsString()} {this.InputAttribute}";
return $"{this.TargetAttribute} {(this.AggregateType == AggregateType.Multiplicate ? "*" : "+")}= {this.OperandAttribute?.ToString() ?? this.InputOperand.ToString(CultureInfo.InvariantCulture)} {this.InputOperator.AsString()} {this.InputAttribute}";
}

return $"{this.TargetAttribute} += {this.InputAttribute} {this.InputOperator.AsString()} {this.OperandAttribute?.ToString() ?? this.InputOperand.ToString(CultureInfo.InvariantCulture)}";
return $"{this.TargetAttribute} {(this.AggregateType == AggregateType.Multiplicate ? "*" : "+")}= {this.InputAttribute} {this.InputOperator.AsString()} {this.OperandAttribute?.ToString() ?? this.InputOperand.ToString(CultureInfo.InvariantCulture)}";
}
}
8 changes: 7 additions & 1 deletion src/AttributeSystem/AttributeRelationshipElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,13 @@ private float CalculateValue()
InputOperator.ExponentiateByAttribute => (float)Math.Pow(
this.InputOperand.Value,
this.InputElements.Sum(a => a.Value)),
_ => throw new InvalidOperationException($"Input operator {this.InputOperator} unknown")
InputOperator.Minimum => Math.Min(
this.InputElements.Sum(a => a.Value),
this.InputOperand.Value),
InputOperator.Maximum => Math.Max(
this.InputElements.Sum(a => a.Value),
this.InputOperand.Value),
_ => throw new InvalidOperationException($"Input operator {this.InputOperator} unknown"),
};
}
}
3 changes: 2 additions & 1 deletion src/AttributeSystem/AttributeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public IElement CreateRelatedAttribute(AttributeRelationship relationship, IAttr
return new AttributeRelationshipElement(inputElements, relationship.GetOperandElement(sourceAttributeHolder), relationship.InputOperator)
{
AggregateType = aggregateType,
Stage = relationship.Stage,
};
}

Expand Down Expand Up @@ -238,7 +239,7 @@ protected virtual void OnAttributeRemoved(IAttribute attribute)
/// <param name="combination">The combination.</param>
private void AddAttributeRelationship(AttributeRelationship combination)
{
this.AddAttributeRelationship(combination, this, AggregateType.AddRaw);
this.AddAttributeRelationship(combination, this, combination.AggregateType);
}

private IElement? GetAttribute(AttributeDefinition? attributeDefinition)
Expand Down
3 changes: 3 additions & 0 deletions src/AttributeSystem/BaseAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public virtual AttributeDefinition Definition
/// <inheritdoc/>
public AggregateType AggregateType { get; }

/// <inheritdoc />
public byte Stage { get; }

/// <inheritdoc/>
public override string ToString()
{
Expand Down
5 changes: 4 additions & 1 deletion src/AttributeSystem/CombinedElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ public CombinedElement(IElement element1, IElement element2)
/// <inheritdoc />
public AggregateType AggregateType => this._element1.AggregateType;

/// <inheritdoc />
public byte Stage => this._element1.Stage;

/// <inheritdoc/>
public override string ToString()
{
return $"{this.Value} ({this.AggregateType})";
return $"{this.Value} ({this.AggregateType}) @{this.Stage}";
}
}
42 changes: 25 additions & 17 deletions src/AttributeSystem/ComposableAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,26 +58,34 @@ private float GetAndCacheValue()
return 0;
}

var rawValues = this.Elements.Where(e => e.AggregateType == AggregateType.AddRaw).Sum(e => e.Value);
var multiValues = this.Elements.Where(e => e.AggregateType == AggregateType.Multiplicate).Select(e => e.Value).Concat(Enumerable.Repeat(1.0F, 1)).Aggregate((a, b) => a * b);
var finalValues = this.Elements.Where(e => e.AggregateType == AggregateType.AddFinal).Sum(e => e.Value);
var maxValues = this.Elements.Where(e => e.AggregateType == AggregateType.Maximum).MaxBy(e => e.Value)?.Value ?? 0;
rawValues += maxValues;

if (multiValues == 0 && this.Elements.All(e => e.AggregateType != AggregateType.Multiplicate))
{
multiValues = 1;
}
else if (rawValues == 0 && multiValues != 0 && this.Elements.All(e => e.AggregateType != AggregateType.AddRaw))
{
rawValues = 1;
}
else
var highestStage = this._elementList.Max(e => e.Stage);
float newValue = 0;
for (int i = 0; i <= highestStage; i++)
{
// nothing to do
var stageElements = this._elementList.Where(e => e.Stage == i);

var rawValues = stageElements.Where(e => e.AggregateType == AggregateType.AddRaw).Sum(e => e.Value);
var multiValues = stageElements.Where(e => e.AggregateType == AggregateType.Multiplicate).Select(e => e.Value).Concat(Enumerable.Repeat(1.0F, 1)).Aggregate((a, b) => a * b);
var finalValues = stageElements.Where(e => e.AggregateType == AggregateType.AddFinal).Sum(e => e.Value);
var maxValues = stageElements.Where(e => e.AggregateType == AggregateType.Maximum).MaxBy(e => e.Value)?.Value ?? 0;
rawValues += maxValues;

if (multiValues == 0 && stageElements.All(e => e.AggregateType != AggregateType.Multiplicate))
{
multiValues = 1;
}
else if (newValue + rawValues == 0 && multiValues != 0 && stageElements.All(e => e.AggregateType == AggregateType.Multiplicate))
{
rawValues = 1;
}
else
{
// nothing to do
}

newValue = ((newValue + rawValues) * multiValues) + finalValues;
}

var newValue = (rawValues * multiValues) + finalValues;
if (this.Definition.MaximumValue.HasValue)
{
newValue = Math.Min(this.Definition.MaximumValue.Value, newValue);
Expand Down
13 changes: 10 additions & 3 deletions src/AttributeSystem/ConstValueAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ public class ConstValueAttribute : IAttribute
/// </summary>
/// <param name="value">The value.</param>
/// <param name="definition">The definition.</param>
public ConstValueAttribute(float value, AttributeDefinition definition)
/// <param name="aggregateType">The type of the aggregate on the <paramref name="definition"/>.</param>
/// <param name="stage">The calculation stage on the <paramref name="definition"/>.</param>
public ConstValueAttribute(float value, AttributeDefinition definition, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0)
{
this.Value = value;
this._definition = definition;
this.AggregateType = aggregateType;
this.Stage = stage;
}

/// <summary>
Expand Down Expand Up @@ -57,11 +61,14 @@ public virtual AttributeDefinition Definition
public float Value { get; protected set; }

/// <inheritdoc/>
public AggregateType AggregateType => AggregateType.AddRaw;
public AggregateType AggregateType { get; protected set; }

/// <inheritdoc />
public byte Stage { get; protected set; }

/// <inheritdoc/>
public override string ToString()
{
return $"{this.Definition.Designation}: {this.Value}";
return $"{this.Definition.Designation}: {this.Value} ({this.AggregateType}) @{this.Stage}";
}
}
9 changes: 7 additions & 2 deletions src/AttributeSystem/ConstantElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ public class ConstantElement : IElement
/// </summary>
/// <param name="value">The constant value.</param>
/// <param name="aggregateType">Type of the aggregate.</param>
public ConstantElement(float value, AggregateType aggregateType = AggregateType.AddRaw)
/// <param name="stage">The calculation stage.</param>
public ConstantElement(float value, AggregateType aggregateType = AggregateType.AddRaw, byte stage = 0)
{
this.Value = value;
this.AggregateType = aggregateType;
this.Stage = stage;
}

/// <summary>
Expand All @@ -42,9 +44,12 @@ public event EventHandler? ValueChanged
/// <inheritdoc/>
public AggregateType AggregateType { get; }

/// <inheritdoc />
public byte Stage { get; }

/// <inheritdoc/>
public override string ToString()
{
return $"{this.Value} ({this.AggregateType})";
return $"{this.Value} ({this.AggregateType}) @{this.Stage}";
}
}
2 changes: 2 additions & 0 deletions src/AttributeSystem/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public static string AsString(this InputOperator inputOperator)
InputOperator.Multiply => "*",
InputOperator.Exponentiate => "^",
InputOperator.ExponentiateByAttribute => "^",
InputOperator.Minimum => "<min>",
InputOperator.Maximum => "<max>",
_ => string.Empty,
};
}
Expand Down
8 changes: 8 additions & 0 deletions src/AttributeSystem/IElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ public interface IElement
/// Gets the type of the aggregate.
/// </summary>
AggregateType AggregateType { get; }

/// <summary>
/// Gets the stage at which the element value is calculated when part of a <see cref="ComposableAttribute"/>, if any.
/// </summary>
/// <remarks>Useful for attributes which have several rounds of addition and multiplication elements, like the min/max base type damages.
/// For example, <c>(a * b + c) * d + e</c> would be a two-stage calculation, with <c>a</c>, <c>b</c>, <c>c</c> comprising the first stage, and <c>d</c>, <c>e</c> the second.
/// In such a case <c>a</c> represents an <see cref="AggregateType.AddRaw"/> value; <c>b</c> and <c>d</c> an <see cref="AggregateType.Multiplicate"/> values; <c>c</c> and <c>e</c> an <see cref="AggregateType.AddFinal"/> values.</remarks>
byte Stage { get; }
}
22 changes: 20 additions & 2 deletions src/AttributeSystem/SimpleElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class SimpleElement : IElement
{
private float _value;
private AggregateType _aggregateType;
private byte _stage;

/// <summary>
/// Initializes a new instance of the <see cref="SimpleElement"/> class.
Expand All @@ -24,10 +25,12 @@ public SimpleElement()
/// </summary>
/// <param name="value">The value.</param>
/// <param name="aggregateType">Type of the aggregate.</param>
public SimpleElement(float value, AggregateType aggregateType)
/// <param name="stage">The calculation stage.</param>
public SimpleElement(float value, AggregateType aggregateType, byte stage = 0)
{
this._value = value;
this._aggregateType = aggregateType;
this._stage = stage;
}

/// <inheritdoc/>
Expand Down Expand Up @@ -63,10 +66,25 @@ public AggregateType AggregateType
}
}

/// <inheritdoc />
public byte Stage
{
get => this._stage;

set
{
if (this._stage != value)
{
this._stage = value;
this.RaiseValueChanged();
}
}
}

/// <inheritdoc/>
public override string ToString()
{
return $"{this.Value} ({this.AggregateType})";
return $"{this.Value} ({this.AggregateType}) @{this.Stage}";
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/DataModel/Attributes/PowerUpDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace MUnique.OpenMU.DataModel.Attributes;
using MUnique.OpenMU.AttributeSystem;

/// <summary>
/// The power up definition which describes the boost of an target attribute.
/// The power up definition which describes the boost of a target attribute.
/// </summary>
[Cloneable]
public partial class PowerUpDefinition
Expand Down
Loading
Loading