diff --git a/Forge.Tests/Core/Curve.cs b/Forge.Tests/Core/Curve.cs index af44de2..8ce5fc8 100644 --- a/Forge.Tests/Core/Curve.cs +++ b/Forge.Tests/Core/Curve.cs @@ -7,10 +7,10 @@ namespace Gamesmiths.Forge.Tests.Core; /// /// Initializes a new instance of the class. /// -/// The keys for the curve. -public readonly struct Curve(CurveKey[] keys) : ICurve, IEquatable +/// The keys for the curve. +public readonly record struct Curve(CurveKey[] Keys) : ICurve { - private readonly CurveKey[] _keys = [.. keys.OrderBy(x => x.Time)]; + private readonly CurveKey[] _keys = [.. Keys.OrderBy(x => x.Time)]; /// /// Evaluates the curve at a given time. @@ -47,62 +47,4 @@ public float Evaluate(float value) // Fallback. return 1.0f; } - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - foreach (CurveKey key in _keys) - { - hash.Add(key); - } - - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is Curve other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(Curve other) - { - if (_keys is null) - { - return other._keys is null; - } - - return _keys.SequenceEqual(other._keys); - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(Curve lhs, Curve rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(Curve lhs, Curve rhs) - { - return !(lhs == rhs); - } } diff --git a/Forge.Tests/Core/CurveKey.cs b/Forge.Tests/Core/CurveKey.cs index 7aaaac5..0c31afe 100644 --- a/Forge.Tests/Core/CurveKey.cs +++ b/Forge.Tests/Core/CurveKey.cs @@ -1,74 +1,10 @@ // Copyright © Gamesmiths Guild. -namespace Gamesmiths.Forge.Core; +namespace Gamesmiths.Forge.Tests.Core; /// /// Represents a key into a . /// -/// The time of the curve key. -/// The value of the curve key. -public readonly struct CurveKey(float time, float value) : IEquatable -{ - /// - /// Gets the time of this curve key. - /// - public float Time { get; } = time; - - /// - /// Gets the value of this curve key. - /// - public float Value { get; } = value; - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(Time); - hash.Add(Value); - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is CurveKey other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(CurveKey other) - { -#pragma warning disable S1244 // Floating point numbers should not be tested for equality - return Time == other.Time - && Value.Equals(other.Value); -#pragma warning restore S1244 // Floating point numbers should not be tested for equality - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(CurveKey lhs, CurveKey rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(CurveKey lhs, CurveKey rhs) - { - return !(lhs == rhs); - } -} +/// The time of the curve key. +/// The value of the curve key. +public readonly record struct CurveKey(float Time, float Value); diff --git a/Forge.Tests/Cues/CueTests.cs b/Forge.Tests/Cues/CueTests.cs index 74d2e17..548226f 100644 --- a/Forge.Tests/Cues/CueTests.cs +++ b/Forge.Tests/Cues/CueTests.cs @@ -2456,10 +2456,10 @@ private static EffectData CreateDurationStackableEffectData( StackMagnitudePolicy.Sum, StackOverflowPolicy.AllowApplication, StackExpirationPolicy.RemoveSingleStackAndRefreshDuration, - levelDenialPolicy: LevelComparison.None, - levelOverridePolicy: LevelComparison.Lower | LevelComparison.Equal | LevelComparison.Higher, - levelOverrideStackCountPolicy: StackLevelOverrideStackCountPolicy.IncreaseStacks, - applicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication), + LevelDenialPolicy: LevelComparison.None, + LevelOverridePolicy: LevelComparison.Lower | LevelComparison.Equal | LevelComparison.Higher, + LevelOverrideStackCountPolicy: StackLevelOverrideStackCountPolicy.IncreaseStacks, + ApplicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication), snapshopLevel: false, requireModifierSuccessToTriggerCue: requireModifierSuccessToTriggerCue, suppressStackingCues: suppressStackingCues, diff --git a/Forge.Tests/Effects/EffectsTests.cs b/Forge.Tests/Effects/EffectsTests.cs index 117203e..46a1d76 100644 --- a/Forge.Tests/Effects/EffectsTests.cs +++ b/Forge.Tests/Effects/EffectsTests.cs @@ -138,7 +138,7 @@ public void Attribute_based_effect_with_curve_modifies_values_based_on_curve_loo new ScalableFloat(coefficient), new ScalableFloat(preMultiplyAdditiveValue), new ScalableFloat(postMultiplyAdditiveValue), - lookupCurve: new Curve( + LookupCurve: new Curve( [ new CurveKey(6, 4), new CurveKey(8, 3), diff --git a/Forge.Tests/Effects/TargetTagRequirementsComponentTests.cs b/Forge.Tests/Effects/TargetTagRequirementsComponentTests.cs index 2f2932c..3d9e03d 100644 --- a/Forge.Tests/Effects/TargetTagRequirementsComponentTests.cs +++ b/Forge.Tests/Effects/TargetTagRequirementsComponentTests.cs @@ -348,7 +348,7 @@ public void Effect_meets_application_requirements_with_query() new DurationData(DurationType.Infinite), effectComponents: [ - new TargetTagRequirementsEffectComponent(new TagRequirements(tagQuery: query)) + new TargetTagRequirementsEffectComponent(new TagRequirements(TagQuery: query)) ]); var effect = new Effect(effectData, new EffectOwnership(entity, entity)); @@ -391,7 +391,7 @@ public void Effect_does_not_meet_application_requirements_with_query() new DurationData(DurationType.Infinite), effectComponents: [ - new TargetTagRequirementsEffectComponent(new TagRequirements(tagQuery: query)) + new TargetTagRequirementsEffectComponent(new TagRequirements(TagQuery: query)) ]); var effect = new Effect(effectData, new EffectOwnership(entity, entity)); diff --git a/Forge.Tests/Samples/QuickStartTests.cs b/Forge.Tests/Samples/QuickStartTests.cs index 139ce5b..2019026 100644 --- a/Forge.Tests/Samples/QuickStartTests.cs +++ b/Forge.Tests/Samples/QuickStartTests.cs @@ -239,9 +239,9 @@ public void Periodic_effect_example() ) }, periodicData: new PeriodicData( - period: new ScalableFloat(2.0f), - executeOnApplication: true, - periodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod + Period: new ScalableFloat(2.0f), + ExecuteOnApplication: true, + PeriodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod ) ); @@ -282,23 +282,23 @@ public void Stacking_poison_effect_example() ) }, periodicData: new PeriodicData( - period: new ScalableFloat(2.0f), - executeOnApplication: false, - periodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod + Period: new ScalableFloat(2.0f), + ExecuteOnApplication: false, + PeriodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod ), stackingData: new StackingData( - stackLimit: new ScalableInt(3), // Max 3 stacks - initialStack: new ScalableInt(1), // Starts with 1 stack - overflowPolicy: StackOverflowPolicy.DenyApplication, // Deny if max stacks reached - magnitudePolicy: StackMagnitudePolicy.Sum, // Total damage increases with stacks - expirationPolicy: StackExpirationPolicy.ClearEntireStack, // All stacks expire together - applicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication, - stackPolicy: StackPolicy.AggregateBySource, // Aggregate stacks from the same source - stackLevelPolicy: StackLevelPolicy.SegregateLevels, // Each stack can have its own level + StackLimit: new ScalableInt(3), // Max 3 stacks + InitialStack: new ScalableInt(1), // Starts with 1 stack + OverflowPolicy: StackOverflowPolicy.DenyApplication, // Deny if max stacks reached + MagnitudePolicy: StackMagnitudePolicy.Sum, // Total damage increases with stacks + ExpirationPolicy: StackExpirationPolicy.ClearEntireStack, // All stacks expire together + ApplicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication, + StackPolicy: StackPolicy.AggregateBySource, // Aggregate stacks from the same source + StackLevelPolicy: StackLevelPolicy.SegregateLevels, // Each stack can have its own level // The next two values must be defined because this is a periodic effect with stacking - executeOnSuccessfulApplication: false, // Do not execute on successful application - applicationResetPeriodPolicy: StackApplicationResetPeriodPolicy.ResetOnSuccessfulApplication + ExecuteOnSuccessfulApplication: false, // Do not execute on successful application + ApplicationResetPeriodPolicy: StackApplicationResetPeriodPolicy.ResetOnSuccessfulApplication ) ); @@ -351,20 +351,20 @@ public void Unique_effect_example() ) }, stackingData: new StackingData( - stackLimit: new ScalableInt(1), // Only 1 instance allowed - initialStack: new ScalableInt(1), // Starts with 1 stack - overflowPolicy: StackOverflowPolicy.AllowApplication, // Allow application even if max stacks reached - magnitudePolicy: StackMagnitudePolicy.Sum, // Total damage increases with stacks - expirationPolicy: StackExpirationPolicy.ClearEntireStack, // All stacks expire together - applicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication, - stackPolicy: StackPolicy.AggregateByTarget, // Only one effect per target - ownerDenialPolicy: StackOwnerDenialPolicy.AlwaysAllow, // Always allow application regardless of owner - ownerOverridePolicy: StackOwnerOverridePolicy.Override, // Override existing effect if applied again - ownerOverrideStackCountPolicy: StackOwnerOverrideStackCountPolicy.ResetStacks, - stackLevelPolicy: StackLevelPolicy.AggregateLevels, // Aggregate levels of the effect - levelOverridePolicy: LevelComparison.Equal | LevelComparison.Higher, - levelDenialPolicy: LevelComparison.Lower, // Deny lower-level effects - levelOverrideStackCountPolicy: StackLevelOverrideStackCountPolicy.ResetStacks + StackLimit: new ScalableInt(1), // Only 1 instance allowed + InitialStack: new ScalableInt(1), // Starts with 1 stack + OverflowPolicy: StackOverflowPolicy.AllowApplication, // Allow application even if max stacks reached + MagnitudePolicy: StackMagnitudePolicy.Sum, // Total damage increases with stacks + ExpirationPolicy: StackExpirationPolicy.ClearEntireStack, // All stacks expire together + ApplicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication, + StackPolicy: StackPolicy.AggregateByTarget, // Only one effect per target + OwnerDenialPolicy: StackOwnerDenialPolicy.AlwaysAllow, // Always allow application regardless of owner + OwnerOverridePolicy: StackOwnerOverridePolicy.Override, // Override existing effect if applied again + OwnerOverrideStackCountPolicy: StackOwnerOverrideStackCountPolicy.ResetStacks, + StackLevelPolicy: StackLevelPolicy.AggregateLevels, // Aggregate levels of the effect + LevelOverridePolicy: LevelComparison.Equal | LevelComparison.Higher, + LevelDenialPolicy: LevelComparison.Lower, // Deny lower-level effects + LevelOverrideStackCountPolicy: StackLevelOverrideStackCountPolicy.ResetStacks ) ); @@ -456,7 +456,7 @@ public void Preventing_effect_application_based_on_tags() new TargetTagRequirementsEffectComponent( applicationTagRequirements: new TagRequirements( // Prevent application if target has "status.immune.fire" - ignoreTags: tagsManager.RequestTagContainer(new[] { "status.immune.fire" }) + IgnoreTags: tagsManager.RequestTagContainer(new[] { "status.immune.fire" }) ) ) } @@ -638,17 +638,17 @@ public void Triggering_a_cue_through_effects() ) }, periodicData: new PeriodicData( - period: new ScalableFloat(1.0f), // Ticks every second - executeOnApplication: true, - periodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod + Period: new ScalableFloat(1.0f), // Ticks every second + ExecuteOnApplication: true, + PeriodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod ), cues: new[] { new CueData( - cueTags: tagsManager.RequestTagContainer(new[] { "cues.damage.fire" }), - minValue: 0, - maxValue: 100, - magnitudeType: CueMagnitudeType.AttributeValueChange, - magnitudeAttribute: "PlayerAttributeSet.Health" // Tracks health changes + CueTags: tagsManager.RequestTagContainer(new[] { "cues.damage.fire" }), + MinValue: 0, + MaxValue: 100, + MagnitudeType: CueMagnitudeType.AttributeValueChange, + MagnitudeAttribute: "PlayerAttributeSet.Health" // Tracks health changes ) } ); @@ -700,10 +700,10 @@ public void Manually_triggering_a_cue() // Manually trigger a fire damage cue var parameters = new CueParameters( - magnitude: 25, // Raw damage value - normalizedMagnitude: 0.25f, // Normalized between 0-1 - source: player, - customParameters: new Dictionary + Magnitude: 25, // Raw damage value + NormalizedMagnitude: 0.25f, // Normalized between 0-1 + Source: player, + CustomParameters: new Dictionary { { "DamageType", "Fire" }, { "IsCritical", true } @@ -797,12 +797,12 @@ public StrengthDamageCalculator() StrengthAttribute = new AttributeCaptureDefinition( "PlayerAttributeSet.Strength", AttributeCaptureSource.Source, - snapshot: true); + Snapshot: true); SpeedAttribute = new AttributeCaptureDefinition( "PlayerAttributeSet.Speed", AttributeCaptureSource.Source, - snapshot: true); + Snapshot: true); AttributesToCapture.Add(StrengthAttribute); AttributesToCapture.Add(SpeedAttribute); @@ -833,17 +833,17 @@ public HealthDrainExecution() TargetHealth = new AttributeCaptureDefinition( "PlayerAttributeSet.Health", AttributeCaptureSource.Target, - snapshot: false); + Snapshot: false); SourceHealth = new AttributeCaptureDefinition( "PlayerAttributeSet.Health", AttributeCaptureSource.Source, - snapshot: false); + Snapshot: false); SourceStrength = new AttributeCaptureDefinition( "PlayerAttributeSet.Strength", AttributeCaptureSource.Source, - snapshot: false); + Snapshot: false); // Register attributes for capture AttributesToCapture.Add(TargetHealth); @@ -922,7 +922,7 @@ public void OnUpdate(IForgeEntity? target, CueParameters? parameters) // Logic for updating persistent cues (e.g., adjust fire intensity) if (parameters.HasValue) { - Console.WriteLine($"Fire damage cue updated with magnitude: {parameters.Value.Magnitude}"); + Console.WriteLine($"Fire damage cue updated with Magnitude: {parameters.Value.Magnitude}"); } } } diff --git a/Forge/Attributes/AttributeInfo.cs b/Forge/Attributes/AttributeInfo.cs index 56483c2..4549cda 100644 --- a/Forge/Attributes/AttributeInfo.cs +++ b/Forge/Attributes/AttributeInfo.cs @@ -6,29 +6,8 @@ namespace Gamesmiths.Forge.Attributes; /// /// Initializes a new instance of the struct. /// -/// The full key of the attribute, in the format "setname.attributename". -/// The simple name of the attribute. -/// The name of the attribute set. -/// The attribute instance. -public readonly struct AttributeInfo(string fullKey, string name, string setName, EntityAttribute value) -{ - /// - /// Gets the full key of the attribute (e.g. "vitalattributes.health"). - /// - public string FullKey { get; } = fullKey; - - /// - /// Gets the simple attribute name (e.g. "health"). - /// - public string Name { get; } = name; - - /// - /// Gets the name of the attribute set (e.g. "vitalattributes"). - /// - public string SetName { get; } = setName; - - /// - /// Gets the attribute instance. - /// - public EntityAttribute Value { get; } = value; -} +/// The full key of the attribute, in the format "setname.attributename". +/// The simple name of the attribute. +/// The name of the attribute set. +/// The attribute instance. +public readonly record struct AttributeInfo(string FullKey, string Name, string SetName, EntityAttribute Value); diff --git a/Forge/Attributes/AttributeOverride.cs b/Forge/Attributes/AttributeOverride.cs index ffd45a1..88193e6 100644 --- a/Forge/Attributes/AttributeOverride.cs +++ b/Forge/Attributes/AttributeOverride.cs @@ -5,17 +5,6 @@ namespace Gamesmiths.Forge.Attributes; /// /// Represents the data for an attribute override. /// -/// The magnitude of the override. -/// The channel in which the override is applied. -public class AttributeOverride(int magnitude, int channel) -{ - /// - /// Gets the override magnitude. - /// - public int Magnitude { get; } = magnitude; - - /// - /// Gets the target channel for the override. - /// - public int Channel { get; } = channel; -} +/// The magnitude of the override. +/// The channel in which the override is applied. +public readonly record struct AttributeOverride(int Magnitude, int Channel); diff --git a/Forge/Attributes/ChannelData.cs b/Forge/Attributes/ChannelData.cs index 43607ed..4bcb514 100644 --- a/Forge/Attributes/ChannelData.cs +++ b/Forge/Attributes/ChannelData.cs @@ -9,7 +9,7 @@ namespace Gamesmiths.Forge.Attributes; /// Attributes have channels for calculating its modifiers. Multiple channels can be used to calculate in sequence, /// granting it's possible to have various kinds of formulas combining flat and percentage modifiers. /// -public class ChannelData +public struct ChannelData { /// /// Gets or sets an override value at this channel. diff --git a/Forge/Attributes/EntityAttribute.cs b/Forge/Attributes/EntityAttribute.cs index aeb92d4..0b96250 100644 --- a/Forge/Attributes/EntityAttribute.cs +++ b/Forge/Attributes/EntityAttribute.cs @@ -11,7 +11,7 @@ namespace Gamesmiths.Forge.Attributes; /// public sealed class EntityAttribute { - private readonly List _channels = []; + private readonly ChannelData[] _channels; private readonly LinkedList _attributeOverrides = []; @@ -87,14 +87,16 @@ internal EntityAttribute( Overflow = 0; CurrentValue = BaseValue; + _channels = new ChannelData[channels]; + for (var i = 0; i < channels; i++) { - _channels.Add(new ChannelData + _channels[i] = new ChannelData { Override = null, FlatModifier = 0, PercentModifier = 1, - }); + }; } if (Validation.Enabled) @@ -183,7 +185,8 @@ internal void AddOverride(AttributeOverride attributeOverrideData) var oldValue = CurrentValue; - _channels[attributeOverrideData.Channel].Override = attributeOverrideData.Magnitude; + ref ChannelData channelData = ref _channels[attributeOverrideData.Channel]; + channelData.Override = attributeOverrideData.Magnitude; UpdateCachedValues(); @@ -200,13 +203,14 @@ internal void ClearOverride(in AttributeOverride attributeOverride) _attributeOverrides.Remove(attributeOverride); + ref ChannelData channelData = ref _channels[channel]; if (_attributeOverrides.Any(x => x.Channel == channel)) { - _channels[channel].Override = _attributeOverrides.First(x => x.Channel == channel).Magnitude; + channelData.Override = _attributeOverrides.First(x => x.Channel == channel).Magnitude; } else { - _channels[channel].Override = null; + channelData.Override = null; } UpdateCachedValues(); @@ -221,7 +225,8 @@ internal void AddFlatModifier(int value, int channel) { var oldValue = CurrentValue; - _channels[channel].FlatModifier += value; + ref ChannelData channelData = ref _channels[channel]; + channelData.FlatModifier += value; UpdateCachedValues(); @@ -235,7 +240,8 @@ internal void AddPercentModifier(float value, int channel) { var oldValue = CurrentValue; - _channels[channel].PercentModifier += value; + ref ChannelData channelData = ref _channels[channel]; + channelData.PercentModifier += value; UpdateCachedValues(); @@ -318,7 +324,7 @@ private void ValidateData() "DefaultValue should be withing MinValue and MaxValue."); Validation.Assert( - _channels.Count > 0, + _channels.Length > 0, "There should be at least one channel."); } } diff --git a/Forge/Compatibility/IsExternalInit.cs b/Forge/Compatibility/IsExternalInit.cs new file mode 100644 index 0000000..6245477 --- /dev/null +++ b/Forge/Compatibility/IsExternalInit.cs @@ -0,0 +1,15 @@ +// Copyright © Gamesmiths Guild. + +#if NETSTANDARD2_1 +#pragma warning disable IDE0130 // Namespace does not match folder structure +namespace System.Runtime.CompilerServices; +#pragma warning restore IDE0130 // Namespace does not match folder structure + +/// +/// Reserved to be used by the compiler for tracking metadata. +/// This class should not be used by developers in source code. +/// +#pragma warning disable S2094 // Remove this empty class, write its code or make it an "interface". +internal static class IsExternalInit; +#pragma warning restore S2094 // Remove this empty class, write its code or make it an "interface". +#endif diff --git a/Forge/Cues/CueData.cs b/Forge/Cues/CueData.cs index ef3af3a..b3b7fe9 100644 --- a/Forge/Cues/CueData.cs +++ b/Forge/Cues/CueData.cs @@ -7,56 +7,24 @@ namespace Gamesmiths.Forge.Cues; /// /// Configuration data for a cue. /// -/// The container with all identifier tags for this cue. -/// The minimum value used for this cue's normalized magnitude calculation. -/// The maximum value used for this cue's normalized magnitude calculation. -/// The type of magnitude to be used for this cue. -/// The modified attribute to be used as magnitude. If the +/// The container with all identifier tags for this cue. +/// The minimum value used for this cue's normalized magnitude calculation. +/// The maximum value used for this cue's normalized magnitude calculation. +/// The type of magnitude to be used for this cue. +/// The modified attribute to be used as magnitude. If the /// effect level will be used instead. /// -/// In case == +/// In case == /// a final channel for the calculation /// must be provided. -public readonly struct CueData( - TagContainer? cueTags, - int minValue, - int maxValue, - CueMagnitudeType magnitudeType, - string? magnitudeAttribute = null, - int finalChannel = 0) +public readonly record struct CueData( + TagContainer? CueTags, + int MinValue, + int MaxValue, + CueMagnitudeType MagnitudeType, + string? MagnitudeAttribute = null, + int FinalChannel = 0) { - /// - /// Gets a container with all the identifier tags for this cue. - /// - public TagContainer? CueTags { get; } = cueTags; - - /// - /// Gets the minimum value used for this cue's normalized magnitude calculation. - /// - public int MinValue { get; } = minValue; - - /// - /// Gets the maximum value used for this cue's normalized magnitude calculation. - /// - public int MaxValue { get; } = maxValue; - - /// - /// Gets the type of magnitude to be used for this cue. - /// - public CueMagnitudeType MagnitudeType { get; } = magnitudeType; - - /// - /// Gets the attribute to be used as magnitude modifier. If the effect level will be used - /// instead. - /// - public string? MagnitudeAttribute { get; } = magnitudeAttribute; - - /// - /// Gets final channel to be used when capturing the magnitude for this cue, specifically for - /// == . - /// - public int FinalChannel { get; } = finalChannel; - /// /// Calculates and gets the normalized magnitude for the given value. /// diff --git a/Forge/Cues/CueParameters.cs b/Forge/Cues/CueParameters.cs index c74fe09..f01da27 100644 --- a/Forge/Cues/CueParameters.cs +++ b/Forge/Cues/CueParameters.cs @@ -7,33 +7,12 @@ namespace Gamesmiths.Forge.Cues; /// /// Contains parameters that can be passed to Cues. /// -/// The magnitude for this cue. -/// The normalized magnitude for this cue between 0 and 1. -/// The source of the cue. -/// Additional custom parameters that can be passed to the cue. -public readonly struct CueParameters( - int magnitude, - float normalizedMagnitude, - IForgeEntity? source = null, - Dictionary? customParameters = null) -{ - /// - /// Gets the magnitude or strength of the effect. - /// - public readonly int Magnitude { get; } = magnitude; - - /// - /// Gets the normalized magnitude (usually between 0 and 1). - /// - public readonly float NormalizedMagnitude { get; } = normalizedMagnitude; - - /// - /// Gets optional source of the cue. - /// - public readonly IForgeEntity? Source { get; } = source; - - /// - /// Gets additional custom parameters that can be passed to the cue. - /// - public readonly Dictionary? CustomParameters { get; } = customParameters; -} +/// The magnitude for this cue. +/// The normalized magnitude for this cue between 0 and 1. +/// The source of the cue. +/// Additional custom parameters that can be passed to the cue. +public readonly record struct CueParameters( + int Magnitude, + float NormalizedMagnitude, + IForgeEntity? Source = null, + Dictionary? CustomParameters = null); diff --git a/Forge/Effects/ActiveEffect.cs b/Forge/Effects/ActiveEffect.cs index 80db8e5..daa6783 100644 --- a/Forge/Effects/ActiveEffect.cs +++ b/Forge/Effects/ActiveEffect.cs @@ -32,7 +32,7 @@ internal sealed class ActiveEffect internal int StackCount { get; private set; } - internal bool IsExpired => EffectData.DurationData.Type == + internal bool IsExpired => EffectData.DurationData.DurationType == DurationType.HasDuration && RemainingDuration <= 0; @@ -281,7 +281,7 @@ internal void RemoveStack() internal void Update(double deltaTime) { - if (EffectData.DurationData.Type == DurationType.HasDuration) + if (EffectData.DurationData.DurationType == DurationType.HasDuration) { RemainingDuration -= deltaTime; @@ -425,11 +425,11 @@ private void ApplyModifiers(bool unapply = false) if (multiplier == 1) { - modifier.Attribute.AddOverride(modifier.AttributeOverride); + modifier.Attribute.AddOverride(modifier.AttributeOverride.Value); break; } - modifier.Attribute.ClearOverride(modifier.AttributeOverride); + modifier.Attribute.ClearOverride(modifier.AttributeOverride.Value); break; } } diff --git a/Forge/Effects/ActiveEffectEvaluatedData.cs b/Forge/Effects/ActiveEffectEvaluatedData.cs index c1d06a8..92e7401 100644 --- a/Forge/Effects/ActiveEffectEvaluatedData.cs +++ b/Forge/Effects/ActiveEffectEvaluatedData.cs @@ -8,42 +8,14 @@ namespace Gamesmiths.Forge.Effects; /// /// Serves as data for event arguments, not really used for optimization. /// -/// The active effect handle for this evaluated data. -/// The evaluated data for the applied effect. -/// The remaining duration for this active effect. -/// The next periodic tick for this active effect, if it's a periodic effect. -/// The execution count for this active effect, if it's a periodic effect. -public readonly struct ActiveEffectEvaluatedData( - ActiveEffectHandle activeEffectHandle, - EffectEvaluatedData effectEvaluatedData, - double remainingDuration, - double nextPeriodicTick, - int executionCount) -{ - /// - /// Gets the active effect for this evaluated data. - /// - public ActiveEffectHandle ActiveEffectHandle { get; } = activeEffectHandle; - - /// - /// Gets the pre-computed evaluated data for the effect. - /// - public EffectEvaluatedData EffectEvaluatedData { get; } = effectEvaluatedData; - - /// - /// Gets the remaining duration for this active effect at the moment of evaluation. - /// - public double RemainingDuration { get; } = remainingDuration; - - /// - /// Gets the next periodic tick for this active effect at the moment of the evaluation in case it's a periodic - /// effect. - /// - public double NextPeriodicTick { get; } = nextPeriodicTick; - - /// - /// Gets the count of executions for this active effect at the moment of the evaluation in case it's a periodic - /// effect. - /// - public int ExecutionCount { get; } = executionCount; -} +/// The active effect handle for this evaluated data. +/// The evaluated data for the applied effect. +/// The remaining duration for this active effect. +/// The next periodic tick for this active effect, if it's a periodic effect. +/// The execution count for this active effect, if it's a periodic effect. +public readonly record struct ActiveEffectEvaluatedData( + ActiveEffectHandle ActiveEffectHandle, + EffectEvaluatedData EffectEvaluatedData, + double RemainingDuration, + double NextPeriodicTick, + int ExecutionCount); diff --git a/Forge/Effects/Components/TagRequirements.cs b/Forge/Effects/Components/TagRequirements.cs index 5a4f447..bf844dc 100644 --- a/Forge/Effects/Components/TagRequirements.cs +++ b/Forge/Effects/Components/TagRequirements.cs @@ -7,33 +7,18 @@ namespace Gamesmiths.Forge.Effects.Components; /// /// A serieis of tag requirements to be evaluated and validated against a . /// -/// The tags that the target container must have. -/// The tags that the target container must not have. -/// An optional tag query that must match. -public readonly struct TagRequirements( - TagContainer? requiredTags = null, - TagContainer? ignoreTags = null, - TagQuery? tagQuery = null) +/// The tags that the target container must have. +/// The tags that the target container must not have. +/// An optional tag query that must match. +public readonly record struct TagRequirements( + TagContainer? RequiredTags = null, + TagContainer? IgnoreTags = null, + TagQuery? TagQuery = null) { - /// - /// Gets the set of required tags for this requirements. - /// - public TagContainer? RequireTags { get; } = requiredTags; - - /// - /// Gets the set of ignored tags for this requirements. - /// - public TagContainer? IgnoreTags { get; } = ignoreTags; - - /// - /// Gets the tag query that this requirements must match. - /// - public TagQuery? TagQuery { get; } = tagQuery; - /// /// Gets a value indicating whether this requirements have no required and ignored tags definied. /// - public readonly bool IsEmpty => (RequireTags?.IsEmpty != false) + public readonly bool IsEmpty => (RequiredTags?.IsEmpty != false) && (IgnoreTags?.IsEmpty != false) && (TagQuery?.IsEmpty != false); @@ -44,7 +29,7 @@ public readonly struct TagRequirements( /// if the requirements are met; otherwise. public bool RequirementsMet(in TagContainer targetContainer) { - var hasRequired = RequireTags is null || targetContainer.HasAll(RequireTags); + var hasRequired = RequiredTags is null || targetContainer.HasAll(RequiredTags); var hasIgnored = IgnoreTags is not null && targetContainer.HasAny(IgnoreTags); var matchQuery = TagQuery?.IsEmpty != false || TagQuery.Matches(targetContainer); diff --git a/Forge/Effects/Duration/DurationData.cs b/Forge/Effects/Duration/DurationData.cs index aead5e0..4fc586e 100644 --- a/Forge/Effects/Duration/DurationData.cs +++ b/Forge/Effects/Duration/DurationData.cs @@ -7,73 +7,7 @@ namespace Gamesmiths.Forge.Effects.Duration; /// /// Duration data for a effect. /// -/// The type of duration for the effect. -/// The duration for this effect in case it's of type . +/// The type of duration for the effect. +/// The duration for this effect in case it's of type . /// -public readonly struct DurationData(DurationType durationType, ScalableFloat? duration = null) - : IEquatable -{ - /// - /// Gets the type of duration for the effect. - /// - public DurationType Type { get; } = durationType; - - /// - /// Gets the duration of the effects. - /// - /// - /// This is only valid for effects with . otherwise. - /// - public ScalableFloat? Duration { get; } = duration; - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(Type); - hash.Add(Duration); - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is DurationData other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(DurationData other) - { - return Type == other.Type - && Duration.Equals(other.Duration); - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(DurationData lhs, DurationData rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(DurationData lhs, DurationData rhs) - { - return !(lhs == rhs); - } -} +public readonly record struct DurationData(DurationType DurationType, ScalableFloat? Duration = null); diff --git a/Forge/Effects/EffectData.cs b/Forge/Effects/EffectData.cs index bcbda7e..a7dfe92 100644 --- a/Forge/Effects/EffectData.cs +++ b/Forge/Effects/EffectData.cs @@ -15,7 +15,7 @@ namespace Gamesmiths.Forge.Effects; /// /// The configuration data for a effect. /// -public readonly struct EffectData : IEquatable +public readonly record struct EffectData { /// /// Gets the name of this effect. @@ -125,80 +125,18 @@ public EffectData( } } - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(Name); - hash.Add(DurationData); - hash.Add(StackingData); - hash.Add(PeriodicData); - hash.Add(SnapshopLevel); - hash.Add(RequireModifierSuccessToTriggerCue); - hash.Add(SuppressStackingCues); - - foreach (CustomExecution execution in CustomExecutions) - { - hash.Add(execution); - } - - foreach (Modifier modifier in Modifiers) - { - hash.Add(modifier); - } - - foreach (IEffectComponent component in EffectComponents) - { - hash.Add(component); - } - - foreach (CueData cue in Cues) - { - hash.Add(cue); - } - - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is EffectData other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(EffectData other) - { - return Name == other.Name - && DurationData.Equals(other.DurationData) - && Nullable.Equals(StackingData, other.StackingData) - && Nullable.Equals(PeriodicData, other.PeriodicData) - && SnapshopLevel == other.SnapshopLevel - && RequireModifierSuccessToTriggerCue == other.RequireModifierSuccessToTriggerCue - && SuppressStackingCues == other.SuppressStackingCues - && CustomExecutions.SequenceEqual(other.CustomExecutions) - && Modifiers.SequenceEqual(other.Modifiers) - && EffectComponents.SequenceEqual(other.EffectComponents) - && Cues.SequenceEqual(other.Cues); - } - private void ValidateData() { Validation.Assert( - !(PeriodicData.HasValue && DurationData.Type == DurationType.Instant), + !(PeriodicData.HasValue && DurationData.DurationType == DurationType.Instant), "Periodic effects can't be set as instant."); Validation.Assert( - !(DurationData.Type != DurationType.HasDuration && DurationData.Duration.HasValue), - $"Can't set duration if {nameof(DurationType)} is set to {DurationData.Type}."); + !(DurationData.DurationType != DurationType.HasDuration && DurationData.Duration.HasValue), + $"Can't set duration if {nameof(DurationType)} is set to {DurationData.DurationType}."); Validation.Assert( - !(StackingData.HasValue && DurationData.Type == DurationType.Instant), + !(StackingData.HasValue && DurationData.DurationType == DurationType.Instant), $"{DurationType.Instant} effects can't have stacks."); Validation.Assert( @@ -258,7 +196,7 @@ private void ValidateData() Validation.Assert( !(StackingData.HasValue - && (DurationData.Type == DurationType.HasDuration != + && (DurationData.DurationType == DurationType.HasDuration != StackingData.Value.ApplicationRefreshPolicy.HasValue)), $"Effects set as {DurationType.HasDuration} must define {nameof(StackApplicationRefreshPolicy)} and not define it if otherwise."); @@ -273,7 +211,7 @@ private void ValidateData() $"Both {nameof(PeriodicData)} and {nameof(StackApplicationResetPeriodPolicy)} must be either defined or undefined."); Validation.Assert( - !(DurationData.Type == DurationType.Instant && Modifiers is not null && Array.Exists( + !(DurationData.DurationType == DurationType.Instant && Modifiers is not null && Array.Exists( Modifiers, x => x.Magnitude.MagnitudeCalculationType == MagnitudeCalculationType.AttributeBased && x.Magnitude.AttributeBasedFloat.HasValue @@ -281,14 +219,14 @@ private void ValidateData() $"Effects set as {DurationType.Instant} and {MagnitudeCalculationType.AttributeBased} cannot be set as non Snapshot."); Validation.Assert( - !(DurationData.Type == DurationType.Instant && !SnapshopLevel), + !(DurationData.DurationType == DurationType.Instant && !SnapshopLevel), $"Effects set as {DurationType.Instant} cannot be set as non Snapshot for Level."); Validation.Assert( EffectComponents is null || !Array.Exists(EffectComponents, x => x is ModifierTagsEffectComponent) || (Array.Exists(EffectComponents, x => x is ModifierTagsEffectComponent) && - DurationData.Type != DurationType.Instant), + DurationData.DurationType != DurationType.Instant), $"Instant effects cannot apply tags from the {nameof(ModifierTagsEffectComponent)}."); foreach (CueData cue in Cues) @@ -315,28 +253,4 @@ EffectComponents is null || "Attribute magnitudes type must have a configured MagnitudeAttribute, and not configured otherwise."); } } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(EffectData lhs, EffectData rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(EffectData lhs, EffectData rhs) - { - return !(lhs == rhs); - } } diff --git a/Forge/Effects/EffectEvaluatedData.cs b/Forge/Effects/EffectEvaluatedData.cs index 125ae39..6b9a1fc 100644 --- a/Forge/Effects/EffectEvaluatedData.cs +++ b/Forge/Effects/EffectEvaluatedData.cs @@ -18,7 +18,7 @@ namespace Gamesmiths.Forge.Effects; /// /// Optimizes performance by avoiding repeated complex calculations and serves as data for event arguments. /// -public readonly struct EffectEvaluatedData +public readonly record struct EffectEvaluatedData { private const string InvalidPeriodicDataException = "Evaluated period must be greater than zero. A non-positive" + " value would cause the effect to loop indefinitely."; @@ -94,7 +94,7 @@ public EffectEvaluatedData( CustomCueParameters = EvaluateCustomCueParameters(); - if (effect.EffectData.DurationData.Type == DurationType.Instant) + if (effect.EffectData.DurationData.DurationType == DurationType.Instant) { AttributesToCapture = []; return; @@ -211,7 +211,7 @@ private float EvaluateModifierMagnitude(ModifierMagnitude modifierMagnitude) private bool IsModifierSnapshop(ModifierMagnitude modifierMagnitude) { - if (Effect.EffectData.DurationData.Type == DurationType.Instant) + if (Effect.EffectData.DurationData.DurationType == DurationType.Instant) { return true; } @@ -241,7 +241,7 @@ private bool IsModifierSnapshop(ModifierMagnitude modifierMagnitude) private EntityAttribute[] CaptureModifierBackingAttribute(ModifierMagnitude modifierMagnitude) { - if (Effect.EffectData.DurationData.Type == DurationType.Instant) + if (Effect.EffectData.DurationData.DurationType == DurationType.Instant) { return []; } diff --git a/Forge/Effects/EffectOwnership.cs b/Forge/Effects/EffectOwnership.cs index 6eb4a6f..ac3dccb 100644 --- a/Forge/Effects/EffectOwnership.cs +++ b/Forge/Effects/EffectOwnership.cs @@ -7,73 +7,6 @@ namespace Gamesmiths.Forge.Effects; /// /// The context of the effect, representing who caused the effect using what. /// -/// Who triggered the action that caused the effect. -/// What object or entity actually caused the effect. -public readonly struct EffectOwnership(IForgeEntity? owner, IForgeEntity? source) : IEquatable -{ - /// - /// Gets the entity responsible for causing the action or event (eg. Character, NPC, Environment). - /// - /// - /// Who caused the effect. - /// - public IForgeEntity? Owner { get; } = owner; - - /// - /// Gets the actual entity that caused the effect (eg. Weapon, Projectile, Trap, the Owner itself). - /// - /// - /// What caused the effect. - /// - public IForgeEntity? Source { get; } = source; - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(Owner); - hash.Add(Source); - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is EffectOwnership other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(EffectOwnership other) - { - return Owner == other.Owner && Source == other.Source; - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(EffectOwnership lhs, EffectOwnership rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(EffectOwnership lhs, EffectOwnership rhs) - { - return !(lhs == rhs); - } -} +/// Who triggered the action that caused the effect. +/// What object or entity actually caused the effect. +public readonly record struct EffectOwnership(IForgeEntity? Owner, IForgeEntity? Source); diff --git a/Forge/Effects/EffectStackInstanceData.cs b/Forge/Effects/EffectStackInstanceData.cs index e4ca935..d4374c4 100644 --- a/Forge/Effects/EffectStackInstanceData.cs +++ b/Forge/Effects/EffectStackInstanceData.cs @@ -7,23 +7,7 @@ namespace Gamesmiths.Forge.Effects; /// /// Data with information about an applied effect stack. /// -/// The owner of the effect stack. -/// The level of the effect stack. -/// The number of stacks in the effect stack. -public readonly struct EffectStackInstanceData(IForgeEntity? owner, int effectLevel, int stackCount) -{ - /// - /// Gets the owner of this effect stack. - /// - public IForgeEntity? Owner { get; } = owner; - - /// - /// Gets the level of this effect stack. - /// - public int EffectLevel { get; } = effectLevel; - - /// - /// Gets the stack count of this effect stack. - /// - public int StackCount { get; } = stackCount; -} +/// The owner of the effect stack. +/// The level of the effect stack. +/// The number of stacks in the effect stack. +public readonly record struct EffectStackInstanceData(IForgeEntity? Owner, int EffectLevel, int StackCount); diff --git a/Forge/Effects/EffectsManager.cs b/Forge/Effects/EffectsManager.cs index a1ed3a5..8c8983e 100644 --- a/Forge/Effects/EffectsManager.cs +++ b/Forge/Effects/EffectsManager.cs @@ -37,7 +37,7 @@ public class EffectsManager(IForgeEntity owner, CuesManager cuesManager) return null; } - if (effect.EffectData.DurationData.Type == DurationType.Instant) + if (effect.EffectData.DurationData.DurationType == DurationType.Instant) { var evaluatedData = new EffectEvaluatedData(effect, Owner); @@ -311,7 +311,7 @@ private void RemoveStackOrUnapply(ActiveEffect? effectToRemove, bool forceUnappl return; } - if (effectToRemove.EffectData.DurationData.Type == DurationType.HasDuration) + if (effectToRemove.EffectData.DurationData.DurationType == DurationType.HasDuration) { forceUnapply = true; } diff --git a/Forge/Effects/Magnitudes/AttributeBasedFloat.cs b/Forge/Effects/Magnitudes/AttributeBasedFloat.cs index d03ffdf..d023a67 100644 --- a/Forge/Effects/Magnitudes/AttributeBasedFloat.cs +++ b/Forge/Effects/Magnitudes/AttributeBasedFloat.cs @@ -15,61 +15,25 @@ namespace Gamesmiths.Forge.Effects.Magnitudes; /// The captured attribute can also be a snapshot at the moment of creation or updated whenever the target /// attribute updates its value. /// -/// Information about which and attribute should be captured and how. -/// How the magnitude is going to be extracted from the given attribute. -/// Value to be multiplied with the calculcuated magnitude. -/// Value to be added to the magnitude before multiplying the coeficient. -/// Value to be added to the magnitude after multiplying the coeficient. -/// In case == +/// Information about which and attribute should be captured and how. +/// How the magnitude is going to be extracted from the given attribute. +/// Value to be multiplied with the calculcuated magnitude. +/// Value to be added to the magnitude before multiplying the coeficient. +/// Value to be added to the magnitude after multiplying the coeficient. +/// In case == /// a final channel for the calculation /// must be provided. -/// If provided, the final evaluated magnitude will be used as a lookup into this curve. +/// If provided, the final evaluated magnitude will be used as a lookup into this curve. /// -public readonly struct AttributeBasedFloat( - AttributeCaptureDefinition backingAttribute, - AttributeCalculationType attributeCalculationType, - ScalableFloat coefficient, - ScalableFloat preMultiplyAdditiveValue, - ScalableFloat postMultiplyAdditiveValue, - int finalChannel = 0, - ICurve? lookupCurve = null) : IEquatable +public readonly record struct AttributeBasedFloat( + AttributeCaptureDefinition BackingAttribute, + AttributeCalculationType AttributeCalculationType, + ScalableFloat Coefficient, + ScalableFloat PreMultiplyAdditiveValue, + ScalableFloat PostMultiplyAdditiveValue, + int FinalChannel = 0, + ICurve? LookupCurve = null) { - /// - /// Gets the capture definition for the backing attribute. - /// - public AttributeCaptureDefinition BackingAttribute { get; } = backingAttribute; - - /// - /// Gets the calculation type used to capture the base magnitude. - /// - public AttributeCalculationType AttributeCalculationType { get; } = attributeCalculationType; - - /// - /// Gets the coeficient to be multiplied with the captured magnitude. - /// - public ScalableFloat Coefficient { get; } = coefficient; - - /// - /// Gets the value to be added to the captured magnitude before multiplying the coefficient. - /// - public ScalableFloat PreMultiplyAdditiveValue { get; } = preMultiplyAdditiveValue; - - /// - /// Gets the value to be added to the captured magnitude after multiplying the coefficient. - /// - public ScalableFloat PostMultiplyAdditiveValue { get; } = postMultiplyAdditiveValue; - - /// - /// Gets a value for the final channel when capturing the magnitude using - /// . - /// - public int FinalChannel { get; } = finalChannel; - - /// - /// Gets the curve entry to use as a lookup instead of directly using the evaluated magnitude. - /// - public ICurve? LookupCurve { get; } = lookupCurve; - /// /// Calculates the final magnitude based on the AttributeBasedFloat configurations. /// @@ -156,64 +120,4 @@ public readonly float CalculateMagnitude(Effect effect, IForgeEntity target, int return finalMagnitude; } - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(BackingAttribute); - hash.Add(AttributeCalculationType); - hash.Add(Coefficient); - hash.Add(PreMultiplyAdditiveValue); - hash.Add(PostMultiplyAdditiveValue); - hash.Add(FinalChannel); - - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is AttributeBasedFloat other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(AttributeBasedFloat other) - { - return BackingAttribute.Equals(other.BackingAttribute) - && AttributeCalculationType.Equals(other.AttributeCalculationType) - && Coefficient.Equals(other.Coefficient) - && PreMultiplyAdditiveValue.Equals(other.PreMultiplyAdditiveValue) - && PostMultiplyAdditiveValue.Equals(other.PostMultiplyAdditiveValue) - && Equals(FinalChannel, other.FinalChannel); - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(AttributeBasedFloat lhs, AttributeBasedFloat rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(AttributeBasedFloat lhs, AttributeBasedFloat rhs) - { - return !(lhs == rhs); - } } diff --git a/Forge/Effects/Magnitudes/AttributeCaptureDefinition.cs b/Forge/Effects/Magnitudes/AttributeCaptureDefinition.cs index 7538b8b..33f4680 100644 --- a/Forge/Effects/Magnitudes/AttributeCaptureDefinition.cs +++ b/Forge/Effects/Magnitudes/AttributeCaptureDefinition.cs @@ -9,34 +9,14 @@ namespace Gamesmiths.Forge.Effects.Magnitudes; /// /// Set of data that definies how an attribute is going to be captured. /// -/// Which attribute to capture. -/// From what target to capture the attribute from. -/// Whether the captured value should be a snapshot or not. -public readonly struct AttributeCaptureDefinition( - StringKey attribute, - AttributeCaptureSource source, - bool snapshot = true) : IEquatable +/// Which attribute to capture. +/// From what target to capture the attribute from. +/// Whether the captured value should be a snapshot or not. +public readonly record struct AttributeCaptureDefinition( + StringKey Attribute, + AttributeCaptureSource Source, + bool Snapshot = true) { - /// - /// Gets a key indicating which attribute is being captured. - /// - public StringKey Attribute { get; } = attribute; - - /// - /// Gets the source entity from where the attribute is being captured from. - /// - public AttributeCaptureSource Source { get; } = source; - - /// - /// Gets a value indicating whether snapshot is enabled. A snapshot indicates that the value is saved at the moment - /// of effect creation. Non-snapshop captures are updated when the target attribute is updated. - /// - /// - /// Only effects with == or - /// == can snapshot. - /// - public bool Snapshot { get; } = snapshot; - /// /// Tries to retrieve the captured attribute for a given entity. /// @@ -56,57 +36,4 @@ public readonly bool TryGetAttribute(IForgeEntity? source, [NotNullWhen(true)] o return true; } - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(Attribute); - hash.Add(Source); - hash.Add(Snapshot); - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is AttributeCaptureDefinition other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(AttributeCaptureDefinition other) - { - return Attribute.Equals(other.Attribute) - && Source.Equals(other.Source) - && Snapshot == other.Snapshot; - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(AttributeCaptureDefinition lhs, AttributeCaptureDefinition rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(AttributeCaptureDefinition lhs, AttributeCaptureDefinition rhs) - { - return !(lhs == rhs); - } } diff --git a/Forge/Effects/Magnitudes/CustomCalculationBasedFloat.cs b/Forge/Effects/Magnitudes/CustomCalculationBasedFloat.cs index 353590d..b3f840d 100644 --- a/Forge/Effects/Magnitudes/CustomCalculationBasedFloat.cs +++ b/Forge/Effects/Magnitudes/CustomCalculationBasedFloat.cs @@ -15,44 +15,19 @@ namespace Gamesmiths.Forge.Effects.Magnitudes; /// finalValue = (coefficient * (calculatedMagnitude + preMultiply)) + postMultiply; /// /// -/// The magnitude calculator class to be used for magnitude calculation. -/// Value to be multiplied with the calculcuated magnitude. -/// Value to be added to the magnitude before multiplying the coeficient. -/// Value to be added to the magnitude after multiplying the coeficient. -/// If provided, the final evaluated magnitude will be used as a lookup into this curve. +/// The magnitude calculator class to be used for magnitude calculation. +/// Value to be multiplied with the calculcuated magnitude. +/// Value to be added to the magnitude before multiplying the coeficient. +/// Value to be added to the magnitude after multiplying the coeficient. +/// If provided, the final evaluated magnitude will be used as a lookup into this curve. /// -public readonly struct CustomCalculationBasedFloat( - CustomModifierMagnitudeCalculator magnitudeCalculatorClass, - ScalableFloat coefficient, - ScalableFloat preMultiplyAdditiveValue, - ScalableFloat postMultiplyAdditiveValue, - ICurve? lookupCurve = null) : IEquatable +public readonly record struct CustomCalculationBasedFloat( + CustomModifierMagnitudeCalculator MagnitudeCalculatorClass, + ScalableFloat Coefficient, + ScalableFloat PreMultiplyAdditiveValue, + ScalableFloat PostMultiplyAdditiveValue, + ICurve? LookupCurve = null) { - /// - /// Gets the magnitude calculator class used to calculate the magnitude. - /// - public CustomModifierMagnitudeCalculator MagnitudeCalculatorClass { get; } = magnitudeCalculatorClass; - - /// - /// Gets the coeficient to be multiplied with the captured magnitude. - /// - public ScalableFloat Coefficient { get; } = coefficient; - - /// - /// Gets the value to be added to the captured magnitude before multiplying the coefficient. - /// - public ScalableFloat PreMultiplyAdditiveValue { get; } = preMultiplyAdditiveValue; - - /// - /// Gets the value to be added to the captured magnitude after multiplying the coefficient. - /// - public ScalableFloat PostMultiplyAdditiveValue { get; } = postMultiplyAdditiveValue; - - /// - /// Gets the curve entry to use as a lookup instead of directly using the evaluated magnitude. - /// - public ICurve? LookupCurve { get; } = lookupCurve; - /// /// Calculates the final magnitude based on the CustomCalculationBasedFloat configurations. /// @@ -74,60 +49,4 @@ public float CalculateMagnitude(in Effect effect, IForgeEntity target, int level return finalMagnitude; } - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(MagnitudeCalculatorClass); - hash.Add(Coefficient); - hash.Add(PreMultiplyAdditiveValue); - hash.Add(PostMultiplyAdditiveValue); - - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is CustomCalculationBasedFloat other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(CustomCalculationBasedFloat other) - { - return MagnitudeCalculatorClass.Equals(other.MagnitudeCalculatorClass) - && Coefficient.Equals(other.Coefficient) - && PreMultiplyAdditiveValue.Equals(other.PreMultiplyAdditiveValue) - && PostMultiplyAdditiveValue.Equals(other.PostMultiplyAdditiveValue); - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(CustomCalculationBasedFloat lhs, CustomCalculationBasedFloat rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(CustomCalculationBasedFloat lhs, CustomCalculationBasedFloat rhs) - { - return !(lhs == rhs); - } } diff --git a/Forge/Effects/Magnitudes/ModifierMagnitude.cs b/Forge/Effects/Magnitudes/ModifierMagnitude.cs index 3b33288..410d42b 100644 --- a/Forge/Effects/Magnitudes/ModifierMagnitude.cs +++ b/Forge/Effects/Magnitudes/ModifierMagnitude.cs @@ -7,7 +7,7 @@ namespace Gamesmiths.Forge.Effects.Magnitudes; /// /// Provides a magnitude for the in a . /// -public readonly struct ModifierMagnitude : IEquatable +public readonly record struct ModifierMagnitude { /// /// Gets the type of magnitude calculation being used for this magnitude. @@ -131,58 +131,4 @@ public readonly float GetMagnitude(Effect effect, IForgeEntity target, int? leve return 0; } } - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(MagnitudeCalculationType); - hash.Add(ScalableFloatMagnitude); - hash.Add(AttributeBasedFloat); - - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is ModifierMagnitude other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(ModifierMagnitude other) - { - return MagnitudeCalculationType.Equals(other.MagnitudeCalculationType) - && Nullable.Equals(ScalableFloatMagnitude, other.ScalableFloatMagnitude) - && Nullable.Equals(AttributeBasedFloat, other.AttributeBasedFloat); - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(ModifierMagnitude lhs, ModifierMagnitude rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(ModifierMagnitude lhs, ModifierMagnitude rhs) - { - return !(lhs == rhs); - } } diff --git a/Forge/Effects/Magnitudes/ScalableFloat.cs b/Forge/Effects/Magnitudes/ScalableFloat.cs index 06b79cc..5f9d363 100644 --- a/Forge/Effects/Magnitudes/ScalableFloat.cs +++ b/Forge/Effects/Magnitudes/ScalableFloat.cs @@ -8,20 +8,10 @@ namespace Gamesmiths.Forge.Effects.Magnitudes; /// A scalable float is a magnitude value that associates a float with a curve that can be evaluated and scaled over /// time. /// -/// The base value for this magnitude. -/// The curve used for scaling. -public readonly struct ScalableFloat(float baseValue, ICurve? curve = null) : IEquatable +/// The base value for this magnitude. +/// The curve used for scaling. +public readonly record struct ScalableFloat(float BaseValue, ICurve? ScalingCurve = null) { - /// - /// Gets the base value for this scalable float. - /// - public float BaseValue { get; } = baseValue; - - /// - /// Gets the curve fort this scalable float. - /// - public ICurve? ScalingCurve { get; } = curve; - /// /// Gets an evaluated value for this scalable float at the given time. /// @@ -37,57 +27,4 @@ public float GetValue(float time) var scalingFactor = ScalingCurve.Evaluate(time); return BaseValue * scalingFactor; } - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(BaseValue); - hash.Add(ScalingCurve); - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is ScalableFloat other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(ScalableFloat other) - { -#pragma warning disable S1244 // Floating point numbers should not be tested for equality - return BaseValue == other.BaseValue - && ScalingCurve == other.ScalingCurve; -#pragma warning restore S1244 // Floating point numbers should not be tested for equality - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(ScalableFloat lhs, ScalableFloat rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(ScalableFloat lhs, ScalableFloat rhs) - { - return !(lhs == rhs); - } } diff --git a/Forge/Effects/Magnitudes/ScalableInt.cs b/Forge/Effects/Magnitudes/ScalableInt.cs index dd4b1a3..2e297e5 100644 --- a/Forge/Effects/Magnitudes/ScalableInt.cs +++ b/Forge/Effects/Magnitudes/ScalableInt.cs @@ -8,20 +8,10 @@ namespace Gamesmiths.Forge.Effects.Magnitudes; /// A scalable int is a magnitude value that associates an integer with a curve that can be evaluated and scaled over /// time. /// -/// The base value for this magnitude. -/// The curve used for scaling. -public readonly struct ScalableInt(int baseValue, ICurve? curve = null) : IEquatable +/// The base value for this magnitude. +/// The curve used for scaling. +public readonly record struct ScalableInt(int BaseValue, ICurve? ScalingCurve = null) { - /// - /// Gets the base value for this scalable int. - /// - public int BaseValue { get; } = baseValue; - - /// - /// Gets the curve fort this scalable int. - /// - public ICurve? ScalingCurve { get; } = curve; - /// /// Gets an evaluated value for this scalable int at the given time. /// @@ -37,55 +27,4 @@ public readonly int GetValue(float time) var scalingFactor = ScalingCurve.Evaluate(time); return (int)(BaseValue * scalingFactor); } - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(BaseValue); - hash.Add(ScalingCurve); - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is ScalableInt other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(ScalableInt other) - { - return BaseValue == other.BaseValue - && ScalingCurve == other.ScalingCurve; - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(ScalableInt lhs, ScalableInt rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(ScalableInt lhs, ScalableInt rhs) - { - return !(lhs == rhs); - } } diff --git a/Forge/Effects/Magnitudes/SetByCallerFloat.cs b/Forge/Effects/Magnitudes/SetByCallerFloat.cs index a55a691..22f2b83 100644 --- a/Forge/Effects/Magnitudes/SetByCallerFloat.cs +++ b/Forge/Effects/Magnitudes/SetByCallerFloat.cs @@ -7,61 +7,8 @@ namespace Gamesmiths.Forge.Effects.Magnitudes; /// /// A set by caller float is a magnitude used for allowing the caller to set a specific value before applying an effect. /// -/// The tag used to identify this custom magnitude. +/// The tag used to identify this custom magnitude. /// /// A is used for mapping different possible custom values. /// -public readonly struct SetByCallerFloat(Tag tag) : IEquatable -{ - /// - /// Gets the tag used for identifying the custom value set. - /// - public readonly Tag Tag { get; } = tag; - - /// - public override int GetHashCode() - { - return Tag.GetHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is SetByCallerFloat other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(SetByCallerFloat other) - { - return Tag == other.Tag; - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(SetByCallerFloat lhs, SetByCallerFloat rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(SetByCallerFloat lhs, SetByCallerFloat rhs) - { - return !(lhs == rhs); - } -} +public readonly record struct SetByCallerFloat(Tag Tag); diff --git a/Forge/Effects/ModifierEvaluatedData.cs b/Forge/Effects/ModifierEvaluatedData.cs index 878e9d7..b35a1f3 100644 --- a/Forge/Effects/ModifierEvaluatedData.cs +++ b/Forge/Effects/ModifierEvaluatedData.cs @@ -11,7 +11,7 @@ namespace Gamesmiths.Forge.Effects; /// /// Optimizes performance by avoiding repeated complex calculations and serves as data for event arguments. /// -public readonly struct ModifierEvaluatedData +public readonly record struct ModifierEvaluatedData { /// /// Gets the target attribute of this modifier. diff --git a/Forge/Effects/Modifiers/Modifier.cs b/Forge/Effects/Modifiers/Modifier.cs index be80963..b063baa 100644 --- a/Forge/Effects/Modifiers/Modifier.cs +++ b/Forge/Effects/Modifiers/Modifier.cs @@ -8,88 +8,12 @@ namespace Gamesmiths.Forge.Effects.Modifiers; /// /// A modifier that affects an attribute with the given configuration. /// -/// The target attribute to be modified. -/// The type of operation to be used. -/// The magnitude calculation and configurations to be used. -/// The channel to be affected by this modifier. -public readonly struct Modifier( - StringKey attribute, - ModifierOperation operation, - ModifierMagnitude magnitude, - int channel = 0) : IEquatable -{ - /// - /// Gets the attribute being modified by this modifier. - /// - public StringKey Attribute { get; } = attribute; - - /// - /// Gets the type of operation this modifier is using. - /// - public ModifierOperation Operation { get; } = operation; - - /// - /// Gets the magnitude calculation and configurations this modifier is using. - /// - public ModifierMagnitude Magnitude { get; } = magnitude; - - /// - /// Gets which channel this modifier is being applied to. - /// - public int Channel { get; } = channel; - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(Attribute); - hash.Add(Operation); - hash.Add(Magnitude); - hash.Add(Channel); - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is Modifier other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(Modifier other) - { - return Attribute == other.Attribute - && Operation.Equals(other.Operation) - && Magnitude.Equals(other.Magnitude) - && Channel.Equals(other.Channel); - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(Modifier lhs, Modifier rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(Modifier lhs, Modifier rhs) - { - return !(lhs == rhs); - } -} +/// The target attribute to be modified. +/// The type of operation to be used. +/// The magnitude calculation and configurations to be used. +/// The channel to be affected by this modifier. +public readonly record struct Modifier( + StringKey Attribute, + ModifierOperation Operation, + ModifierMagnitude Magnitude, + int Channel = 0); diff --git a/Forge/Effects/Periodic/PeriodicData.cs b/Forge/Effects/Periodic/PeriodicData.cs index 037a42f..7b0dcbb 100644 --- a/Forge/Effects/Periodic/PeriodicData.cs +++ b/Forge/Effects/Periodic/PeriodicData.cs @@ -7,80 +7,10 @@ namespace Gamesmiths.Forge.Effects.Periodic; /// /// The periodic data for a effect. /// -/// The duration for the periodic triggers for the effect. -/// If the periodic effect should trigger on application. -/// How to handle periods when inhibition is removed. -public readonly struct PeriodicData( - ScalableFloat period, - bool executeOnApplication, - PeriodInhibitionRemovedPolicy periodInhibitionRemovedPolicy) : IEquatable -{ - /// - /// Gets the period duration for the periodic effect. - /// - public ScalableFloat Period { get; } = period; - - /// - /// Gets a value indicating whether this effect should execute its periodic effect on application or not. - /// - public bool ExecuteOnApplication { get; } = executeOnApplication; - - /// - /// Gets a value for the policy to use when the period inhibition is removed. - /// - public PeriodInhibitionRemovedPolicy PeriodInhibitionRemovedPolicy { get; } = periodInhibitionRemovedPolicy; - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(Period); - hash.Add(ExecuteOnApplication); - hash.Add(PeriodInhibitionRemovedPolicy); - - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is PeriodicData other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(PeriodicData other) - { - return Period == other.Period - && ExecuteOnApplication.Equals(other.ExecuteOnApplication) - && PeriodInhibitionRemovedPolicy == other.PeriodInhibitionRemovedPolicy; - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(PeriodicData lhs, PeriodicData rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(PeriodicData lhs, PeriodicData rhs) - { - return !(lhs == rhs); - } -} +/// The duration for the periodic triggers for the effect. +/// If the periodic effect should trigger on application. +/// How to handle periods when inhibition is removed. +public readonly record struct PeriodicData( + ScalableFloat Period, + bool ExecuteOnApplication, + PeriodInhibitionRemovedPolicy PeriodInhibitionRemovedPolicy); diff --git a/Forge/Effects/Stacking/StackingData.cs b/Forge/Effects/Stacking/StackingData.cs index a6d8607..3bafd8a 100644 --- a/Forge/Effects/Stacking/StackingData.cs +++ b/Forge/Effects/Stacking/StackingData.cs @@ -1,241 +1,45 @@ // Copyright © Gamesmiths Guild. -using Gamesmiths.Forge.Effects.Duration; using Gamesmiths.Forge.Effects.Magnitudes; -using Gamesmiths.Forge.Effects.Periodic; namespace Gamesmiths.Forge.Effects.Stacking; /// /// The stacking data for a effect. /// -/// Max number of stacks. -/// The initial number of stacks when first applied. -/// How stacks aggregate based on target and owner. -/// How stacks aggregate based on effect level. -/// How the magnitude value of the effect is handled. -/// What happens when the stack limit is reached. -/// What happens to stacks when the effect duration expires. -/// How to handle applications from different owner. -/// How to handle the effect's instance owner when accepting application +/// Max number of stacks. +/// The initial number of stacks when first applied. +/// How stacks aggregate based on target and owner. +/// How stacks aggregate based on effect level. +/// How the magnitude value of the effect is handled. +/// What happens when the stack limit is reached. +/// What happens to stacks when the effect duration expires. +/// How to handle applications from different owner. +/// How to handle the effect's instance owner when accepting application /// from different owner. -/// How to handle the stack count when the owner is overriden. +/// How to handle the stack count when the owner is overriden. /// -/// How to handle stack applications of different levels. -/// How to handle the effect's instance level when accepting applications of different +/// How to handle stack applications of different levels. +/// How to handle the effect's instance level when accepting applications of different /// levels. -/// How to handle the stack count when the level is overriden. -/// What happens with the stack duration when a new stack is applied. -/// What happens with periodic durations when a new stack is applied. -/// Whether the effect executes when a new stack is applied. -public readonly struct StackingData( - ScalableInt stackLimit, - ScalableInt initialStack, - StackPolicy stackPolicy, - StackLevelPolicy stackLevelPolicy, - StackMagnitudePolicy magnitudePolicy, - StackOverflowPolicy overflowPolicy, - StackExpirationPolicy expirationPolicy, - StackOwnerDenialPolicy? ownerDenialPolicy = null, - StackOwnerOverridePolicy? ownerOverridePolicy = null, - StackOwnerOverrideStackCountPolicy? ownerOverrideStackCountPolicy = null, - LevelComparison? levelDenialPolicy = null, - LevelComparison? levelOverridePolicy = null, - StackLevelOverrideStackCountPolicy? levelOverrideStackCountPolicy = null, - StackApplicationRefreshPolicy? applicationRefreshPolicy = null, - StackApplicationResetPeriodPolicy? applicationResetPeriodPolicy = null, - bool? executeOnSuccessfulApplication = null) : IEquatable -{ - /// - /// Gets the stack limit for this stackable effect. - /// - public ScalableInt StackLimit { get; } = stackLimit; - - /// - /// Gets the initial stack value for this stackable effect. - /// - public ScalableInt InitialStack { get; } = initialStack; - - /// - /// Gets the stack policy for this stackable effect. - /// - public StackPolicy StackPolicy { get; } = stackPolicy; - - /// - /// Gets the stack level policy for this stackable effect. - /// - public StackLevelPolicy StackLevelPolicy { get; } = stackLevelPolicy; - - /// - /// Gets the magnitude policy for this stackable effect. - /// - public StackMagnitudePolicy MagnitudePolicy { get; } = magnitudePolicy; - - /// - /// Gets the overflow policy for this stackable effect. - /// - public StackOverflowPolicy OverflowPolicy { get; } = overflowPolicy; - - /// - /// Gets the expiration policy for this stackable effect. - /// - /// - /// Infinite effects removal will count as expiration. - /// - public StackExpirationPolicy ExpirationPolicy { get; } = expirationPolicy; - - /// - /// Gets the owner denial policy for this stackable effect. - /// - /// - /// Only valid when == . - /// - public StackOwnerDenialPolicy? OwnerDenialPolicy { get; } = ownerDenialPolicy; - - /// - /// Gets the owner override policy for this stackable effect. - /// - /// - /// Only valid when == . - /// - public StackOwnerOverridePolicy? OwnerOverridePolicy { get; } = ownerOverridePolicy; - - /// - /// Gets the owner override stack count policy for this stackable effect. - /// - /// - /// Only valid when == and - /// == . - /// - public StackOwnerOverrideStackCountPolicy? OwnerOverrideStackCountPolicy { get; } = - ownerOverrideStackCountPolicy; - - /// - /// Gets the level denial policy for this stackable effect. - /// - /// - /// Only valid when == . - /// - public LevelComparison? LevelDenialPolicy { get; } = levelDenialPolicy; - - /// - /// Gets the level override policy for this stackable effect. - /// - /// - /// Only valid when == . - /// - public LevelComparison? LevelOverridePolicy { get; } = levelOverridePolicy; - - /// - /// Gets the level override stack count policy for this stackable effect. - /// - /// - /// Only valid when == and - /// != . - /// - public StackLevelOverrideStackCountPolicy? LevelOverrideStackCountPolicy { get; } = levelOverrideStackCountPolicy; - - /// - /// Gets the application refresh policy for this stackable effect. - /// - /// - /// Only valid for effects set as . - /// - public StackApplicationRefreshPolicy? ApplicationRefreshPolicy { get; } = applicationRefreshPolicy; - - /// - /// Gets the application reset period policy for this stackable effect. - /// - /// - /// Only valid for effects that have . - /// - public StackApplicationResetPeriodPolicy? ApplicationResetPeriodPolicy { get; } = applicationResetPeriodPolicy; - - /// - /// Gets a value indicating whether this periodic effect executes on successful stack application. - /// - /// - /// Only valid for effects that have . - /// - public bool? ExecuteOnSuccessfulApplication { get; } = executeOnSuccessfulApplication; - - /// - public override int GetHashCode() - { - var hash = default(HashCode); - hash.Add(StackLimit); - hash.Add(InitialStack); - hash.Add(StackPolicy); - hash.Add(StackLevelPolicy); - hash.Add(MagnitudePolicy); - hash.Add(OverflowPolicy); - hash.Add(ExpirationPolicy); - hash.Add(OwnerDenialPolicy); - hash.Add(OwnerOverridePolicy); - hash.Add(OwnerOverrideStackCountPolicy); - hash.Add(LevelDenialPolicy); - hash.Add(LevelOverridePolicy); - hash.Add(LevelOverrideStackCountPolicy); - hash.Add(ApplicationRefreshPolicy); - hash.Add(ApplicationResetPeriodPolicy); - hash.Add(ExecuteOnSuccessfulApplication); - - return hash.ToHashCode(); - } - - /// - public override bool Equals(object? obj) - { - if (obj is StackingData other) - { - return Equals(other); - } - - return false; - } - - /// - public bool Equals(StackingData other) - { - return StackLimit.Equals(other.StackLimit) - && InitialStack.Equals(other.InitialStack) - && StackPolicy.Equals(other.StackPolicy) - && StackLevelPolicy.Equals(other.StackLevelPolicy) - && MagnitudePolicy.Equals(other.MagnitudePolicy) - && OverflowPolicy.Equals(other.OverflowPolicy) - && ExpirationPolicy.Equals(other.ExpirationPolicy) - && Nullable.Equals(OwnerDenialPolicy, other.OwnerDenialPolicy) - && Nullable.Equals(OwnerOverridePolicy, other.OwnerOverridePolicy) - && Nullable.Equals(OwnerOverrideStackCountPolicy, other.OwnerOverrideStackCountPolicy) - && Nullable.Equals(LevelDenialPolicy, other.LevelDenialPolicy) - && Nullable.Equals(LevelOverridePolicy, other.LevelOverridePolicy) - && Nullable.Equals(LevelOverrideStackCountPolicy, other.LevelOverrideStackCountPolicy) - && Nullable.Equals(ApplicationRefreshPolicy, other.ApplicationRefreshPolicy) - && Nullable.Equals(ApplicationResetPeriodPolicy, other.ApplicationResetPeriodPolicy) - && Nullable.Equals(ExecuteOnSuccessfulApplication, other.ExecuteOnSuccessfulApplication); - } - - /// - /// Determines if two objects are equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are equal; - /// otherwise, . - public static bool operator ==(StackingData lhs, StackingData rhs) - { - return lhs.Equals(rhs); - } - - /// - /// Determines if two objects are not equal. - /// - /// The first to compare. - /// The second to compare. - /// if the values of and are not - /// equal; otherwise, . - public static bool operator !=(StackingData lhs, StackingData rhs) - { - return !(lhs == rhs); - } -} +/// How to handle the stack count when the level is overriden. +/// What happens with the stack duration when a new stack is applied. +/// What happens with periodic durations when a new stack is applied. +/// Whether the effect executes when a new stack is applied. +public readonly record struct StackingData( + ScalableInt StackLimit, + ScalableInt InitialStack, + StackPolicy StackPolicy, + StackLevelPolicy StackLevelPolicy, + StackMagnitudePolicy MagnitudePolicy, + StackOverflowPolicy OverflowPolicy, + StackExpirationPolicy ExpirationPolicy, + StackOwnerDenialPolicy? OwnerDenialPolicy = null, + StackOwnerOverridePolicy? OwnerOverridePolicy = null, + StackOwnerOverrideStackCountPolicy? OwnerOverrideStackCountPolicy = null, + LevelComparison? LevelDenialPolicy = null, + LevelComparison? LevelOverridePolicy = null, + StackLevelOverrideStackCountPolicy? LevelOverrideStackCountPolicy = null, + StackApplicationRefreshPolicy? ApplicationRefreshPolicy = null, + StackApplicationResetPeriodPolicy? ApplicationResetPeriodPolicy = null, + bool? ExecuteOnSuccessfulApplication = null);