-
Notifications
You must be signed in to change notification settings - Fork 509
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
894924f
c951f2c
f8c0142
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
Member
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. It's just theoretical, but it's used just in one special code path. So, just retrieve it locally. |
||
|
|
||
| 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 |
|---|---|---|
|
|
@@ -243,6 +243,14 @@ public class Stats | |
| /// <summary> | ||
| /// Gets the min and max physical base DMG attribute definition. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// <see cref="AggregateType.AddRaw"/> values include: | ||
| /// Weapon item option; excellent lvl/20 option (weapons) | ||
| /// <see cref="AggregateType.Multiplicate"/> values include: | ||
| /// Double wield halving (averaging). | ||
| /// <see cref="AggregateType.AddFinal"/> values include: | ||
| /// Excellent lvl/20 option (pendant); wings damage option; harmony damage (min and max) option; gold fenrir damage bonus; <see cref="BaseDamageBonus"/>. | ||
| /// </remarks> | ||
| public static AttributeDefinition PhysicalBaseDmg { get; } = new(new Guid("DD1E13E4-BFFD-45B5-9B91-9080710324B2"), "Physical Base Damage (min and max)", string.Empty); | ||
|
|
||
| /// <summary> | ||
|
|
@@ -421,7 +429,12 @@ public class Stats | |
| /// <summary> | ||
| /// Gets the physical base (min and max) damage increase attribute definition>. | ||
| /// </summary> | ||
| /// <remarks>Includes excellent 2% physical increase option, ammunition damage increase, and the double wield multiplier (55%).</remarks> | ||
| /// <remarks> | ||
| /// <see cref="AggregateType.AddRaw"/> values include: | ||
| /// Excellent 2% increase option (double wield weapons); ammunition damage increase. | ||
| /// <see cref="AggregateType.Multiplicate"/> values include: | ||
| /// Double wield halving (averaging); double wield bonus multiplier (55%); excellent 2% increase option (pendant and other weapons). | ||
| /// </remarks> | ||
| public static AttributeDefinition PhysicalBaseDmgIncrease { get; } = new(new Guid("104B4DAA-C507-4CBB-AF38-D53DDBB4817E"), "Physical Base Damage Increase", string.Empty); | ||
|
|
||
| /// <summary> | ||
|
|
@@ -1130,14 +1143,51 @@ public class Stats | |
| public static AttributeDefinition DoubleDamageChance { get; } = new(new Guid("2B8A03E6-1CC2-48A0-8633-3F36E17050F4"), "Double Damage Chance", string.Empty); | ||
|
|
||
| /// <summary> | ||
| /// Gets the stun chance attribute definition. | ||
| /// Gets the MST stun chance attribute definition. | ||
| /// </summary> | ||
| /// <remarks>Bucket attribute for the master skills: wind tome (book of neil) mastery, fire burst mastery, earthshake mastery and mace mastery.</remarks> | ||
| public static AttributeDefinition MasteryStunChance { get; } = new(new Guid("610D3259-1158-424A-8738-9EB7A71DE600"), "Mastery Stun Chance (MST)", "A generic master tree stun chance attribute, which serves as a bucket for \"mastery\" skills."); | ||
|
|
||
| /// <summary> | ||
| /// Gets the MST mace mastery stun chance attribute definition. | ||
| /// </summary> | ||
| public static AttributeDefinition MaceMasteryStunChance { get; } = new(new Guid("6E3A9F2D-5B7C-4D8E-A1F3-2C9E5B7D4F6A"), "Mace Mastery Stun Chance (MST)", string.Empty); | ||
|
|
||
| /// <summary> | ||
| /// Gets the MST target move chance attribute definition. | ||
| /// </summary> | ||
| /// <remarks>Bucket attribute for the master skills: lightning tome (book of lagle) mastery and twisting slash mastery.</remarks> | ||
| public static AttributeDefinition MasteryMoveTargetChance { get; } = new(new Guid("6F9619FF-8B86-D011-B42D-00C04FC964FF"), "Mastery Move Target Chance (MST)", "A generic master tree move target chance attribute, which serves as a bucket for \"mastery\" skills."); | ||
|
|
||
| /// <summary> | ||
| /// Gets the rageful blow mastery decrease durability MST chance attribute definition. | ||
| /// </summary> | ||
| public static AttributeDefinition RagefulBlowMasteryDurabilityDecChance { get; } = new(new Guid("2F8A5D3B-9C7E-4F1A-B6D2-8E3C5A7F9B1D"), "Rageful Blow Mastery Durability Decrease Chance (MST)", string.Empty); | ||
|
|
||
| /// <summary> | ||
| /// Gets the durability reduction factor attribute definition. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Factor by which the maximum durability of armor items is multiplied when attacked by Rageful Blow and <see cref="RagefulBlowMasteryDurabilityDecChance"/> is successful. | ||
| /// Decreases with the level of the master skills DurabilityReduction1 or DurabilityReduction1FistMaster. | ||
| /// Value ranges from 10% (default) to 6%. | ||
| /// </remarks> | ||
| public static AttributeDefinition DurabilityReductionFactor { get; } = new(new Guid("3C9E7F2A-B1D4-8E6F-5A0C-1D8F3B5E7A2D"), "Durability Reduction Factor", string.Empty); | ||
|
|
||
| /// <summary> | ||
| /// Gets the spear mastery double damage MST chance attribute definition. | ||
| /// </summary> | ||
| public static AttributeDefinition SpearMasteryDoubleDamageChance { get; } = new(new Guid("5D9E2A7B-3C4F-8E1A-B5D6-2E7F9C4A1B8D"), "Spear Mastery Double Damage Chance (MST)", string.Empty); | ||
|
|
||
| /// <summary> | ||
| /// Gets the swell life skill health increase attribute definition. | ||
| /// </summary> | ||
| public static AttributeDefinition StunChance { get; } = new(new Guid("610D3259-1158-424A-8738-9EB7A71DE600"), "Stun Chance", string.Empty); | ||
|
Member
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. Why was
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. |
||
| public static AttributeDefinition SwellLifeHealthIncrease { get; } = new(new Guid("9C4E7B2A-F1D6-4A3E-B8C5-1D7F2E9A3B4C"), "Swell Life Health Increase", string.Empty); | ||
|
|
||
| /// <summary> | ||
| /// Gets the pollution skill MST target move chance, which rises with lightning tome mastery. | ||
| /// Gets the swell life skill mana increase attribute definition. | ||
| /// </summary> | ||
| public static AttributeDefinition PollutionMoveTargetChance { get; } = new(new Guid("6F9619FF-8B86-D011-B42D-00C04FC964FF"), "Pollution Move Target Chance (MST)", "The pollution skill (book of lagle) move chance, which rises with lightning tome mastery."); | ||
| public static AttributeDefinition SwellLifeManaIncrease { get; } = new(new Guid("8B4F1C6D-9A2E-4F7B-A3D5-1E9C7F2A4B6D"), "Swell Life Mana Increase", string.Empty); | ||
|
|
||
| /// <summary> | ||
| /// Gets the mana after monster kill attribute definition. | ||
|
|
||
| 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.