-
Notifications
You must be signed in to change notification settings - Fork 504
DK Master Tree Finishup #766
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
base: master
Are you sure you want to change the base?
Changes from all commits
cf29196
7be1f3e
d21e5fd
722e876
25da2be
c65ef5a
6022df1
47aa81d
b70dfd5
05440a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,18 +68,10 @@ private float GetAndCacheValue() | |
| 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)) | ||
| if (this.Elements.All(e => e.AggregateType == AggregateType.Multiplicate)) | ||
| { | ||
| rawValues = 1; | ||
| } | ||
|
Comment on lines
+71
to
74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new logic for defaulting if (this.Elements.All(e => e.AggregateType != AggregateType.AddRaw))
{
rawValues = 1;
}
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would fail if we have only In case the attribute has different values, like |
||
| else | ||
| { | ||
| // nothing to do | ||
| } | ||
|
|
||
| var newValue = (rawValues * multiValues) + finalValues; | ||
| if (this._maximumValue.HasValue) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,13 +21,17 @@ public static class AttackableExtensions | |
| { | ||
| private const short ExplosionMagicEffectNumber = 75; // 0x4B | ||
|
|
||
| private const short StunnedMagicEffectNumber = 61; // 0x3D | ||
|
|
||
| private static readonly IDictionary<AttributeDefinition, AttributeDefinition> ReductionModifiers = | ||
| new Dictionary<AttributeDefinition, AttributeDefinition> | ||
| { | ||
| { Stats.CurrentMana, Stats.ManaUsageReduction }, | ||
| { Stats.CurrentAbility, Stats.AbilityUsageReduction }, | ||
| }; | ||
|
|
||
| private static MagicEffectDefinition? stunEffectDefinition; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The static field
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That seems to make sense. Remove |
||
|
|
||
| extension(IAttackable attackable) | ||
| { | ||
| /// <summary> | ||
|
|
@@ -327,7 +331,7 @@ public static async ValueTask ApplyMagicEffectAsync(this IAttackable target, IAt | |
| } | ||
|
|
||
| float chance = target is Player ? skillEntry.PowerUpChancePvp!.Value : skillEntry.PowerUpChance!.Value; | ||
| if (!Rand.NextRandomBool(Convert.ToDouble(chance))) | ||
| if (!Rand.NextRandomBool(chance)) | ||
| { | ||
| return; | ||
| } | ||
|
|
@@ -597,6 +601,20 @@ public static double CalculateBaseExperience(this IAttackable killedObject, floa | |
| return Math.Max(tempExperience, 0) * 1.25; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Applies the mace mastery stun effect to the specified attackable. | ||
| /// </summary> | ||
| /// <param name="attacker">The attacker.</param> | ||
| /// <param name="attackable">The attackable.</param> | ||
| /// <returns>A task representing the asynchronous operation.</returns> | ||
| public static async ValueTask ApplyMaceMasteryStunEffectAsync(this Player attacker, IAttackable attackable) | ||
| { | ||
| stunEffectDefinition ??= attacker.GameContext.Configuration.MagicEffects.First(m => m.Number == StunnedMagicEffectNumber); | ||
| var powerUp = attackable.Attributes.CreateElement(stunEffectDefinition.PowerUpDefinitions.First(pu => pu.TargetAttribute == Stats.IsStunned)); | ||
| var magicEffect = new MagicEffect(TimeSpan.FromSeconds(2), stunEffectDefinition, [new MagicEffect.ElementWithTarget(powerUp, Stats.IsStunned)]); | ||
| await attackable.MagicEffectList.AddEffectAsync(magicEffect).ConfigureAwait(false); | ||
| } | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| private static bool IsAttackSuccessfulTo(this IAttacker attacker, IAttackable defender) | ||
| { | ||
| var hitChance = attacker.GetHitChanceTo(defender); | ||
|
|
@@ -863,8 +881,8 @@ private static async ValueTask ApplyMagicEffectAsync(this IAttackable target, IA | |
| } | ||
| else if (magicEffectDefinition.PowerUpDefinitions.Any(e => e.TargetAttribute == Stats.IsStunned)) | ||
| { | ||
| var stunChancePowerUp = powerUps.FirstOrDefault(p => p.Target == Stats.StunChance); | ||
| if (stunChancePowerUp.Boost is null || !Rand.NextRandomBool(Convert.ToDouble(stunChancePowerUp.Boost.Value))) | ||
| var stunChancePowerUp = powerUps.FirstOrDefault(p => p.Target == Stats.MasteryStunChance); | ||
| if (stunChancePowerUp.Boost is null || !Rand.NextRandomBool(stunChancePowerUp.Boost.Value)) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,8 @@ public sealed class PowerUpWrapper : IElement, IDisposable | |
| { | ||
| private readonly IElement _element; | ||
|
|
||
| private readonly AggregateType? _aggregateType; | ||
|
|
||
| private ComposableAttribute? _parentAttribute; | ||
|
|
||
| /// <summary> | ||
|
|
@@ -22,7 +24,8 @@ public sealed class PowerUpWrapper : IElement, IDisposable | |
| /// <param name="element">The element.</param> | ||
| /// <param name="targetAttribute">The target attribute.</param> | ||
| /// <param name="attributeHolder">The attribute holder.</param> | ||
| public PowerUpWrapper(IElement element, AttributeDefinition targetAttribute, AttributeSystem attributeHolder) | ||
| /// <param name="aggregateType">The aggregate type that should override the <paramref name="element"/>'s.</param> | ||
| public PowerUpWrapper(IElement element, AttributeDefinition targetAttribute, AttributeSystem attributeHolder, AggregateType? aggregateType = null) | ||
| { | ||
| this._parentAttribute = attributeHolder.GetComposableAttribute(targetAttribute); | ||
| if (this._parentAttribute is null) | ||
|
|
@@ -31,6 +34,7 @@ public PowerUpWrapper(IElement element, AttributeDefinition targetAttribute, Att | |
| } | ||
|
|
||
| this._element = element; | ||
| this._aggregateType = aggregateType; | ||
| this._parentAttribute.AddElement(this); | ||
| this._element.ValueChanged += this.OnValueChanged; | ||
| } | ||
|
|
@@ -42,33 +46,36 @@ public PowerUpWrapper(IElement element, AttributeDefinition targetAttribute, Att | |
| public float Value => this._element.Value; | ||
|
|
||
| /// <inheritdoc/> | ||
| public AggregateType AggregateType => this._element.AggregateType; | ||
| public AggregateType AggregateType => this._aggregateType ?? this._element.AggregateType; | ||
|
|
||
| /// <summary> | ||
| /// Creates elements by a <see cref="PowerUpDefinition"/>. | ||
| /// </summary> | ||
| /// <param name="powerUpDef">The power up definition.</param> | ||
| /// <param name="attributeHolder">The attribute holder.</param> | ||
| /// <param name="aggregateType">The specific aggregate type. If not specified, the aggregate type of the <paramref name="powerUpDef"/>'s constant value will be used.</param> | ||
| /// <returns>The elements which represent the power-up.</returns> | ||
| public static IEnumerable<PowerUpWrapper> CreateByPowerUpDefinition(PowerUpDefinition powerUpDef, AttributeSystem attributeHolder) | ||
| public static IEnumerable<PowerUpWrapper> CreateByPowerUpDefinition(PowerUpDefinition powerUpDef, AttributeSystem attributeHolder, AggregateType? aggregateType = null) | ||
| { | ||
| if (powerUpDef.Boost?.ConstantValue != null) | ||
| { | ||
| yield return new PowerUpWrapper( | ||
| powerUpDef.Boost.ConstantValue, | ||
| powerUpDef.TargetAttribute ?? throw Error.NotInitializedProperty(powerUpDef, nameof(PowerUpDefinition.TargetAttribute)), | ||
| attributeHolder); | ||
| attributeHolder, | ||
| aggregateType); | ||
| } | ||
|
|
||
| if (powerUpDef.Boost?.RelatedValues != null) | ||
| { | ||
| foreach (var relationship in powerUpDef.Boost.RelatedValues) | ||
| { | ||
| var aggregateType = powerUpDef.Boost?.ConstantValue.AggregateType ?? AggregateType.AddRaw; | ||
| var aggregType = powerUpDef.Boost?.ConstantValue.AggregateType ?? AggregateType.AddRaw; | ||
| yield return new PowerUpWrapper( | ||
| attributeHolder.CreateRelatedAttribute(relationship, attributeHolder, aggregateType), | ||
| attributeHolder.CreateRelatedAttribute(relationship, attributeHolder, aggregType), | ||
| powerUpDef.TargetAttribute ?? throw Error.NotInitializedProperty(powerUpDef, nameof(PowerUpDefinition.TargetAttribute)), | ||
| attributeHolder); | ||
| attributeHolder, | ||
| aggregateType); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -88,7 +95,7 @@ public void Dispose() | |
| /// <inheritdoc/> | ||
| public override string? ToString() | ||
| { | ||
| return $"{this._parentAttribute?.Definition.Designation}: {this._element}"; | ||
| return $"{this._parentAttribute?.Definition.Designation}: {this._element}{(this._aggregateType is { } aggreg ? $"->({aggreg})" : string.Empty)}"; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So that one can see that this aggregate type has been overriden. |
||
| } | ||
|
|
||
| private void OnValueChanged(object? sender, EventArgs eventArgs) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -149,6 +149,18 @@ public static bool IsJewelry(this Item item) | |
| return item.ItemSlot >= InventoryConstants.PendantSlot && item.ItemSlot <= InventoryConstants.Ring2Slot; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Determines whether this item is an armor item. | ||
| /// </summary> | ||
| /// <param name="item">The item.</param> | ||
| /// <returns> | ||
| /// <c>true</c> if the specified item is armor; otherwise, <c>false</c>. | ||
| /// </returns> | ||
| public static bool IsArmorItem(this Item item) | ||
| { | ||
| return item.ItemSlot >= InventoryConstants.HelmSlot && item.ItemSlot <= InventoryConstants.BootsSlot; | ||
| } | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| /// <summary> | ||
| /// Determines whether this instance is a is weapon which deals physical damage. | ||
| /// </summary> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -273,7 +273,28 @@ private IEnumerable<PowerUpWrapper> GetPowerUpsOfItemOptions(Item item, Attribut | |
| continue; | ||
| } | ||
|
|
||
| foreach (var wrapper in PowerUpWrapper.CreateByPowerUpDefinition(powerUp, attributeHolder)) | ||
| AggregateType? aggregateType = null; | ||
| if (option.OptionType == ItemOptionTypes.Excellent) | ||
| { | ||
| if (item.ItemSlot == InventoryConstants.PendantSlot | ||
| && option.PowerUpDefinition?.TargetAttribute == Stats.PhysicalBaseDmg) | ||
| { | ||
| // Pendant options are not subject to double wield averaging | ||
| aggregateType = AggregateType.AddFinal; | ||
| } | ||
| else if (option.PowerUpDefinition?.TargetAttribute == Stats.PhysicalBaseDmgIncrease | ||
| && item.Definition!.BasePowerUpAttributes.Any(pu => pu.TargetAttribute == Stats.DoubleWieldWeaponCount)) | ||
| { | ||
| // This needs special treatment, since this option is averaged when double wielding | ||
| aggregateType = AggregateType.AddRaw; | ||
| } | ||
| else | ||
| { | ||
| // the normal aggregate type should be used | ||
| } | ||
|
Comment on lines
+277
to
+294
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
|
|
||
| foreach (var wrapper in PowerUpWrapper.CreateByPowerUpDefinition(powerUp, attributeHolder, aggregateType)) | ||
| { | ||
| yield return wrapper; | ||
| } | ||
|
|
@@ -344,6 +365,13 @@ private IEnumerable<PowerUpWrapper> CreateExcellentAndAncientBasePowerUpWrappers | |
| yield return new PowerUpWrapper(new SimpleElement(ancientBonus, AggregateType.AddRaw), minDmgAttribute, attributeHolder); | ||
| yield return new PowerUpWrapper(new SimpleElement(ancientBonus, AggregateType.AddRaw), maxDmgAttribute, attributeHolder); | ||
| } | ||
|
|
||
| if (itemIsExcellent | ||
| && item.ItemOptions.Any(io => io.ItemOption?.PowerUpDefinition?.TargetAttribute == Stats.PhysicalBaseDmgIncrease) | ||
| && item.Definition!.BasePowerUpAttributes.Any(pu => pu.TargetAttribute == Stats.DoubleWieldWeaponCount)) | ||
| { | ||
| yield return new PowerUpWrapper(new SimpleElement(-1, AggregateType.AddRaw), Stats.PhysicalBaseDmgIncrease, attributeHolder); | ||
| } | ||
| } | ||
|
|
||
| if (item.IsWizardryWeapon(out var staffRise) && item.ItemSlot == InventoryConstants.LeftHandSlot) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an impossible situation since in line 66 an enumerable with "1" is concatenated.