diff --git a/src/GameLogic/Attributes/Stats.cs b/src/GameLogic/Attributes/Stats.cs index 8ac681bcb..125fde185 100644 --- a/src/GameLogic/Attributes/Stats.cs +++ b/src/GameLogic/Attributes/Stats.cs @@ -231,6 +231,11 @@ public class Stats /// public static AttributeDefinition ScepterRise { get; } = new(new Guid("FB374862-D360-4FF0-AB88-2C170E6A9F85"), "Scepter Rise Percentage", string.Empty); + /// + /// Gets the book rise percentage attribute definition. + /// + public static AttributeDefinition BookRise { get; } = new(new Guid("AD9C9AE0-BA76-4C99-9F53-AE8F1AF6CAD4"), "Book Rise Percentage", string.Empty); + /// /// Gets the minimum curse base DMG attribute definition. /// diff --git a/src/GameLogic/ItemExtensions.cs b/src/GameLogic/ItemExtensions.cs index 1ba9616ad..34849077e 100644 --- a/src/GameLogic/ItemExtensions.cs +++ b/src/GameLogic/ItemExtensions.cs @@ -146,17 +146,17 @@ public static bool IsJewelry(this Item item) /// public static bool IsPhysicalWeapon(this Item item, [NotNullWhen(true)] out float? minimumDmg) { - minimumDmg = item.Definition?.BasePowerUpAttributes.FirstOrDefault(a => a.TargetAttribute == Stats.MinimumPhysBaseDmg)?.BaseValue; + minimumDmg = item.Definition?.BasePowerUpAttributes.FirstOrDefault(a => a.TargetAttribute == Stats.MinimumPhysBaseDmgByWeapon)?.BaseValue; return minimumDmg is not null; } /// - /// Determines whether this instance is a weapon which deals wizardry damage. + /// Determines whether this instance is a weapon which increases wizardry damage. /// /// The item. - /// The staff rise percentage of the weapon. + /// The staff/stick's wizardry damage rise percentage. /// - /// true if this instance is a weapon which deals wizardry damage; otherwise, false. + /// true if this instance is a weapon which increases wizardry damage; otherwise, false. /// public static bool IsWizardryWeapon(this Item item, [NotNullWhen(true)] out float? staffRise) { @@ -168,14 +168,28 @@ public static bool IsWizardryWeapon(this Item item, [NotNullWhen(true)] out floa /// Determines whether this instance is a scepter which increases raven damage. /// /// The item. - /// The stick rise percentage of the weapon. + /// The scepter's pet attack rise percentage. /// /// true if this instance is a scepter which increases raven damage; otherwise, false. /// - public static bool IsScepter(this Item item, [NotNullWhen(true)] out float? stickRise) + public static bool IsScepter(this Item item, [NotNullWhen(true)] out float? scepterRise) { - stickRise = item.Definition?.BasePowerUpAttributes.FirstOrDefault(a => a.TargetAttribute == Stats.ScepterRise)?.BaseValue; - return stickRise is not null; + scepterRise = item.Definition?.BasePowerUpAttributes.FirstOrDefault(a => a.TargetAttribute == Stats.ScepterRise)?.BaseValue; + return scepterRise is not null; + } + + /// + /// Determines whether this instance is a book which increases curse damage. + /// + /// The item. + /// The book's curse damage rise percentage. + /// + /// true if this instance is a book which increases curse damage; otherwise, false. + /// + public static bool IsBook(this Item item, [NotNullWhen(true)] out float? bookRise) + { + bookRise = item.Definition?.BasePowerUpAttributes.FirstOrDefault(a => a.TargetAttribute == Stats.BookRise)?.BaseValue; + return bookRise is not null; } /// diff --git a/src/GameLogic/ItemPowerUpFactory.cs b/src/GameLogic/ItemPowerUpFactory.cs index 7aceea01b..227328b09 100644 --- a/src/GameLogic/ItemPowerUpFactory.cs +++ b/src/GameLogic/ItemPowerUpFactory.cs @@ -272,10 +272,9 @@ private IEnumerable CreateExcellentAndAncientBasePowerUpWrappers var baseDefense = (int)(item.Definition?.BasePowerUpAttributes.FirstOrDefault(a => a.TargetAttribute == Stats.DefenseBase)?.BaseValue ?? 0); var additionalDefense = (baseDefense * 12 / baseDropLevel) + (baseDropLevel / 5) + 4; yield return new PowerUpWrapper(new SimpleElement(additionalDefense, AggregateType.AddRaw), Stats.DefenseBase, attributeHolder); - if (itemIsAncient) { - var ancientDefenseBonus = (baseDefense * 3 / ancientDropLevel) + (ancientDropLevel / 30) + 2; + var ancientDefenseBonus = 2 + ((baseDefense + additionalDefense) * 3 / ancientDropLevel) + (ancientDropLevel / 30); yield return new PowerUpWrapper(new SimpleElement(ancientDefenseBonus, AggregateType.AddRaw), Stats.DefenseBase, attributeHolder); } } @@ -288,7 +287,7 @@ private IEnumerable CreateExcellentAndAncientBasePowerUpWrappers if (itemIsAncient) { var baseDefense = (int)(item.Definition?.BasePowerUpAttributes.FirstOrDefault(a => a.TargetAttribute == Stats.DefenseBase)?.BaseValue ?? 0); - var ancientDefenseBonus = (baseDefense * 20 / ancientDropLevel) + 2; + var ancientDefenseBonus = 2 + ((baseDefense + item.Level) * 20 / ancientDropLevel); yield return new PowerUpWrapper(new SimpleElement(ancientDefenseBonus, AggregateType.AddRaw), Stats.DefenseBase, attributeHolder); } } @@ -308,25 +307,36 @@ private IEnumerable CreateExcellentAndAncientBasePowerUpWrappers if (item.IsWizardryWeapon(out var staffRise)) { - var additionalRise = ((int)staffRise * 25 / baseDropLevel) + 5; + var additionalRise = (((int)staffRise * 2 * 25 / baseDropLevel) + 5) / 2; yield return new PowerUpWrapper(new SimpleElement(additionalRise, AggregateType.AddRaw), Stats.StaffRise, attributeHolder); if (itemIsAncient) { - var ancientRiseBonus = 5 + (ancientDropLevel / 60); + var ancientRiseBonus = (2 + (ancientDropLevel / 60)) / 2; yield return new PowerUpWrapper(new SimpleElement(ancientRiseBonus, AggregateType.AddRaw), Stats.StaffRise, attributeHolder); } } if (item.IsScepter(out var scepterRise)) { - var additionalRise = ((int)scepterRise * 25 / baseDropLevel) + 5; + var additionalRise = (((int)scepterRise * 2 * 25 / baseDropLevel) + 5) / 2; yield return new PowerUpWrapper(new SimpleElement(additionalRise, AggregateType.AddRaw), Stats.ScepterRise, attributeHolder); if (itemIsAncient) { - var ancientRiseBonus = 5 + (ancientDropLevel / 60); + var ancientRiseBonus = (2 + (ancientDropLevel / 60)) / 2; yield return new PowerUpWrapper(new SimpleElement(ancientRiseBonus, AggregateType.AddRaw), Stats.ScepterRise, attributeHolder); } } + + if (item.IsBook(out var curseRise)) + { + var additionalRise = (((int)curseRise * 2 * 25 / baseDropLevel) + 5) / 2; + yield return new PowerUpWrapper(new SimpleElement(additionalRise, AggregateType.AddRaw), Stats.BookRise, attributeHolder); + if (itemIsAncient) + { + var ancientRiseBonus = (2 + (ancientDropLevel / 60)) / 2; + yield return new PowerUpWrapper(new SimpleElement(ancientRiseBonus, AggregateType.AddRaw), Stats.BookRise, attributeHolder); + } + } } private PowerUpWrapper? GetPetLevel(Item item, AttributeSystem attributeHolder) diff --git a/src/GameLogic/PlayerActions/ItemConsumeActions/ItemUpgradeConsumeHandlerPlugIn.cs b/src/GameLogic/PlayerActions/ItemConsumeActions/ItemUpgradeConsumeHandlerPlugIn.cs index 52bbe76c8..316e34ba6 100644 --- a/src/GameLogic/PlayerActions/ItemConsumeActions/ItemUpgradeConsumeHandlerPlugIn.cs +++ b/src/GameLogic/PlayerActions/ItemConsumeActions/ItemUpgradeConsumeHandlerPlugIn.cs @@ -166,7 +166,7 @@ private bool TryAddItemOption(Item item, IContext persistenceContext) else { // ItemOptionTypes.Option - optionLink.ItemOption = possibleOptions.First(); + optionLink.ItemOption = possibleOptions.SelectRandom(); optionLink.Level = 1; } diff --git a/src/Persistence/Initialization/CharacterClasses/ClassSummoner.cs b/src/Persistence/Initialization/CharacterClasses/ClassSummoner.cs index edd00f973..d6e5de428 100644 --- a/src/Persistence/Initialization/CharacterClasses/ClassSummoner.cs +++ b/src/Persistence/Initialization/CharacterClasses/ClassSummoner.cs @@ -98,6 +98,7 @@ private CharacterClass CreateSummoner(CharacterClassNumber number, string name, result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MinimumCurseBaseDmg, 1.0f / 9, Stats.TotalEnergy)); result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.MaximumCurseBaseDmg, 1.0f / 4, Stats.TotalEnergy)); + result.AttributeCombinations.Add(this.CreateAttributeRelationship(Stats.CurseAttackDamageIncrease, 1.0f / 100, Stats.BookRise)); result.AttributeCombinations.Add(this.CreateConditionalRelationship(Stats.WizardryBaseDmg, Stats.IsStickEquipped, Stats.StickBonusBaseDamage)); diff --git a/src/Persistence/Initialization/Items/ExcellentOptions.cs b/src/Persistence/Initialization/Items/ExcellentOptions.cs index dc49c1252..61b9269fd 100644 --- a/src/Persistence/Initialization/Items/ExcellentOptions.cs +++ b/src/Persistence/Initialization/Items/ExcellentOptions.cs @@ -51,9 +51,12 @@ public override void Initialize() this.CreateDefenseOptions(); this.CreatePhysicalAttackOptions(); this.CreateWizardryAttackOptions(); - this.CreateCurseAttackOptions(); + + // this.CreateCurseAttackOptions(); } + [Obsolete(@"There are no curse attack excellent options until Season 14 (Summoner renewal). Until then, excellent curse spell books had excellent wizardry attack options. + Reference: https://muonline.webzen.com/pt/gameinfo/guide/detail/91")] private void CreateCurseAttackOptions() { var definition = this.Context.CreateNew(); diff --git a/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugIn075.cs b/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugIn075.cs new file mode 100644 index 000000000..109072901 --- /dev/null +++ b/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugIn075.cs @@ -0,0 +1,22 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.Updates; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.PlugIns; + +/// +/// This update fixes weapons (staff) rise percentage. +/// +[PlugIn(PlugInName, PlugInDescription)] +[Guid("5B63534D-E5DF-46B1-992D-C1637B197EE1")] +public class FixWeaponRisePercentagePlugIn075 : FixWeaponRisePercentagePlugInBase +{ + /// + public override string DataInitializationKey => Version075.DataInitialization.Id; + + /// + public override UpdateVersion Version => UpdateVersion.FixWeaponRisePercentage075; +} \ No newline at end of file diff --git a/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugIn095d.cs b/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugIn095d.cs new file mode 100644 index 000000000..8a1aefe36 --- /dev/null +++ b/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugIn095d.cs @@ -0,0 +1,22 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.Updates; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.PlugIns; + +/// +/// This update fixes weapons (staff) rise percentage. +/// +[PlugIn(PlugInName, PlugInDescription)] +[Guid("33259706-F3DF-4F4D-9935-3DEF7E53BF81")] +public class FixWeaponRisePercentagePlugIn095D : FixWeaponRisePercentagePlugInBase +{ + /// + public override string DataInitializationKey => Version095d.DataInitialization.Id; + + /// + public override UpdateVersion Version => UpdateVersion.FixWeaponRisePercentage095d; +} \ No newline at end of file diff --git a/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugInBase.cs b/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugInBase.cs new file mode 100644 index 000000000..b3ea5a355 --- /dev/null +++ b/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugInBase.cs @@ -0,0 +1,82 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.Updates; + +using MUnique.OpenMU.DataModel.Configuration; +using MUnique.OpenMU.DataModel.Configuration.Items; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.Persistence.Initialization.Items; + +/// +/// This update fixes weapons (staff) rise percentage. +/// +public abstract class FixWeaponRisePercentagePlugInBase : UpdatePlugInBase +{ + /// + /// The plug in name. + /// + internal const string PlugInName = "Fix Weapon Rise Percentage"; + + /// + /// The plug in description. + /// + internal const string PlugInDescription = "This update fixes weapons (staff) rise percentage"; + + /// + public override string Name => PlugInName; + + /// + public override string Description => PlugInDescription; + + /// + public override bool IsMandatory => true; + + /// + public override DateTime CreatedAt => new(2024, 11, 11, 16, 0, 0, DateTimeKind.Utc); + + /// + protected override async ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration) + { + var staffRiseBonusTable = gameConfiguration.ItemLevelBonusTables.Single(bt => bt.Name == "Staff Rise"); + + // Modify existing table name and description + staffRiseBonusTable.Name = "Staff Rise (even)"; + staffRiseBonusTable.Description = "The staff rise bonus per item level for even magic power staves."; + + // Add new staff odd increase table + float[] staffRiseIncreaseByLevelOdd = { 0, 4, 7, 11, 14, 18, 21, 25, 28, 32, 36, 40, 45, 51, 57, 63 }; + + var staffOddTable = context.CreateNew(); + gameConfiguration.ItemLevelBonusTables.Add(staffOddTable); + staffOddTable.Name = "Staff Rise (odd)"; + staffOddTable.Description = "The staff rise bonus per item level for odd magic power staves."; + for (int level = 0; level < staffRiseIncreaseByLevelOdd.Length; level++) + { + var value = staffRiseIncreaseByLevelOdd[level]; + if (value != 0) + { + var levelBonus = context.CreateNew(); + levelBonus.Level = level; + levelBonus.AdditionalValue = staffRiseIncreaseByLevelOdd[level]; + staffOddTable.BonusPerLevel.Add(levelBonus); + } + } + + // Fix Group 5 weapons (staves) + var staves = gameConfiguration.Items.Where(i => i.Group == (int)ItemGroups.Staff && i.BasePowerUpAttributes.Any(pua => pua.TargetAttribute == Stats.StaffRise)); + foreach (var staff in staves) + { + if (staff.BasePowerUpAttributes.FirstOrDefault(pua => pua.TargetAttribute == Stats.StaffRise) is { } staffRiseAttr) + { + if ((int)staffRiseAttr.BaseValue % 2 != 0) + { + staffRiseAttr.BonusPerLevelTable = staffOddTable; + } + + staffRiseAttr.BaseValue /= 2.0f; + } + } + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugInSeason6.cs b/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugInSeason6.cs new file mode 100644 index 000000000..ef7eae966 --- /dev/null +++ b/src/Persistence/Initialization/Updates/FixWeaponRisePercentagePlugInSeason6.cs @@ -0,0 +1,380 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Persistence.Initialization.Updates; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.AttributeSystem; +using MUnique.OpenMU.DataModel.Attributes; +using MUnique.OpenMU.DataModel.Configuration; +using MUnique.OpenMU.DataModel.Configuration.Items; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.Network.Packets; +using MUnique.OpenMU.Persistence.Initialization.Items; +using MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Items; +using MUnique.OpenMU.PlugIns; +using static MUnique.OpenMU.Persistence.Initialization.CharacterClasses.CharacterClassHelper; + +/// +/// This update fixes weapons (staff, stick, book, scepter) rise percentage increase; Summoner weapons and wings wizardry/curse options; and Wing of Dimension (inc/dec), Cape of Overrule (inc/dec), Cape of Emperor (dec) damage rates.. +/// +[PlugIn(PlugInName, PlugInDescription)] +[Guid("58740F26-6496-4CCA-8C90-C4749E09DDB2")] +public class FixWeaponRisePercentagePlugInSeason6 : FixWeaponRisePercentagePlugInBase +{ + /// + /// The plug in name. + /// + private new const string PlugInName = "Fix Weapon Rise Percentage, Summoner Items Wizardry/Curse Options, and Several 3rd Level Wing Damage Rates"; + + /// + /// The plug in description. + /// + private new const string PlugInDescription = "This update fixes weapons (staff, stick, book, scepter) rise percentage; Summoner weapons and wings wizardry/curse options; and Wing of Dimension (inc/dec), Cape of Overrule (inc/dec), Cape of Emperor (dec) damage rates. Also includes fixes for Divine Staff of Archangel and Eternal Wing Stick."; + + /// + public override string Name => PlugInName; + + /// + public override string Description => PlugInDescription; + + /// + public override string DataInitializationKey => VersionSeasonSix.DataInitialization.Id; + + /// + public override UpdateVersion Version => UpdateVersion.FixWeaponRisePercentageSeason6; + + /// + protected override async ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration) + { + await base.ApplyAsync(context, gameConfiguration).ConfigureAwait(false); + + var scepterRiseBonusTable = gameConfiguration.ItemLevelBonusTables.Single(bt => bt.Name == "Scepter Rise"); + + // Modify existing table name and description + scepterRiseBonusTable.Name = "Scepter Rise (even)"; + scepterRiseBonusTable.Description = "The scepter rise bonus per item level for even magic power scepters."; + + // Add new scepter odd increase table + float[] scepterRiseIncreaseByLevelOdd = { 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 18, 21, 25, 29, 33 }; + + var scepterOddTable = context.CreateNew(); + gameConfiguration.ItemLevelBonusTables.Add(scepterOddTable); + scepterOddTable.Name = "Scepter Rise (odd)"; + scepterOddTable.Description = "The scepter rise bonus per item level for odd magic power scepters."; + for (int level = 0; level < scepterRiseIncreaseByLevelOdd.Length; level++) + { + var value = scepterRiseIncreaseByLevelOdd[level]; + if (value != 0) + { + var levelBonus = context.CreateNew(); + levelBonus.Level = level; + levelBonus.AdditionalValue = scepterRiseIncreaseByLevelOdd[level]; + scepterOddTable.BonusPerLevel.Add(levelBonus); + } + } + + // Fix scepters + var scepters = gameConfiguration.Items.Where(i => i.Group == (int)ItemGroups.Scepters && i.BasePowerUpAttributes.Any(pua => pua.TargetAttribute == Stats.ScepterRise)); + foreach (var scepter in scepters) + { + if (scepter.BasePowerUpAttributes.FirstOrDefault(pua => pua.TargetAttribute == Stats.ScepterRise) is { } scepterRiseAttr) + { + if ((int)scepterRiseAttr.BaseValue % 2 != 0) + { + scepterRiseAttr.BonusPerLevelTable = scepterOddTable; + } + + scepterRiseAttr.BaseValue /= 2.0f; + } + } + + // Fix Group 5 weapons (Skull & Divine Staves, sticks, and books) + var weaponsG5 = gameConfiguration.Items.Where(i => i.Group == 5); + var summonerWeapons = weaponsG5.Where(i => i.PossibleItemOptions.Contains(gameConfiguration.ItemOptions.First(io => io.Name == ExcellentOptions.CurseAttackOptionsName))); // Skull Staff included at this point + var staffEvenTable = gameConfiguration.ItemLevelBonusTables.Single(bt => bt.Name == "Staff Rise (even)"); + var staffOddTable = gameConfiguration.ItemLevelBonusTables.Single(bt => bt.Name == "Staff Rise (odd)"); + + // -> fix Skull Staff + if (weaponsG5.FirstOrDefault(e => e.Number == 0) is { } skullStaff) + { + skullStaff.PossibleItemOptions.Clear(); + skullStaff.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.Name == ExcellentOptions.WizardryAttackOptionsName)); + skullStaff.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.Name == HarmonyOptions.WizardryAttackOptionsName)); + skullStaff.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Luck))); + skullStaff.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumWizBaseDmg))); + + var powerUpDefinition = context.CreateNew(); + powerUpDefinition.TargetAttribute = Stats.StaffRise.GetPersistent(gameConfiguration); + powerUpDefinition.BaseValue = 6 / 2.0f; + powerUpDefinition.AggregateType = AggregateType.AddRaw; + powerUpDefinition.BonusPerLevelTable = staffEvenTable; + skullStaff.BasePowerUpAttributes.Add(powerUpDefinition); + } + + // -> fix Divine Staff of Archangel + if (weaponsG5.FirstOrDefault(e => e.Number == 10) is { } divineStaff) + { + var basePowerUps = divineStaff.BasePowerUpAttributes; + if (basePowerUps.FirstOrDefault(pu => pu.TargetAttribute == Stats.MinimumPhysBaseDmgByWeapon) is { } minPhysDmgAttr) + { + minPhysDmgAttr.BaseValue = 153; + } + + if (basePowerUps.FirstOrDefault(pu => pu.TargetAttribute == Stats.MaximumPhysBaseDmgByWeapon) is { } maxPhysDmgAttr) + { + maxPhysDmgAttr.BaseValue = 165; + } + + if (basePowerUps.FirstOrDefault(pu => pu.TargetAttribute == Stats.AttackSpeedByWeapon) is { } attackSpeedAttr) + { + attackSpeedAttr.BaseValue = 30; + } + + if (basePowerUps.FirstOrDefault(pu => pu.TargetAttribute == Stats.StaffRise) is { } staffRiseAttr) + { + staffRiseAttr.BaseValue = 156 / 2.0f; + } + } + + var rhOnlySlotType = gameConfiguration.ItemSlotTypes.First(t => !t.ItemSlots.Contains(0) && t.ItemSlots.Contains(1)); + var books = summonerWeapons.Where(e => e.ItemSlot == rhOnlySlotType); + var sticks = summonerWeapons.Except(books); + + // -> fix sticks + Dictionary sticksMagicPower = new() + { + [14] = 34, + [15] = 46, + [16] = 59, + [17] = 76, + [18] = 92, + [19] = 110, + [20] = 106, + [34] = 130, + [36] = 146, + }; + foreach (var stick in sticks) + { + stick.PossibleItemOptions.Clear(); + stick.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.Name == ExcellentOptions.WizardryAttackOptionsName)); + stick.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.Name == HarmonyOptions.WizardryAttackOptionsName)); + stick.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Luck))); + stick.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumWizBaseDmg))); + if (sticksMagicPower.ContainsKey(stick.Number)) + { + var powerUpDefinition = context.CreateNew(); + powerUpDefinition.TargetAttribute = Stats.StaffRise.GetPersistent(gameConfiguration); + powerUpDefinition.BaseValue = sticksMagicPower[stick.Number] / 2.0f; + powerUpDefinition.AggregateType = AggregateType.AddRaw; + powerUpDefinition.BonusPerLevelTable = sticksMagicPower[stick.Number] % 2 == 0 ? staffEvenTable : staffOddTable; + stick.BasePowerUpAttributes.Add(powerUpDefinition); + } + } + + // -> fix Eternal Wing Stick + if (weaponsG5.FirstOrDefault(e => e.Number == 20) is { } eternalStick) + { + eternalStick.DropLevel = 147; + var basePowerUps = eternalStick.BasePowerUpAttributes; + if (basePowerUps.FirstOrDefault(pu => pu.TargetAttribute == Stats.MinimumPhysBaseDmgByWeapon) is { } minPhysDmgAttr) + { + minPhysDmgAttr.BaseValue = 66; + } + + if (basePowerUps.FirstOrDefault(pu => pu.TargetAttribute == Stats.MaximumPhysBaseDmgByWeapon) is { } maxPhysDmgAttr) + { + maxPhysDmgAttr.BaseValue = 74; + } + + if (basePowerUps.FirstOrDefault(pu => pu.TargetAttribute == Stats.AttackSpeedByWeapon) is { } attackSpeedAttr) + { + attackSpeedAttr.BaseValue = 30; + } + } + + // -> fix books + if (gameConfiguration.CharacterClasses.FirstOrDefault(cc => cc.Number == (int)CharacterClassNumber.Summoner) is { } summoner) + { + var bookRiseAttr = context.CreateNew(Stats.BookRise.Id, Stats.BookRise.Designation, Stats.BookRise.Description); + gameConfiguration.Attributes.Add(bookRiseAttr); + summoner.AttributeCombinations.Add(CreateAttributeRelationship(context, gameConfiguration, Stats.CurseAttackDamageIncrease, 1.0f / 100, Stats.BookRise)); + } + + Dictionary booksMagicPower = new() { [21] = 46, [22] = 59, [23] = 72 }; + foreach (var book in books) + { + book.PossibleItemOptions.Clear(); + book.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.Name == ExcellentOptions.WizardryAttackOptionsName)); + book.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.Name == HarmonyOptions.WizardryAttackOptionsName)); + book.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Luck))); + book.PossibleItemOptions.Add(gameConfiguration.ItemOptions.First(io => io.PossibleOptions.Any(o => o.OptionType == ItemOptionTypes.Option && o.PowerUpDefinition?.TargetAttribute == Stats.MaximumCurseBaseDmg))); + if (booksMagicPower.ContainsKey(book.Number)) + { + var powerUpDefinition = context.CreateNew(); + powerUpDefinition.TargetAttribute = Stats.BookRise.GetPersistent(gameConfiguration); + powerUpDefinition.BaseValue = booksMagicPower[book.Number] / 2.0f; + powerUpDefinition.AggregateType = AggregateType.AddRaw; + powerUpDefinition.BonusPerLevelTable = booksMagicPower[book.Number] % 2 == 0 ? staffEvenTable : staffOddTable; + book.BasePowerUpAttributes.Add(powerUpDefinition); + } + + if (book.BasePowerUpAttributes.FirstOrDefault(pua => pua.TargetAttribute == Stats.IsStickEquipped) is { } stickEquipAttr) + { + book.BasePowerUpAttributes.Remove(stickEquipAttr); + } + } + + // Fix Wings of Curse options + var wingsOfCurse = gameConfiguration.Items.FirstOrDefault(i => i.GetId() == new Guid("00000080-000c-0029-0000-000000000000")); + if (wingsOfCurse is not null) + { + wingsOfCurse.Name = "Wings of Curse"; + var wingOpts = wingsOfCurse.PossibleItemOptions.First(o => o.Name == "Wing of Curse Options"); + + var wizOption = wingOpts.PossibleOptions.First(); + wizOption.PowerUpDefinition = this.CreatePowerUpDefinition(Stats.MaximumWizBaseDmg, 0, AggregateType.AddRaw, context, gameConfiguration); + wizOption.LevelDependentOptions.Clear(); + for (int level = 1; level <= 4; level++) + { + var optionOfLevel = context.CreateNew(); + optionOfLevel.Level = level; + optionOfLevel.PowerUpDefinition = this.CreatePowerUpDefinition( + wizOption.PowerUpDefinition.TargetAttribute!, + level * 4f, + AggregateType.AddRaw, + context, + gameConfiguration); + wizOption.LevelDependentOptions.Add(optionOfLevel); + } + } + + // Fix Wings of Despair options + var wingsOfDespair = gameConfiguration.Items.FirstOrDefault(i => i.GetId() == new Guid("00000080-000c-002a-0000-000000000000")); + if (wingsOfDespair is not null) + { + var wingOpts = wingsOfDespair.PossibleItemOptions.First(o => o.Name == "Wings of Despair Options"); + + var curseOption = wingOpts.PossibleOptions.First(o => o.Number == 0); + curseOption.PowerUpDefinition = this.CreatePowerUpDefinition(Stats.MaximumCurseBaseDmg, 0, AggregateType.AddRaw, context, gameConfiguration); + curseOption.LevelDependentOptions.Clear(); + for (int level = 1; level <= 4; level++) + { + var optionOfLevel = context.CreateNew(); + optionOfLevel.Level = level; + optionOfLevel.PowerUpDefinition = this.CreatePowerUpDefinition( + curseOption.PowerUpDefinition.TargetAttribute!, + level * 4f, + AggregateType.AddRaw, + context, + gameConfiguration); + curseOption.LevelDependentOptions.Add(optionOfLevel); + } + + var wizOption = wingOpts.PossibleOptions.First(o => o.Number == 2); + wizOption.PowerUpDefinition = this.CreatePowerUpDefinition(Stats.MaximumWizBaseDmg, 0, AggregateType.AddRaw, context, gameConfiguration); + wizOption.LevelDependentOptions.Clear(); + for (int level = 1; level <= 4; level++) + { + var optionOfLevel = context.CreateNew(); + optionOfLevel.Level = level; + optionOfLevel.PowerUpDefinition = this.CreatePowerUpDefinition( + wizOption.PowerUpDefinition.TargetAttribute!, + level * 4f, + AggregateType.AddRaw, + context, + gameConfiguration); + wizOption.LevelDependentOptions.Add(optionOfLevel); + } + } + + // Fix Wing of Dimension options + var wingsOfDimension = gameConfiguration.Items.FirstOrDefault(i => i.GetId() == new Guid("00000080-000c-002b-0000-000000000000")); + if (wingsOfDimension is not null) + { + var wingOpts = wingsOfDimension.PossibleItemOptions.First(o => o.Name == "Wing of Dimension Options"); + + var wizOption = wingOpts.PossibleOptions.First(o => o.Number == 3); + wizOption.PowerUpDefinition = this.CreatePowerUpDefinition(Stats.MaximumWizBaseDmg, 0, AggregateType.AddRaw, context, gameConfiguration); + wizOption.LevelDependentOptions.Clear(); + for (int level = 1; level <= 4; level++) + { + var optionOfLevel = context.CreateNew(); + optionOfLevel.Level = level; + optionOfLevel.PowerUpDefinition = this.CreatePowerUpDefinition( + wizOption.PowerUpDefinition.TargetAttribute!, + level * 4f, + AggregateType.AddRaw, + context, + gameConfiguration); + wizOption.LevelDependentOptions.Add(optionOfLevel); + } + + var curseOption = wingOpts.PossibleOptions.First(o => o.Number == 2); + curseOption.PowerUpDefinition = this.CreatePowerUpDefinition(Stats.MaximumCurseBaseDmg, 0, AggregateType.AddRaw, context, gameConfiguration); + curseOption.LevelDependentOptions.Clear(); + for (int level = 1; level <= 4; level++) + { + var optionOfLevel = context.CreateNew(); + optionOfLevel.Level = level; + optionOfLevel.PowerUpDefinition = this.CreatePowerUpDefinition( + curseOption.PowerUpDefinition.TargetAttribute!, + level * 4f, + AggregateType.AddRaw, + context, + gameConfiguration); + curseOption.LevelDependentOptions.Add(optionOfLevel); + } + + if (wingsOfDimension.BasePowerUpAttributes.FirstOrDefault(pua => pua.TargetAttribute == Stats.AttackDamageIncrease) is { } dmgInc) + { + dmgInc.BaseValue = 1f + (39 / 100f); + } + + if (wingsOfDimension.BasePowerUpAttributes.FirstOrDefault(pua => pua.TargetAttribute == Stats.DamageReceiveDecrement) is { } dmgDec) + { + dmgDec.BaseValue = 1f - (39 / 100f); + } + } + + // Fix Cape of Overrule dmg increase/decrease rate + var capeOfOverrule = gameConfiguration.Items.FirstOrDefault(i => i.GetId() == new Guid("00000080-000c-0032-0000-000000000000")); + if (capeOfOverrule is not null) + { + if (capeOfOverrule.BasePowerUpAttributes.FirstOrDefault(pua => pua.TargetAttribute == Stats.AttackDamageIncrease) is { } dmgInc) + { + dmgInc.BaseValue = 1f + (39 / 100f); + } + + if (capeOfOverrule.BasePowerUpAttributes.FirstOrDefault(pua => pua.TargetAttribute == Stats.DamageReceiveDecrement) is { } dmgDec) + { + dmgDec.BaseValue = 1f - (39 / 100f); + } + } + + // Fix Cape of Emperor dmg decrease rate + var capeOfEmperor = gameConfiguration.Items.FirstOrDefault(i => i.GetId() == new Guid("00000080-000c-0028-0000-000000000000")); + if (capeOfEmperor is not null) + { + if (capeOfEmperor.BasePowerUpAttributes.FirstOrDefault(pua => pua.TargetAttribute == Stats.DamageReceiveDecrement) is { } dmgDec) + { + dmgDec.BaseValue = 1f - (24 / 100f); + } + } + } + + private PowerUpDefinition CreatePowerUpDefinition(AttributeDefinition attributeDefinition, float value, AggregateType aggregateType, IContext context, GameConfiguration gameConfiguration) + { + var powerUpDefinition = context.CreateNew(); + powerUpDefinition.TargetAttribute = attributeDefinition.GetPersistent(gameConfiguration); + if (value != 0) + { + powerUpDefinition.Boost = context.CreateNew(); + powerUpDefinition.Boost.ConstantValue.Value = value; + powerUpDefinition.Boost.ConstantValue.AggregateType = aggregateType; + } + + return powerUpDefinition; + } +} \ No newline at end of file diff --git a/src/Persistence/Initialization/Updates/UpdateVersion.cs b/src/Persistence/Initialization/Updates/UpdateVersion.cs index ca11d7e7c..2f5465e1a 100644 --- a/src/Persistence/Initialization/Updates/UpdateVersion.cs +++ b/src/Persistence/Initialization/Updates/UpdateVersion.cs @@ -194,7 +194,7 @@ public enum UpdateVersion /// The version of the . /// FixAttackSpeedCalculation = 37, - + /// /// The version of the . /// @@ -204,4 +204,19 @@ public enum UpdateVersion /// The version of the . /// FixItemRequirements = 39, + + /// + /// The version of the . + /// + FixWeaponRisePercentage075 = 40, + + /// + /// The version of the . + /// + FixWeaponRisePercentage095d = 41, + + /// + /// The version of the . + /// + FixWeaponRisePercentageSeason6 = 42, } \ No newline at end of file diff --git a/src/Persistence/Initialization/Version075/Items/Weapons.cs b/src/Persistence/Initialization/Version075/Items/Weapons.cs index ba36e1bcd..bd52cee0f 100644 --- a/src/Persistence/Initialization/Version075/Items/Weapons.cs +++ b/src/Persistence/Initialization/Version075/Items/Weapons.cs @@ -26,11 +26,13 @@ internal class Weapons : InitializerBase /// private static readonly float[] DamageIncreaseByLevel = { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 31, 36 }; - private static readonly float[] StaffRiseIncreaseByLevel = { 0, 3, 7, 10, 14, 17, 21, 24, 28, 31, 35, 40 }; + private static readonly float[] StaffRiseIncreaseByLevelEven = { 0, 3, 7, 10, 14, 17, 21, 24, 28, 31, 35, 40, 45, 50, 56, 63 }; // Staff with even magic power + private static readonly float[] StaffRiseIncreaseByLevelOdd = { 0, 4, 7, 11, 14, 18, 21, 25, 28, 32, 36, 40, 45, 51, 57, 63 }; // Staff with odd magic power private ItemLevelBonusTable? _weaponDamageIncreaseTable; - private ItemLevelBonusTable? _staffRiseTable; + private ItemLevelBonusTable? _staffRiseTableEven; + private ItemLevelBonusTable? _staffRiseTableOdd; /// /// Initializes a new instance of the class. @@ -81,7 +83,8 @@ protected ItemOptionDefinition WizardryDamageOption public override void Initialize() { this._weaponDamageIncreaseTable = this.CreateItemBonusTable(DamageIncreaseByLevel, "Damage Increase (Weapons)", "The damage increase by weapon level. It increases by 3 per level, and 1 more after level 10."); - this._staffRiseTable = this.CreateItemBonusTable(StaffRiseIncreaseByLevel, "Staff Rise", "The staff rise bonus per item level."); + this._staffRiseTableEven = this.CreateItemBonusTable(StaffRiseIncreaseByLevelEven, "Staff Rise (even)", "The staff rise bonus per item level for even magic power staves."); + this._staffRiseTableOdd = this.CreateItemBonusTable(StaffRiseIncreaseByLevelOdd, "Staff Rise (odd)", "The staff rise bonus per item level for odd magic power staves."); this.CreateWeapon(0, 0, 0, 0, 1, 2, true, "Kris", 6, 6, 11, 50, 20, 0, 0, 40, 40, 0, 0, 1, 1, 1); this.CreateWeapon(0, 1, 0, 0, 1, 3, true, "Short Sword", 3, 3, 7, 20, 22, 0, 0, 60, 0, 0, 0, 1, 1, 1); @@ -216,7 +219,7 @@ protected void CreateAmmunition(byte @group, byte number, byte slot, byte width, /// The maximum damage. /// The attack speed. /// The durability. - /// The staff rise. + /// The magic power. /// The level requirement. /// The strength requirement. /// The agility requirement. @@ -228,7 +231,7 @@ protected void CreateAmmunition(byte @group, byte number, byte slot, byte width, /// If set to true, the item is ammunition for a weapon. protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber, byte width, byte height, bool dropsFromMonsters, string name, byte dropLevel, int minimumDamage, int maximumDamage, int attackSpeed, - byte durability, int staffRise, int levelRequirement, int strengthRequirement, int agilityRequirement, + byte durability, int magicPower, int levelRequirement, int strengthRequirement, int agilityRequirement, int energyRequirement, int vitalityRequirement, int wizardClass, int knightClass, int elfClass, bool isAmmunition = false) { @@ -282,7 +285,7 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.PossibleItemOptions.Add(this.Luck); - if (staffRise == 0) + if (magicPower == 0) { item.PossibleItemOptions.Add(this.PhysicalDamageOption); } @@ -290,8 +293,8 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber { item.PossibleItemOptions.Add(this.WizardryDamageOption); - var staffRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.StaffRise, staffRise, AggregateType.AddRaw); - staffRisePowerUp.BonusPerLevelTable = this._staffRiseTable; + var staffRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.StaffRise, magicPower / 2.0f, AggregateType.AddRaw); + staffRisePowerUp.BonusPerLevelTable = magicPower % 2 == 0 ? this._staffRiseTableEven : this._staffRiseTableOdd; item.BasePowerUpAttributes.Add(staffRisePowerUp); } diff --git a/src/Persistence/Initialization/Version095d/Items/Weapons.cs b/src/Persistence/Initialization/Version095d/Items/Weapons.cs index 4bcc94196..27dbe137a 100644 --- a/src/Persistence/Initialization/Version095d/Items/Weapons.cs +++ b/src/Persistence/Initialization/Version095d/Items/Weapons.cs @@ -26,11 +26,13 @@ internal class Weapons : InitializerBase /// private static readonly float[] DamageIncreaseByLevel = { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 31, 36 }; - private static readonly float[] StaffRiseIncreaseByLevel = { 0, 3, 7, 10, 14, 17, 21, 24, 28, 31, 35, 40 }; + private static readonly float[] StaffRiseIncreaseByLevelEven = { 0, 3, 7, 10, 14, 17, 21, 24, 28, 31, 35, 40, 45, 50, 56, 63 }; // Staff with even magic power + private static readonly float[] StaffRiseIncreaseByLevelOdd = { 0, 4, 7, 11, 14, 18, 21, 25, 28, 32, 36, 40, 45, 51, 57, 63 }; // Staff with odd magic power private ItemLevelBonusTable? _weaponDamageIncreaseTable; - private ItemLevelBonusTable? _staffRiseTable; + private ItemLevelBonusTable? _staffRiseTableEven; + private ItemLevelBonusTable? _staffRiseTableOdd; /// /// Initializes a new instance of the class. @@ -81,7 +83,8 @@ protected ItemOptionDefinition WizardryDamageOption public override void Initialize() { this._weaponDamageIncreaseTable = this.CreateItemBonusTable(DamageIncreaseByLevel, "Damage Increase (Weapons)", "The damage increase by weapon level. It increases by 3 per level, and 1 more after level 10."); - this._staffRiseTable = this.CreateItemBonusTable(StaffRiseIncreaseByLevel, "Staff Rise", "The staff rise bonus per item level."); + this._staffRiseTableEven = this.CreateItemBonusTable(StaffRiseIncreaseByLevelEven, "Staff Rise (even)", "The staff rise bonus per item level for even magic power staves."); + this._staffRiseTableOdd = this.CreateItemBonusTable(StaffRiseIncreaseByLevelOdd, "Staff Rise (odd)", "The staff rise bonus per item level for odd magic power staves."); this.CreateWeapon(0, 0, 0, 0, 1, 2, true, "Kris", 6, 6, 11, 50, 20, 0, 0, 40, 40, 0, 0, 1, 1, 1); this.CreateWeapon(0, 1, 0, 0, 1, 3, true, "Short Sword", 3, 3, 7, 20, 22, 0, 0, 60, 0, 0, 0, 1, 1, 1); @@ -221,7 +224,7 @@ protected void CreateAmmunition(byte @group, byte number, byte slot, byte width, /// The maximum damage. /// The attack speed. /// The durability. - /// The staff rise. + /// The magic power. /// The level requirement. /// The strength requirement. /// The agility requirement. @@ -234,7 +237,7 @@ protected void CreateAmmunition(byte @group, byte number, byte slot, byte width, /// If set to true, the item is ammunition for a weapon. protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber, byte width, byte height, bool dropsFromMonsters, string name, byte dropLevel, int minimumDamage, int maximumDamage, int attackSpeed, - byte durability, int staffRise, int levelRequirement, int strengthRequirement, int agilityRequirement, + byte durability, int magicPower, int levelRequirement, int strengthRequirement, int agilityRequirement, int energyRequirement, int vitalityRequirement, int wizardClass, int knightClass, int elfClass, int magicGladiatorClass = 0, bool isAmmunition = false) { @@ -292,7 +295,7 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.PossibleItemOptions.Add(this.Luck); - if (staffRise == 0) + if (magicPower == 0) { item.PossibleItemOptions.Add(this.PhysicalDamageOption); item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == ExcellentOptions.PhysicalAttackOptionsName)); @@ -302,8 +305,8 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.PossibleItemOptions.Add(this.WizardryDamageOption); item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == ExcellentOptions.WizardryAttackOptionsName)); - var staffRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.StaffRise, staffRise, AggregateType.AddRaw); - staffRisePowerUp.BonusPerLevelTable = this._staffRiseTable; + var staffRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.StaffRise, magicPower / 2.0f, AggregateType.AddRaw); + staffRisePowerUp.BonusPerLevelTable = magicPower % 2 == 0 ? this._staffRiseTableEven : this._staffRiseTableOdd; item.BasePowerUpAttributes.Add(staffRisePowerUp); } diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/HarmonyOptions.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/HarmonyOptions.cs index 756e67505..71f205fc7 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/HarmonyOptions.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/HarmonyOptions.cs @@ -51,9 +51,12 @@ public override void Initialize() this.CreateDefenseOptions(); this.CreatePhysicalAttackOptions(); this.CreateWizardryAttackOptions(); - this.CreateCurseAttackOptions(); + + // this.CreateCurseAttackOptions(); } + [Obsolete(@"There are no curse attack harmony options until Season 16 (JoH system renewal). Until then, curse spell books had wizardry attack options. + Reference: https://muonline.webzen.com/en/gameinfo/guide/detail/117")] private void CreateCurseAttackOptions() { var definition = this.Context.CreateNew(); diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs index e8213df07..965ea95e5 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs @@ -32,15 +32,19 @@ internal class Weapons : InitializerBase /// private static readonly float[] DamageIncreaseByLevel = { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 31, 36, 42, 49, 57, 66 }; - private static readonly float[] StaffRiseIncreaseByLevel = { 0, 3, 7, 10, 14, 17, 21, 24, 28, 31, 35, 40, 45, 50, 56, 63 }; + private static readonly float[] StaffRiseIncreaseByLevelEven = { 0, 3, 7, 10, 14, 17, 21, 24, 28, 31, 35, 40, 45, 50, 56, 63 }; // Staff/stick with even magic power + private static readonly float[] StaffRiseIncreaseByLevelOdd = { 0, 4, 7, 11, 14, 18, 21, 25, 28, 32, 36, 40, 45, 51, 57, 63 }; // Staff/stick with odd magic power - private static readonly float[] ScepterRiseIncreaseByLevel = { 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 18, 21, 25, 29, 33 }; + private static readonly float[] ScepterRiseIncreaseByLevelEven = { 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 18, 21, 24, 28, 33 }; // Scepter with even magic power + private static readonly float[] ScepterRiseIncreaseByLevelOdd = { 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 18, 21, 25, 29, 33 }; // Scepter with odd magic power private ItemLevelBonusTable? _weaponDamageIncreaseTable; - private ItemLevelBonusTable? _staffRiseTable; + private ItemLevelBonusTable? _staffRiseTableEven; + private ItemLevelBonusTable? _staffRiseTableOdd; - private ItemLevelBonusTable? _scepterRiseTable; + private ItemLevelBonusTable? _scepterRiseTableEven; + private ItemLevelBonusTable? _scepterRiseTableOdd; /// /// Initializes a new instance of the class. @@ -106,8 +110,10 @@ protected ItemOptionDefinition CurseDamageOption public override void Initialize() { this._weaponDamageIncreaseTable = this.CreateItemBonusTable(DamageIncreaseByLevel, "Damage Increase (Weapons)", "The damage increase by weapon level. It increases by 3 per level, and 1 more after level 10."); - this._staffRiseTable = this.CreateItemBonusTable(StaffRiseIncreaseByLevel, "Staff Rise", "The staff rise bonus per item level."); - this._scepterRiseTable = this.CreateItemBonusTable(ScepterRiseIncreaseByLevel, "Scepter Rise", "The scepter rise bonus per item level."); + this._staffRiseTableEven = this.CreateItemBonusTable(StaffRiseIncreaseByLevelEven, "Staff Rise (even)", "The staff rise bonus per item level for even magic power staves."); + this._staffRiseTableOdd = this.CreateItemBonusTable(StaffRiseIncreaseByLevelOdd, "Staff Rise (odd)", "The staff rise bonus per item level for odd magic power staves."); + this._scepterRiseTableEven = this.CreateItemBonusTable(ScepterRiseIncreaseByLevelEven, "Scepter Rise (even)", "The scepter rise bonus per item level for even magic power scepters."); + this._scepterRiseTableOdd = this.CreateItemBonusTable(ScepterRiseIncreaseByLevelOdd, "Scepter Rise (odd)", "The scepter rise bonus per item level for odd magic power scepters."); this.CreateWeapon(0, 0, 0, 0, 1, 2, true, "Kris", 6, 6, 11, 50, 20, 0, 0, 40, 40, 0, 0, 1, 1, 1, 1, 1, 1, 1); this.CreateWeapon(0, 1, 0, 0, 1, 3, true, "Short Sword", 3, 3, 7, 20, 22, 0, 0, 60, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1); @@ -170,7 +176,7 @@ public override void Initialize() this.CreateWeapon(2, 13, 0, 66, 1, 4, false, "Divine Scepter of Archangel", 150, 120, 143, 45, 90, 78, 0, 75, 16, 0, 0, 0, 0, 0, 0, 1, 0, 0); this.CreateWeapon(2, 14, 0, 66, 1, 4, true, "Soleil Scepter", 146, 130, 153, 40, 95, 84, 380, 80, 15, 0, 0, 0, 0, 0, 0, 1, 0, 0); this.CreateWeapon(2, 15, 0, 66, 1, 4, true, "Shining Scepter", 110, 99, 111, 40, 78, 60, 0, 108, 22, 0, 0, 0, 0, 0, 0, 1, 0, 0); - this.CreateWeapon(2, 16, 0, 0, 1, 3, true, "Frost mace", 121, 106, 146, 50, 80, 0, 0, 27, 19, 0, 0, 0, 0, 2, 0, 0, 0, 0); + this.CreateWeapon(2, 16, 0, 0, 1, 3, true, "Frost Mace", 121, 106, 146, 50, 80, 0, 0, 27, 19, 0, 0, 0, 0, 2, 0, 0, 0, 0); this.CreateWeapon(2, 17, 0, 66, 1, 4, true, "Absolute Scepter", 135, 114, 132, 40, 90, 72, 0, 119, 24, 0, 0, 0, 0, 0, 0, 1, 0, 0); this.CreateWeapon(2, 18, 0, 66, 1, 4, false, "Stryker Scepter", 147, 112, 124, 40, 86, 70, 0, 87, 20, 0, 0, 0, 0, 0, 0, 1, 0, 0); // this.CreateWeapon(2, 22, 0, 0, 1, 3, true, "Mace of The king", 54, 132, 153, 45, 40, 3, 0, 80, 17, 0, 0, 0, 1, 1, 1, 1, 0, 0); @@ -206,7 +212,7 @@ public override void Initialize() this.CreateWeapon(4, 15, 0, 0, 1, 1, false, "Arrows", 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0); this.CreateWeapon(4, 16, 0, 24, 2, 4, true, "Saint Crossbow", 84, 102, 127, 35, 72, 0, 0, 50, 160, 0, 0, 0, 0, 1, 0, 0, 0, 0); this.CreateWeapon(4, 17, 1, 24, 2, 4, true, "Celestial Bow", 92, 127, 155, 35, 76, 0, 0, 54, 198, 0, 0, 0, 0, 2, 0, 0, 0, 0); - this.CreateWeapon(4, 18, 0, 24, 2, 3, false, "Divine CB of Archangel", 100, 144, 166, 35, 200, 0, 0, 40, 110, 0, 0, 0, 0, 1, 0, 0, 0, 0); + this.CreateWeapon(4, 18, 0, 24, 2, 3, false, "Divine Crossbow of Archangel", 100, 144, 166, 35, 200, 0, 0, 40, 110, 0, 0, 0, 0, 1, 0, 0, 0, 0); this.CreateWeapon(4, 19, 0, 24, 2, 3, true, "Great Reign Crossbow", 100, 150, 172, 40, 80, 0, 0, 61, 285, 0, 0, 0, 0, 2, 0, 0, 0, 0); this.CreateWeapon(4, 20, 1, 24, 2, 4, true, "Arrow Viper Bow", 135, 166, 190, 45, 86, 0, 0, 52, 245, 0, 0, 0, 0, 2, 0, 0, 0, 0); this.CreateWeapon(4, 21, 1, 24, 2, 4, true, "Sylph Wind Bow", 147, 177, 200, 45, 93, 0, 380, 46, 210, 0, 0, 0, 0, 2, 0, 0, 0, 0); @@ -224,7 +230,7 @@ public override void Initialize() this.CreateWeapon(5, 7, 0, 0, 2, 4, false, "Chaos Lightning Staff", 75, 47, 48, 30, 70, 94, 0, 60, 10, 0, 0, 1, 0, 0, 1, 0, 0, 0); this.CreateWeapon(5, 8, 0, 0, 2, 4, true, "Staff of Destruction", 90, 50, 54, 30, 85, 101, 0, 60, 10, 0, 0, 1, 0, 0, 1, 0, 0, 0); this.CreateWeapon(5, 9, 0, 0, 1, 4, true, "Dragon Soul Staff", 100, 46, 48, 30, 91, 92, 0, 52, 16, 0, 0, 2, 0, 0, 0, 0, 0, 0); - this.CreateWeapon(5, 10, 0, 0, 1, 4, false, "Divine Staff of Archangel", 104, 53, 55, 20, 182, 106, 0, 36, 4, 0, 0, 1, 0, 0, 1, 0, 0, 0); + this.CreateWeapon(5, 10, 0, 0, 1, 4, false, "Divine Staff of Archangel", 104, 153, 165, 30, 182, 156, 0, 36, 4, 0, 0, 1, 0, 0, 1, 0, 0, 0); this.CreateWeapon(5, 11, 0, 0, 1, 4, true, "Staff of Kundun", 140, 55, 61, 30, 95, 110, 0, 45, 16, 0, 0, 2, 0, 0, 1, 0, 0, 0); this.CreateWeapon(5, 12, 0, 0, 1, 4, true, "Grand Viper Staff", 147, 66, 74, 30, 100, 130, 380, 39, 13, 0, 0, 2, 0, 0, 0, 0, 0, 0); this.CreateWeapon(5, 13, 0, 0, 1, 4, true, "Platina Staff", 110, 51, 53, 30, 78, 120, 0, 50, 16, 0, 0, 2, 0, 0, 0, 0, 0, 0); @@ -234,12 +240,12 @@ public override void Initialize() this.CreateWeapon(5, 17, 0, 0, 1, 4, true, "Ancient Stick", 78, 38, 40, 25, 81, 76, 0, 50, 19, 0, 0, 0, 0, 0, 0, 0, 1, 0); this.CreateWeapon(5, 18, 0, 0, 1, 4, true, "Demonic Stick", 100, 46, 48, 30, 91, 92, 0, 54, 15, 0, 0, 0, 0, 0, 0, 0, 2, 0); this.CreateWeapon(5, 19, 0, 0, 1, 4, true, "Storm Blitz Stick", 110, 51, 53, 30, 95, 110, 380, 64, 15, 0, 0, 0, 0, 0, 0, 0, 2, 0); - this.CreateWeapon(5, 20, 0, 0, 1, 4, true, "Eternal Wing Stick", 130, 56, 58, 25, 100, 113, 0, 60, 25, 0, 0, 0, 0, 0, 0, 0, 2, 0); + this.CreateWeapon(5, 20, 0, 0, 1, 4, true, "Eternal Wing Stick", 147, 66, 74, 30, 100, 106, 380, 57, 13, 0, 0, 0, 0, 0, 0, 0, 2, 0); this.CreateWeapon(5, 21, 1, 223, 1, 2, true, "Book of Sahamutt", 52, 0, 0, 25, 60, 46, 0, 0, 20, 135, 0, 0, 0, 0, 0, 0, 1, 0); this.CreateWeapon(5, 22, 1, 224, 1, 2, true, "Book of Neil", 59, 0, 0, 25, 65, 59, 0, 0, 25, 168, 0, 0, 0, 0, 0, 0, 1, 0); this.CreateWeapon(5, 23, 1, 225, 1, 2, true, "Book of Lagle", 65, 0, 0, 25, 50, 72, 0, 0, 30, 201, 0, 0, 0, 0, 0, 0, 1, 0); - this.CreateWeapon(5, 30, 0, 0, 1, 4, true, "Deadly Staff", 138, 57, 59, 30, 91, 126, 0, 47, 18, 0, 0, 0, 0, 0, 1, 0, 0, 0); - this.CreateWeapon(5, 31, 0, 0, 1, 4, true, "Imperial Staff", 137, 57, 61, 30, 182, 124, 0, 48, 14, 0, 0, 2, 0, 0, 0, 0, 0, 0); + this.CreateWeapon(5, 30, 0, 0, 1, 4, true, "Deadly Staff", 138, 57, 59, 30, 91, 126, 380, 47, 18, 0, 0, 0, 0, 0, 1, 0, 0, 0); + this.CreateWeapon(5, 31, 0, 0, 1, 4, true, "Imperial Staff", 137, 57, 61, 30, 182, 124, 380, 48, 14, 0, 0, 2, 0, 0, 0, 0, 0, 0); this.CreateWeapon(5, 33, 0, 0, 1, 4, false, "Chromatic Staff", 147, 55, 57, 30, 78, 124, 0, 50, 12, 0, 0, 2, 0, 0, 1, 0, 0, 0); this.CreateWeapon(5, 34, 0, 0, 1, 4, false, "Raven Stick", 147, 70, 78, 30, 98, 130, 0, 50, 14, 0, 0, 0, 0, 0, 0, 0, 2, 0); this.CreateWeapon(5, 36, 0, 0, 1, 4, false, "Divine Stick of Archangel", 104, 153, 165, 30, 182, 146, 0, 55, 13, 0, 0, 0, 0, 0, 0, 0, 1, 0); @@ -263,7 +269,7 @@ public override void Initialize() /// The maximum damage. /// The attack speed. /// The durability. - /// The staff rise. + /// The magic power. /// The level requirement. /// The strength requirement. /// The agility requirement. @@ -278,7 +284,7 @@ public override void Initialize() /// The ragefighter class. protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber, byte width, byte height, bool dropsFromMonsters, string name, byte dropLevel, int minimumDamage, int maximumDamage, int attackSpeed, - byte durability, int staffRise, int levelRequirement, int strengthRequirement, int agilityRequirement, + byte durability, int magicPower, int levelRequirement, int strengthRequirement, int agilityRequirement, int energyRequirement, int vitalityRequirement, int wizardClass, int knightClass, int elfClass, int magicGladiatorClass, int darkLordClass, int summonerClass, int ragefighterClass) { @@ -313,13 +319,16 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber var qualifiedCharacterClasses = this.GameConfiguration.DetermineCharacterClasses(wizardClass, knightClass, elfClass, magicGladiatorClass, darkLordClass, summonerClass, ragefighterClass); qualifiedCharacterClasses.ToList().ForEach(item.QualifiedCharacters.Add); - var minDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MinimumPhysBaseDmgByWeapon, minimumDamage, AggregateType.AddRaw); - minDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; - item.BasePowerUpAttributes.Add(minDamagePowerUp); + if (minimumDamage > 0) + { + var minDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MinimumPhysBaseDmgByWeapon, minimumDamage, AggregateType.AddRaw); + minDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; + item.BasePowerUpAttributes.Add(minDamagePowerUp); - var maxDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MaximumPhysBaseDmgByWeapon, maximumDamage, AggregateType.AddRaw); - maxDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; - item.BasePowerUpAttributes.Add(maxDamagePowerUp); + var maxDamagePowerUp = this.CreateItemBasePowerUpDefinition(Stats.MaximumPhysBaseDmgByWeapon, maximumDamage, AggregateType.AddRaw); + maxDamagePowerUp.BonusPerLevelTable = this._weaponDamageIncreaseTable; + item.BasePowerUpAttributes.Add(maxDamagePowerUp); + } var speedPowerUp = this.CreateItemBasePowerUpDefinition(Stats.AttackSpeedByWeapon, attackSpeed, AggregateType.AddRaw); item.BasePowerUpAttributes.Add(speedPowerUp); @@ -332,39 +341,39 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber item.PossibleItemOptions.Add(this.Luck); - if (staffRise == 0) + if (magicPower == 0 || darkLordClass > 0) { item.PossibleItemOptions.Add(this.PhysicalDamageOption); item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == ExcellentOptions.PhysicalAttackOptionsName)); item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == HarmonyOptions.PhysicalAttackOptionsName)); + + if (darkLordClass > 0) + { + var scepterRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.ScepterRise, magicPower / 2.0f, AggregateType.AddRaw); + scepterRisePowerUp.BonusPerLevelTable = magicPower % 2 == 0 ? this._scepterRiseTableEven : this._scepterRiseTableOdd; + item.BasePowerUpAttributes.Add(scepterRisePowerUp); + } } else { - if (summonerClass > 0) + item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == ExcellentOptions.WizardryAttackOptionsName)); + item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == HarmonyOptions.WizardryAttackOptionsName)); + + if (summonerClass > 0 && slot == 1) { item.PossibleItemOptions.Add(this.CurseDamageOption); - item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == ExcellentOptions.CurseAttackOptionsName)); - item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == HarmonyOptions.CurseAttackOptionsName)); - //// TODO: Is there something similar as the staff rise? + + var bookRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.BookRise, magicPower / 2.0f, AggregateType.AddRaw); + bookRisePowerUp.BonusPerLevelTable = magicPower % 2 == 0 ? this._staffRiseTableEven : this._staffRiseTableOdd; + item.BasePowerUpAttributes.Add(bookRisePowerUp); } else { item.PossibleItemOptions.Add(this.WizardryDamageOption); - item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == ExcellentOptions.WizardryAttackOptionsName)); - item.PossibleItemOptions.Add(this.GameConfiguration.ItemOptions.Single(o => o.Name == HarmonyOptions.WizardryAttackOptionsName)); - if (darkLordClass > 0) - { - var scepterRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.ScepterRise, staffRise, AggregateType.AddRaw); - scepterRisePowerUp.BonusPerLevelTable = this._scepterRiseTable; - item.BasePowerUpAttributes.Add(scepterRisePowerUp); - } - else - { - var staffRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.StaffRise, staffRise, AggregateType.AddRaw); - staffRisePowerUp.BonusPerLevelTable = this._staffRiseTable; - item.BasePowerUpAttributes.Add(staffRisePowerUp); - } + var staffRisePowerUp = this.CreateItemBasePowerUpDefinition(Stats.StaffRise, magicPower / 2.0f, AggregateType.AddRaw); + staffRisePowerUp.BonusPerLevelTable = magicPower % 2 == 0 ? this._staffRiseTableEven : this._staffRiseTableOdd; + item.BasePowerUpAttributes.Add(staffRisePowerUp); } } @@ -427,14 +436,18 @@ protected void CreateWeapon(byte @group, byte number, byte slot, int skillNumber if (group == (int)ItemGroups.Staff) { - if (wizardClass == 0 && summonerClass > 0) + if (wizardClass == 0 && summonerClass > 0 && slot == 0) { item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(Stats.IsStickEquipped, 1, AggregateType.AddRaw)); } - else + else if (wizardClass == 1) { item.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(width == 1 ? Stats.IsOneHandedStaffEquipped : Stats.IsTwoHandedStaffEquipped, 1, AggregateType.AddRaw)); } + else + { + // It's a book. Nothing to do here. + } } if (group == (int)ItemGroups.Bows && !item.IsAmmunition) diff --git a/src/Persistence/Initialization/VersionSeasonSix/Items/Wings.cs b/src/Persistence/Initialization/VersionSeasonSix/Items/Wings.cs index 53415b041..846bb7c03 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Wings.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Wings.cs @@ -73,7 +73,7 @@ public override void Initialize() this.CreateWing(0, 3, 2, "Wings of Elf", 100, 10, 200, 180, 0, 0, 1, 0, 0, 0, 0, this.BuildOptions((0, OptionType.HealthRecover)), 12, 12, this._damageIncreaseByLevelTable, null); this.CreateWing(1, 5, 3, "Wings of Heaven", 100, 10, 200, 180, 1, 0, 0, 1, 0, 0, 0, this.BuildOptions((0, OptionType.WizDamage)), 12, 12, this._damageIncreaseByLevelTable, null); this.CreateWing(2, 5, 2, "Wings of Satan", 100, 20, 200, 180, 0, 1, 0, 1, 0, 0, 0, this.BuildOptions((0, OptionType.PhysDamage)), 12, 12, this._damageIncreaseByLevelTable, null); - this.CreateWing(41, 4, 2, "Wing of Curse", 100, 10, 200, 180, 0, 0, 0, 0, 0, 1, 0, this.BuildOptions((0, OptionType.CurseDamage)), 12, 12, this._damageIncreaseByLevelTable, null); + this.CreateWing(41, 4, 2, "Wings of Curse", 100, 10, 200, 180, 0, 0, 0, 0, 0, 1, 0, this.BuildOptions((0, OptionType.WizDamage)), 12, 12, this._damageIncreaseByLevelTable, null); // Second class wings: var secondWingOptions = this.CreateSecondClassWingOptions(); @@ -81,7 +81,7 @@ public override void Initialize() this.CreateWing(4, 5, 3, "Wings of Soul", 150, 30, 200, 215, 2, 0, 0, 0, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b10, OptionType.WizDamage)), 32, 25, this._damageIncreaseByLevelTableSecond, secondWingOptions); this.CreateWing(5, 3, 3, "Wings of Dragon", 150, 45, 200, 215, 0, 2, 0, 0, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b10, OptionType.PhysDamage)), 32, 25, this._damageIncreaseByLevelTableSecond, secondWingOptions); this.CreateWing(6, 4, 2, "Wings of Darkness", 150, 40, 200, 215, 0, 0, 0, 1, 0, 0, 0, this.BuildOptions((0b00, OptionType.WizDamage), (0b10, OptionType.PhysDamage)), 32, 25, this._damageIncreaseByLevelTableSecond, secondWingOptions); - this.CreateWing(42, 4, 3, "Wings of Despair", 150, 30, 200, 215, 0, 0, 0, 0, 0, 2, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b10, OptionType.CurseDamage)), 32, 25, this._damageIncreaseByLevelTableSecond, secondWingOptions); + this.CreateWing(42, 4, 3, "Wings of Despair", 150, 30, 200, 215, 0, 0, 0, 0, 0, 2, 0, this.BuildOptions((0b00, OptionType.CurseDamage), (0b10, OptionType.WizDamage)), 32, 25, this._damageIncreaseByLevelTableSecond, secondWingOptions); // The capes are a bit of a hybrid. Their damage gets increased like first wings, but they start slightly lower than 2nd wings. this.CreateWing(49, 2, 3, "Cape of Fighter", 180, 15, 200, 180, 0, 0, 0, 0, 0, 0, 1, this.BuildOptions((0b00, OptionType.HealthRecover), (0b10, OptionType.PhysDamage)), 20, 10, this._damageIncreaseByLevelTable, secondWingOptions); @@ -95,13 +95,13 @@ public override void Initialize() // Third class wings: var thirdWingOptions = this.CreateThirdClassWingOptions(); - this.CreateWing(36, 4, 3, "Wing of Storm", 150, 60, 220, 300, 0, 3, 0, 0, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.Defense)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); - this.CreateWing(37, 4, 3, "Wing of Eternal", 150, 45, 220, 300, 3, 0, 0, 0, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.WizDamage), (0b10, OptionType.Defense)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); - this.CreateWing(38, 4, 3, "Wing of Illusion", 150, 45, 220, 300, 0, 0, 3, 0, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.Defense)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); - this.CreateWing(39, 4, 3, "Wing of Ruin", 150, 55, 220, 300, 0, 0, 0, 3, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.WizDamage)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); - this.CreateWing(40, 2, 3, "Cape of Emperor", 150, 45, 220, 300, 0, 0, 0, 0, 3, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.Defense)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); - this.CreateWing(43, 4, 3, "Wing of Dimension", 150, 45, 220, 300, 0, 0, 0, 0, 0, 3, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.CurseDamage), (0b10, OptionType.Defense)), 42, 24, this._damageIncreaseByLevelTable, thirdWingOptions); - this.CreateWing(50, 2, 3, "Cape of Overrule", 150, 45, 220, 300, 0, 0, 0, 0, 0, 0, 3, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.Defense)), 42, 24, this._damageIncreaseByLevelTable, thirdWingOptions); + this.CreateWing(36, 4, 3, "Wing of Storm", 150, 60, 220, 400, 0, 3, 0, 0, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.Defense)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); + this.CreateWing(37, 4, 3, "Wing of Eternal", 150, 45, 220, 400, 3, 0, 0, 0, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.WizDamage), (0b10, OptionType.Defense)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); + this.CreateWing(38, 4, 3, "Wing of Illusion", 150, 45, 220, 400, 0, 0, 3, 0, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.Defense)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); + this.CreateWing(39, 4, 3, "Wing of Ruin", 150, 55, 220, 400, 0, 0, 0, 3, 0, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.WizDamage)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); + this.CreateWing(40, 2, 3, "Cape of Emperor", 150, 45, 220, 400, 0, 0, 0, 0, 3, 0, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.Defense)), 39, 24, this._damageIncreaseByLevelTable, thirdWingOptions); + this.CreateWing(43, 4, 3, "Wing of Dimension", 150, 45, 220, 400, 0, 0, 0, 0, 0, 3, 0, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.WizDamage), (0b10, OptionType.CurseDamage)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); + this.CreateWing(50, 2, 3, "Cape of Overrule", 150, 45, 220, 400, 0, 0, 0, 0, 0, 0, 3, this.BuildOptions((0b00, OptionType.HealthRecover), (0b11, OptionType.PhysDamage), (0b10, OptionType.Defense)), 39, 39, this._damageIncreaseByLevelTable, thirdWingOptions); } private void CreateFeather() @@ -238,7 +238,7 @@ private ItemOptionDefinition CreateCapeOptions() var definition = this.CreateSecondClassWingOptions(); definition.SetGuid(ItemOptionDefinitionNumbers.Cape); definition.Name = "Cape of Lord Options"; - definition.PossibleOptions.Add(this.CreateWingOption(4, Stats.TotalLeadership, 10f, AggregateType.AddRaw, 5f)); // Increase Command +10~75 Increases your Command by 10 plus 5 for each level. Only Cape of Lord can have it (PvM, PvP) + definition.PossibleOptions.Add(this.CreateWingOption(4, Stats.TotalLeadership, 10f, AggregateType.AddRaw, 5f)); // Increase Command +10~85. Increases your Command by 10 plus 5 for each level. Only Cape of Lord can have it (PvM, PvP) this.GameConfiguration.ItemOptions.Add(definition); foreach (var option in definition.PossibleOptions) { @@ -259,9 +259,9 @@ private ItemOptionDefinition CreateSecondClassWingOptions() definition.MaximumOptionsPerItem = 1; // "Excellent" 2nd wing options: - definition.PossibleOptions.Add(this.CreateWingOption(1, Stats.MaximumHealth, 50f, AggregateType.AddRaw, 5f)); // Increase max HP +50~115 Increases your maximum amount of life by 50 plus 5 for each level (PvM, PvP) - definition.PossibleOptions.Add(this.CreateWingOption(2, Stats.MaximumMana, 50f, AggregateType.AddRaw, 5f)); // Increase max mana +50~115 Increases your maximum amount of mana by 50 plus 5 for each level (PvM, PvP) - definition.PossibleOptions.Add(this.CreateWingOption(3, Stats.DefenseIgnoreChance, 0.03f, AggregateType.AddRaw)); // Ignore opponent's defensive power by 3% Gives you 3% chance to lower your opponent's defence to 0 for a strike. This strike is shown with yellow colour (PvP) + definition.PossibleOptions.Add(this.CreateWingOption(1, Stats.MaximumHealth, 50f, AggregateType.AddRaw, 5f)); // Increase max HP +50~125. Increases your maximum amount of life by 50 plus 5 for each level (PvM, PvP) + definition.PossibleOptions.Add(this.CreateWingOption(2, Stats.MaximumMana, 50f, AggregateType.AddRaw, 5f)); // Increase max mana +50~125. Increases your maximum amount of mana by 50 plus 5 for each level (PvM, PvP) + definition.PossibleOptions.Add(this.CreateWingOption(3, Stats.DefenseIgnoreChance, 0.03f, AggregateType.AddRaw)); // Ignore opponent's defensive power by 3%. Gives you 3% chance to bypass your opponent's defense for a strike. This strike is shown with cyan colour (PvM, PvP) return definition; } @@ -278,8 +278,8 @@ private ItemOptionDefinition CreateThirdClassWingOptions() definition.PossibleOptions.Add(this.CreateWingOption(1, Stats.DefenseIgnoreChance, 0.05f, AggregateType.AddRaw)); // Ignore opponent's defensive power by 5% definition.PossibleOptions.Add(this.CreateWingOption(2, Stats.DamageReflection, 0.05f, AggregateType.AddRaw)); // Ignore opponent's defensive power by 5% - definition.PossibleOptions.Add(this.CreateWingOption(3, Stats.FullyRecoverHealthAfterHitChance, 0.05f, AggregateType.AddRaw)); // Fully restore health when hit by 5 % - definition.PossibleOptions.Add(this.CreateWingOption(4, Stats.FullyRecoverManaAfterHitChance, 0.05f, AggregateType.AddRaw)); // Fully recover mana when hit by 5 % + definition.PossibleOptions.Add(this.CreateWingOption(3, Stats.FullyRecoverHealthAfterHitChance, 0.05f, AggregateType.AddRaw)); // Fully restore health when hit by 5% + definition.PossibleOptions.Add(this.CreateWingOption(4, Stats.FullyRecoverManaAfterHitChance, 0.05f, AggregateType.AddRaw)); // Fully recover mana when hit by 5% return definition; }