diff --git a/src/Persistence/Initialization/Updates/FinishElfMasterTreePlugIn.cs b/src/Persistence/Initialization/Updates/FinishElfMasterTreePlugIn.cs new file mode 100644 index 0000000..6424ac0 --- /dev/null +++ b/src/Persistence/Initialization/Updates/FinishElfMasterTreePlugIn.cs @@ -0,0 +1,142 @@ +// +// 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.Persistence.Initialization.Items; +using MUnique.OpenMU.Persistence.Initialization.Skills; +using MUnique.OpenMU.PlugIns; + +/// +/// This update completes the elf master tree and fixes some of its skill values. +/// +[PlugIn] +[Display(Name = PlugInName, Description = PlugInDescription)] +[Guid("D1E2F3A4-B5C6-7D8E-9F0A-1B2C3D4E5F6A")] +public class FinishElfMasterTreePlugIn : UpdatePlugInBase +{ + /// + /// The plug in name. + /// + internal const string PlugInName = "Finish Elf Master Tree PlugIn"; + + /// + /// The plug in description. + /// + internal const string PlugInDescription = "This update completes the elf master tree and fixes some of its skill values."; + + /// + public override UpdateVersion Version => UpdateVersion.FinishElfMasterTree; + + /// + public override string DataInitializationKey => VersionSeasonSix.DataInitialization.Id; + + /// + public override string Name => PlugInName; + + /// + public override string Description => PlugInDescription; + + /// + public override bool IsMandatory => true; + + /// + public override DateTime CreatedAt => new(2026, 7, 16, 16, 0, 0, DateTimeKind.Utc); + + /// + protected override async ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration) + { + // Create new Stats + var extraProjectiles = context.CreateNew(Stats.ExtraProjectiles.Id, Stats.ExtraProjectiles.Designation, Stats.ExtraProjectiles.Description); + gameConfiguration.Attributes.Add(extraProjectiles); + var greaterDefenseBonus = context.CreateNew(Stats.GreaterDefenseBonus.Id, Stats.GreaterDefenseBonus.Designation, Stats.GreaterDefenseBonus.Description); + gameConfiguration.Attributes.Add(greaterDefenseBonus); + + var greaterDamageBonus = Stats.GreaterDamageBonus.GetPersistent(gameConfiguration); + + // Update Greater Damage effect + var greaterDamageEffect = gameConfiguration.MagicEffects.First(e => e.Number == (short)MagicEffectNumber.GreaterDamage); + + var greaterDamagePowerUp2 = context.CreateNew(); + greaterDamageEffect.PowerUpDefinitions.Add(greaterDamagePowerUp2); + greaterDamagePowerUp2.TargetAttribute = greaterDamageBonus; + greaterDamagePowerUp2.Boost = context.CreateNew(); + greaterDamagePowerUp2.Boost.ConstantValue.Value = 1f; + greaterDamagePowerUp2.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + + // Update Greater Defense effect + var greaterDefenseEffect = gameConfiguration.MagicEffects.First(e => e.Number == (short)MagicEffectNumber.GreaterDefense); + + if (greaterDefenseEffect.PowerUpDefinitions.FirstOrDefault() is PowerUpDefinition defensePowerUp) + { + defensePowerUp.TargetAttribute = greaterDefenseBonus; + defensePowerUp.Boost?.ConstantValue.AggregateType = AggregateType.AddRaw; + } + + var greaterDefensePowerUp2 = context.CreateNew(); + greaterDefenseEffect.PowerUpDefinitions.Add(greaterDefensePowerUp2); + greaterDefensePowerUp2.TargetAttribute = greaterDefenseBonus; + greaterDefensePowerUp2.Boost = context.CreateNew(); + greaterDefensePowerUp2.Boost.ConstantValue.Value = 1f; + greaterDefensePowerUp2.Boost.ConstantValue.AggregateType = AggregateType.Multiplicate; + + // Update 4-arrow (cross)bows + var affectedBows = new short[] { 18, 19, 22, 23, 24 }; + var bows = gameConfiguration.Items.Where(i => i.Group == (byte)ItemGroups.Bows && affectedBows.Contains(i.Number)); + foreach (var bow in bows) + { + bow.BasePowerUpAttributes.Add(this.CreateItemBasePowerUpDefinition(context, gameConfiguration, extraProjectiles, 1, AggregateType.AddRaw)); + } + + // Update master skills + if (gameConfiguration.Skills.FirstOrDefault(s => s.Number == (short)SkillNumber.DefenseIncreaseStr)?.MasterDefinition is { } defenseIncreaseStr) + { + defenseIncreaseStr.TargetAttribute = greaterDefenseBonus; + defenseIncreaseStr.Aggregation = AggregateType.Multiplicate; + } + + if (gameConfiguration.Skills.FirstOrDefault(s => s.Number == (short)SkillNumber.TripleShotStrengthener)?.MasterDefinition is { } tripleShotStrengthener) + { + tripleShotStrengthener.TargetAttribute = extraProjectiles; + tripleShotStrengthener.Aggregation = AggregateType.AddRaw; + } + + if (gameConfiguration.Skills.FirstOrDefault(s => s.Number == (short)SkillNumber.AttackIncreaseStr)?.MasterDefinition is { } attackIncreaseStr) + { + attackIncreaseStr.TargetAttribute = greaterDamageBonus; + attackIncreaseStr.Aggregation = AggregateType.Multiplicate; + } + + if (gameConfiguration.Skills.FirstOrDefault(s => s.Number == (short)SkillNumber.AttackIncreaseMastery)?.MasterDefinition is { } attackIncreaseMastery) + { + attackIncreaseMastery.ReplacedSkill = gameConfiguration.Skills.First(s => s.Number == (short)SkillNumber.AttackIncreaseStr); + attackIncreaseMastery.TargetAttribute = greaterDamageBonus; + attackIncreaseMastery.Aggregation = AggregateType.Multiplicate; + attackIncreaseMastery.ExtendsDuration = true; + } + + if (gameConfiguration.Skills.FirstOrDefault(s => s.Number == (short)SkillNumber.DefenseIncreaseMastery)?.MasterDefinition is { } defenseIncreaseMastery) + { + defenseIncreaseMastery.ReplacedSkill = gameConfiguration.Skills.First(s => s.Number == (short)SkillNumber.DefenseIncreaseStr); + defenseIncreaseMastery.TargetAttribute = greaterDefenseBonus; + defenseIncreaseMastery.Aggregation = AggregateType.Multiplicate; + defenseIncreaseMastery.ExtendsDuration = true; + } + } + + private ItemBasePowerUpDefinition CreateItemBasePowerUpDefinition(IContext context, GameConfiguration gameConfiguration, AttributeDefinition attributeDefinition, float value, AggregateType aggregateType) + { + var powerUpDefinition = context.CreateNew(); + powerUpDefinition.TargetAttribute = attributeDefinition.GetPersistent(gameConfiguration); + powerUpDefinition.BaseValue = value; + powerUpDefinition.AggregateType = aggregateType; + return powerUpDefinition; + } +} diff --git a/src/Persistence/Initialization/Updates/UpdateVersion.cs b/src/Persistence/Initialization/Updates/UpdateVersion.cs index 81e5e7b..a580f42 100644 --- a/src/Persistence/Initialization/Updates/UpdateVersion.cs +++ b/src/Persistence/Initialization/Updates/UpdateVersion.cs @@ -479,7 +479,7 @@ public enum UpdateVersion /// The version of the . /// AddIsQuestItemFlag = 94, - + /// /// The version of the . /// @@ -519,4 +519,9 @@ public enum UpdateVersion /// The version of the . /// FinishDarkWizardMasterTree = 102, + + /// + /// The version of the . + /// + FinishElfMasterTree = 103, }