From 71665136812b2471378a3f9b8c7475afab11509e Mon Sep 17 00:00:00 2001 From: ze-dom Date: Thu, 16 Jul 2026 11:04:36 +0100 Subject: [PATCH] Fixed elf master skill s and added extra projectile attribute (cherry picked from commit 983db566e6ac315acdcda5d1ac35cdf12d49c8bf) --- src/GameLogic/AttackableExtensions.cs | 4 +-- .../Attributes/MonsterAttributeHolder.cs | 4 +-- src/GameLogic/Attributes/Stats.cs | 17 +++++++++-- src/GameLogic/Player.cs | 28 +++++-------------- .../Skills/AreaSkillAttackAction.cs | 6 ++-- src/GameLogic/SkillList.cs | 3 +- .../Skills/GreaterDamageEffectInitializer.cs | 12 ++++++-- .../Skills/GreaterDefenseEffectInitializer.cs | 12 ++++++-- .../VersionSeasonSix/Items/Weapons.cs | 5 ++++ .../VersionSeasonSix/SkillsInitializer.cs | 12 ++++---- 10 files changed, 61 insertions(+), 42 deletions(-) diff --git a/src/GameLogic/AttackableExtensions.cs b/src/GameLogic/AttackableExtensions.cs index c641dc9..3678a0b 100644 --- a/src/GameLogic/AttackableExtensions.cs +++ b/src/GameLogic/AttackableExtensions.cs @@ -91,7 +91,7 @@ public static class AttackableExtensions else { var defenseAttribute = defender.GetDefenseAttribute(attacker); - defense = (int)(defender.Attributes[defenseAttribute] * defender.Attributes[Stats.DefenseDecrement]); + defense = (int)((defender.Attributes[defenseAttribute] + defender.Attributes[Stats.GreaterDefenseBonus]) * defender.Attributes[Stats.DefenseDecrement]); if (defense < 0) { defense = 0; @@ -378,7 +378,7 @@ public static class AttackableExtensions if (regeneration != null) { var regenerationValue = player.Attributes.CreateElement(powerUpDefinition); - var value = skillEntry.Level == 0 ? regenerationValue.Value : regenerationValue.Value + skillEntry.CalculateValue(); + var value = regenerationValue.Value + (skillEntry.Level == 0 ? 0 : regenerationValue.Value * skillEntry.CalculateValue() / 100); target.Attributes[regeneration.CurrentAttribute] = Math.Min( target.Attributes[regeneration.CurrentAttribute] + value, target.Attributes[regeneration.MaximumAttribute]); diff --git a/src/GameLogic/Attributes/MonsterAttributeHolder.cs b/src/GameLogic/Attributes/MonsterAttributeHolder.cs index 84ee16e..352ec57 100644 --- a/src/GameLogic/Attributes/MonsterAttributeHolder.cs +++ b/src/GameLogic/Attributes/MonsterAttributeHolder.cs @@ -17,8 +17,8 @@ public class MonsterAttributeHolder : IAttributeSystem new Dictionary> { { Stats.CurrentHealth, m => m.Health }, - { Stats.DefensePvm, m => m.Attributes.GetValueOfAttribute(Stats.DefenseBase) + ((m as Monster)?.SummonedBy?.Attributes?[Stats.SummonedMonsterDefenseIncrease] ?? 0) }, - { Stats.DefensePvp, m => m.Attributes.GetValueOfAttribute(Stats.DefenseBase) + ((m as Monster)?.SummonedBy?.Attributes?[Stats.SummonedMonsterDefenseIncrease] ?? 0) }, + { Stats.DefensePvm, m => m.Attributes.GetValueOfAttribute(Stats.DefenseBase) * (1 + ((m as Monster)?.SummonedBy?.Attributes?[Stats.SummonedMonsterDefenseIncrease] ?? 0)) }, + { Stats.DefensePvp, m => m.Attributes.GetValueOfAttribute(Stats.DefenseBase) * (1 + ((m as Monster)?.SummonedBy?.Attributes?[Stats.SummonedMonsterDefenseIncrease] ?? 0)) }, { Stats.DamageReceiveDecrement, m => 1.0f }, { Stats.AttackDamageIncrease, m => 1.0f }, { Stats.MovementSpeedFactor, m => 1.0f }, diff --git a/src/GameLogic/Attributes/Stats.cs b/src/GameLogic/Attributes/Stats.cs index fd4825e..54dea3f 100644 --- a/src/GameLogic/Attributes/Stats.cs +++ b/src/GameLogic/Attributes/Stats.cs @@ -1,4 +1,4 @@ -// +// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // @@ -524,6 +524,12 @@ public class Stats /// public static AttributeDefinition CrossBowMasteryBonusDamage { get; } = new(new Guid("B3AF7F51-6D6B-42FB-B8FF-689D03890F3E"), "Cross Bow Mastery PvP Bonus Damage (MST)", string.Empty); + /// + /// Gets the extra projectiles attribute definition. + /// + /// Can be increased by equipping certain (cross)bows and/or unlocking triple shot mastery. + public static AttributeDefinition ExtraProjectiles { get; } = new(new Guid("B9E4F3C2-A1D5-4B8E-7F2C-6D3A9E1F5C8B"), "Extra Projectiles", "The number of extra projectiles shot with triple shot skill."); + /// /// Gets elf's melee attack mode attribute definition. /// @@ -554,6 +560,11 @@ public class Stats /// public static AttributeDefinition ArcheryMaxDmg { get; } = new(new Guid("EC807B7C-4004-4D13-BED2-326E13F8EFEB"), "Archery Maximum Damage", "The elf's maximum archery damage, which is added to projectile weapon attacks."); + /// + /// Gets the elf's greater defense buff bonus defense attribute definition. + /// + public static AttributeDefinition GreaterDefenseBonus { get; } = new(new Guid("5A7C3E9B-D1F4-4B82-8A6D-2F3E1C9B7A4D"), "Greater Defense Bonus", string.Empty); + /// /// Gets the elf's greater damage buff bonus damage attribute definition. /// @@ -729,7 +740,7 @@ public class Stats public static AttributeDefinition SummonedMonsterHealthIncrease { get; } = new(new Guid("7B0625C8-DA1A-4A5D-BCA5-26AACDA0BDC6"), "Summoned Monster Health Increase %", string.Empty); /// - /// Gets the summoned monster defense increase, absolute. + /// Gets the summoned monster defense increase, percentage. /// public static AttributeDefinition SummonedMonsterDefenseIncrease { get; } = new(new Guid("0D55CFCA-751F-4E66-B327-635576A9A0B3"), "Summoned Monster Defense Increase", string.Empty); @@ -775,7 +786,7 @@ public class Stats /// values include: /// . /// values include: - /// Greater defense buff; MST bonus defense with shield (shield strengthener); MST dark horse strengthener; Jack O'Lantern Cry bonus (halved); Berserker defense reduction. + /// MST bonus defense with shield (shield strengthener); MST dark horse strengthener; Jack O'Lantern Cry bonus (halved); Berserker defense reduction. /// public static AttributeDefinition DefenseFinal { get; } = new(new Guid("0888AD48-0CC8-47CA-B6A3-99F3771AA5FC"), "Final Defense", string.Empty); diff --git a/src/GameLogic/Player.cs b/src/GameLogic/Player.cs index 1012558..49d4808 100644 --- a/src/GameLogic/Player.cs +++ b/src/GameLogic/Player.cs @@ -1646,11 +1646,9 @@ public class Player : AsyncDisposable, IBucketMapObserver, IAttackable, IAttacke var durationExtended = false; foreach (var powerUpDef in powerUps) { - IElement powerUp; + IElement powerUp = this.Attributes!.CreateElement(powerUpDef); if (skillEntry.Level > 0) { - powerUp = this.Attributes!.CreateElement(powerUpDef); - foreach (var masterSkillEntry in GetMasterSkillEntries(skillEntry)) { var extendsDuration = masterSkillEntry.Skill?.MasterDefinition?.ExtendsDuration ?? false; @@ -1658,13 +1656,9 @@ public class Player : AsyncDisposable, IBucketMapObserver, IAttackable, IAttacke { durationElement = new CombinedElement(durationElement, new ConstantElement(masterSkillEntry.CalculateValue())); } - else if (extendsDuration) + + if (masterSkillEntry.Skill?.MasterDefinition?.TargetAttribute is not null) { - continue; - } - else - { - // Apply either for all, or just for the specified TargetAttribute of the master skill powerUp = AppedMasterSkillPowerUp(masterSkillEntry, powerUpDef, powerUp); } } @@ -1672,10 +1666,6 @@ public class Player : AsyncDisposable, IBucketMapObserver, IAttackable, IAttacke // After the first iteration all possible duration extensions have been applied durationExtended = true; } - else - { - powerUp = this.Attributes!.CreateElement(powerUpDef); - } result[i] = (powerUpDef.TargetAttribute!, powerUp); i++; @@ -1694,15 +1684,12 @@ public class Player : AsyncDisposable, IBucketMapObserver, IAttackable, IAttacke IElement AppedMasterSkillPowerUp(SkillEntry masterSkillEntry, PowerUpDefinition powerUpDef, IElement powerUp) { - if (masterSkillEntry.Skill?.MasterDefinition is not { } masterSkillDefinition) - { - return powerUp; - } + var masterSkillDefinition = masterSkillEntry.Skill!.MasterDefinition!; - if (masterSkillDefinition.TargetAttribute is { } masterSkillTargetAttribute - && masterSkillTargetAttribute == powerUpDef.TargetAttribute) + if (masterSkillDefinition.TargetAttribute == powerUpDef.TargetAttribute + && masterSkillDefinition.Aggregation == powerUp.AggregateType) { - var additionalValue = new SimpleElement(masterSkillEntry.CalculateValue(), masterSkillEntry.Skill.MasterDefinition?.Aggregation ?? powerUp.AggregateType); + var additionalValue = new SimpleElement(masterSkillEntry.CalculateValue(), masterSkillDefinition.Aggregation); powerUp = new CombinedElement(powerUp, additionalValue); } @@ -1770,7 +1757,6 @@ public class Player : AsyncDisposable, IBucketMapObserver, IAttackable, IAttacke area.MaximumHealthOverride = (int)monster.Attributes[Stats.MaximumHealth]; area.MaximumHealthOverride += (int)(monster.Attributes[Stats.MaximumHealth] * this.Attributes?[Stats.SummonedMonsterHealthIncrease] ?? 0); - // todo: Stats.SummonedMonsterDefenseIncrease this.Summon = (monster, intelligence); monster.Initialize(); await gameMap.AddAsync(monster).ConfigureAwait(false); diff --git a/src/GameLogic/PlayerActions/Skills/AreaSkillAttackAction.cs b/src/GameLogic/PlayerActions/Skills/AreaSkillAttackAction.cs index 7d9ac46..37415aa 100644 --- a/src/GameLogic/PlayerActions/Skills/AreaSkillAttackAction.cs +++ b/src/GameLogic/PlayerActions/Skills/AreaSkillAttackAction.cs @@ -237,7 +237,6 @@ public class AreaSkillAttackAction var minAttacks = areaSkillSettings.MinimumNumberOfHitsPerAttack == 0 ? maxAttacks : areaSkillSettings.MinimumNumberOfHitsPerAttack; var currentDelay = TimeSpan.Zero; - // Order targets by distance to process nearest targets first var orderedTargets = targets.ToList(); FrustumBasedTargetFilter? filter = null; var projectileCount = 1; @@ -245,9 +244,10 @@ public class AreaSkillAttackAction if (areaSkillSettings is { UseFrustumFilter: true, ProjectileCount: > 1 }) { + // Order targets by distance to process nearest targets first orderedTargets.Sort((a, b) => player.GetDistanceTo(a).CompareTo(player.GetDistanceTo(b))); filter = FrustumFilters.GetOrAdd(areaSkillSettings, static s => new FrustumBasedTargetFilter(s.FrustumStartWidth, s.FrustumEndWidth, s.FrustumDistance, s.ProjectileCount)); - projectileCount = areaSkillSettings.ProjectileCount; + projectileCount = areaSkillSettings.ProjectileCount + (int)(player.Attributes?[Stats.ExtraProjectiles] ?? 0); attackRounds = 1; // One attack round per projectile extraTarget = orderedTargets.FirstOrDefault(t => t.Id == extraTargetId); @@ -256,7 +256,7 @@ public class AreaSkillAttackAction // In this case we just calculate the angle on server side, so that lags // or desynced positions may not have such a big impact var angle = (float)player.Position.GetAngleDegreeTo(extraTarget.Position); - rotation = (byte)((angle / 360.0f) * 256.0f); + rotation = (byte)(angle / 360.0f * 256.0f); } } diff --git a/src/GameLogic/SkillList.cs b/src/GameLogic/SkillList.cs index 8a6a44d..225f7ee 100644 --- a/src/GameLogic/SkillList.cs +++ b/src/GameLogic/SkillList.cs @@ -19,8 +19,9 @@ public sealed class SkillList : ISkillList, IDisposable private const ushort DurabilityReduction1FistMasterSkillId = 578; private const short TwistingSlashMasterySkillId = 332; private const short RagefulBlowMasterySkillId = 333; + private const short TripleShotMasterySkillId = 418; - private readonly short[] _castedSkillsWithPassiveBoost = [TwistingSlashMasterySkillId, RagefulBlowMasterySkillId]; + private readonly short[] _castedSkillsWithPassiveBoost = [TwistingSlashMasterySkillId, RagefulBlowMasterySkillId, TripleShotMasterySkillId]; private readonly IDictionary _availableSkills; diff --git a/src/Persistence/Initialization/Skills/GreaterDamageEffectInitializer.cs b/src/Persistence/Initialization/Skills/GreaterDamageEffectInitializer.cs index f864cfc..ee2de11 100644 --- a/src/Persistence/Initialization/Skills/GreaterDamageEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/GreaterDamageEffectInitializer.cs @@ -36,11 +36,11 @@ public class GreaterDamageEffectInitializer : InitializerBase magicEffect.StopByDeath = true; magicEffect.Duration = this.Context.CreateNew(); magicEffect.Duration.ConstantValue.Value = 60; // 60 Seconds + + // The buff gives 3 + (energy / 7) damage var powerUpDefinition = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(powerUpDefinition); powerUpDefinition.TargetAttribute = Stats.GreaterDamageBonus.GetPersistent(this.GameConfiguration); - - // The buff gives 3 + (energy / 7) damage powerUpDefinition.Boost = this.Context.CreateNew(); powerUpDefinition.Boost.ConstantValue.Value = 3f; powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.AddRaw; @@ -50,5 +50,13 @@ public class GreaterDamageEffectInitializer : InitializerBase boostPerEnergy.InputOperator = InputOperator.Multiply; boostPerEnergy.InputOperand = 1f / 7f; // one damage per 7 energy powerUpDefinition.Boost.RelatedValues.Add(boostPerEnergy); + + // Placeholder for AttackIncreaseStr and AttackIncreaseMastery master skills + var powerUpDefinition2 = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(powerUpDefinition2); + powerUpDefinition2.TargetAttribute = Stats.GreaterDamageBonus.GetPersistent(this.GameConfiguration); + powerUpDefinition2.Boost = this.Context.CreateNew(); + powerUpDefinition2.Boost.ConstantValue.Value = 1f; + powerUpDefinition2.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/Skills/GreaterDefenseEffectInitializer.cs b/src/Persistence/Initialization/Skills/GreaterDefenseEffectInitializer.cs index 903b742..c486163 100644 --- a/src/Persistence/Initialization/Skills/GreaterDefenseEffectInitializer.cs +++ b/src/Persistence/Initialization/Skills/GreaterDefenseEffectInitializer.cs @@ -40,15 +40,23 @@ public class GreaterDefenseEffectInitializer : InitializerBase // The buff gives 2 + (energy / 8) defense var powerUpDefinition = this.Context.CreateNew(); magicEffect.PowerUpDefinitions.Add(powerUpDefinition); - powerUpDefinition.TargetAttribute = Stats.DefenseFinal.GetPersistent(this.GameConfiguration); + powerUpDefinition.TargetAttribute = Stats.GreaterDefenseBonus.GetPersistent(this.GameConfiguration); powerUpDefinition.Boost = this.Context.CreateNew(); powerUpDefinition.Boost.ConstantValue.Value = 2f; - powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.AddFinal; + powerUpDefinition.Boost.ConstantValue.AggregateType = AggregateType.AddRaw; var boostPerEnergy = this.Context.CreateNew(); boostPerEnergy.InputAttribute = Stats.TotalEnergy.GetPersistent(this.GameConfiguration); boostPerEnergy.InputOperator = InputOperator.Multiply; boostPerEnergy.InputOperand = 1f / 8f; // one defense per 8 energy powerUpDefinition.Boost.RelatedValues.Add(boostPerEnergy); + + // Placeholder for DefenseIncreaseStr and DefenseIncreaseMastery master skills + var powerUpDefinition2 = this.Context.CreateNew(); + magicEffect.PowerUpDefinitions.Add(powerUpDefinition2); + powerUpDefinition2.TargetAttribute = Stats.GreaterDefenseBonus.GetPersistent(this.GameConfiguration); + powerUpDefinition2.Boost = this.Context.CreateNew(); + powerUpDefinition2.Boost.ConstantValue.Value = 1f; + powerUpDefinition2.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; } } \ No newline at end of file diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs index a02d718..4827a5e 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs @@ -460,6 +460,11 @@ internal class Weapons : InitializerBase { item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.AmmunitionConsumptionRate, 1, AggregateType.AddRaw)); item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(slot == 0 ? Stats.IsCrossBowEquipped : Stats.IsBowEquipped, 1, AggregateType.AddRaw)); + + if (number == 18 || number == 19 || number == 22 || number == 23 || number == 24) // Divine Crossbow of Archangel, Great Reign Crossbow, Albatross Bow, Stinger Bow, Air Lyn Bow + { + item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.ExtraProjectiles, 1, AggregateType.AddRaw)); + } } if (group < (int)ItemGroups.Bows && width == 2) diff --git a/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs b/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs index 029d952..53a5790 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/SkillsInitializer.cs @@ -818,7 +818,7 @@ internal class SkillsInitializer : SkillsInitializerBase this.AddPassiveMasterSkillDefinition(SkillNumber.TwoHandedStaffMaster, Stats.TwoHandedStaffMasteryBonusDamage, AggregateType.AddRaw, Formula1154, 3, 3, SkillNumber.TwoHandedStaffStrengthener); this.AddPassiveMasterSkillDefinition(SkillNumber.ShieldMasteryGrandMaster, Stats.BonusDefenseRateWithShield, AggregateType.AddRaw, Formula1204, 3, 3, SkillNumber.ShieldStrengthenerGrandMaster); this.AddMasterSkillDefinition(SkillNumber.SoulBarrierStrength, SkillNumber.SoulBarrier, SkillNumber.Undefined, 3, 4, SkillNumber.SoulBarrier, 20, $"{Formula181} / 100", Formula181, Stats.SoulBarrierReceiveDecrement, AggregateType.AddRaw); - this.AddMasterSkillDefinition(SkillNumber.SoulBarrierProficie, SkillNumber.SoulBarrierStrength, SkillNumber.Undefined, 3, 5, SkillNumber.SoulBarrierStrength, 20, Formula803, extendsDuration: true); + this.AddMasterSkillDefinition(SkillNumber.SoulBarrierProficie, SkillNumber.SoulBarrierStrength, SkillNumber.Undefined, 3, 5, SkillNumber.SoulBarrierStrength, 20, Formula803, true); this.AddPassiveMasterSkillDefinition(SkillNumber.MinimumWizardryInc, Stats.MinimumWizBaseDmg, AggregateType.AddRaw, Formula502, 5, 3); // ELF @@ -826,13 +826,13 @@ internal class SkillsInitializer : SkillsInitializerBase this.AddMasterSkillDefinition(SkillNumber.TripleShotStrengthener, SkillNumber.TripleShot, SkillNumber.Undefined, 2, 2, SkillNumber.TripleShot, 20, Formula502); this.AddPassiveMasterSkillDefinition(SkillNumber.SummonedMonsterStr1, Stats.SummonedMonsterHealthIncrease, AggregateType.AddRaw, Formula6020Value, 2, 2, SkillNumber.SummonGoblin); this.AddMasterSkillDefinition(SkillNumber.PenetrationStrengthener, SkillNumber.Penetration, SkillNumber.Undefined, 2, 3, SkillNumber.Penetration, 20, Formula502); - this.AddMasterSkillDefinition(SkillNumber.DefenseIncreaseStr, SkillNumber.GreaterDefense, SkillNumber.Undefined, 2, 3, SkillNumber.GreaterDefense, 20, Formula502); - this.AddMasterSkillDefinition(SkillNumber.TripleShotMastery, SkillNumber.TripleShotStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.TripleShot, 10, Formula1WhenComplete); + this.AddMasterSkillDefinition(SkillNumber.DefenseIncreaseStr, SkillNumber.GreaterDefense, SkillNumber.Undefined, 2, 3, SkillNumber.GreaterDefense, 20, Formula502, Formula502, Stats.GreaterDefenseBonus, AggregateType.Multiplicate); + this.AddMasterSkillDefinition(SkillNumber.TripleShotMastery, SkillNumber.TripleShotStrengthener, SkillNumber.Undefined, 2, 3, SkillNumber.TripleShotStrengthener, 10, Formula1WhenComplete, Formula1WhenComplete, Stats.ExtraProjectiles, AggregateType.AddRaw); this.AddPassiveMasterSkillDefinition(SkillNumber.SummonedMonsterStr2, Stats.SummonedMonsterDefenseIncrease, AggregateType.AddRaw, Formula6020, 2, 3, SkillNumber.SummonGoblin); - this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseStr, SkillNumber.GreaterDamage, SkillNumber.Undefined, 2, 4, SkillNumber.GreaterDamage, 20, Formula502); + this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseStr, SkillNumber.GreaterDamage, SkillNumber.Undefined, 2, 4, SkillNumber.GreaterDamage, 20, Formula502, Formula502, Stats.GreaterDamageBonus, AggregateType.Multiplicate); this.AddPassiveMasterSkillDefinition(SkillNumber.WeaponMasteryHighElf, Stats.MasterSkillPhysBonusDmg, AggregateType.AddRaw, Formula502, 4, 2); - this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseMastery, SkillNumber.AttackIncreaseStr, SkillNumber.Undefined, 2, 5, SkillNumber.GreaterDamage, 20, Formula502); - this.AddMasterSkillDefinition(SkillNumber.DefenseIncreaseMastery, SkillNumber.DefenseIncreaseStr, SkillNumber.Undefined, 2, 5, SkillNumber.GreaterDefense, 20, Formula502); + this.AddMasterSkillDefinition(SkillNumber.AttackIncreaseMastery, SkillNumber.AttackIncreaseStr, SkillNumber.Undefined, 2, 5, SkillNumber.AttackIncreaseStr, 20, Formula502, Formula502, Stats.GreaterDamageBonus, AggregateType.Multiplicate, true); + this.AddMasterSkillDefinition(SkillNumber.DefenseIncreaseMastery, SkillNumber.DefenseIncreaseStr, SkillNumber.Undefined, 2, 5, SkillNumber.DefenseIncreaseStr, 20, Formula502, Formula502, Stats.GreaterDefenseBonus, AggregateType.Multiplicate, true); this.AddMasterSkillDefinition(SkillNumber.IceArrowStrengthener, SkillNumber.IceArrow, SkillNumber.Undefined, 2, 5, SkillNumber.IceArrow, 20, Formula502); this.AddPassiveMasterSkillDefinition(SkillNumber.BowStrengthener, Stats.BowStrBonusDamage, AggregateType.AddRaw, Formula502, 2, 3); this.AddPassiveMasterSkillDefinition(SkillNumber.CrossbowStrengthener, Stats.CrossBowStrBonusDamage, AggregateType.AddRaw, Formula632, 2, 3);