From ef3bffe39c641e1143cbb56cbab1fc7a11bfb80a Mon Sep 17 00:00:00 2001 From: Acentech Dev Date: Thu, 16 Jul 2026 22:03:08 +0300 Subject: [PATCH] feat(items): add Imperial Sword (0/50) and Imperial Staff (5/50) Two new weapons placed at free item slots so they never collide with standard Season 6 items. The client name DB (Item_eng.bmd) is the source of tooltip name/stats, so only free slots are usable for custom items. Both seed paths are covered: - Fresh DB: Weapons.Initialize() calls the new CreateImperialWeapons050(). - Existing DB: AddImperialWeapons050UpdateSeason6 (UpdateVersion 95), applied from the AdminPanel Updates page, with an idempotency guard. Imperial Sword is a Magic Gladiator weapon (copy of 0/28), Imperial Staff is a Wizard weapon (copy of 5/31). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../AddImperialWeapons050UpdateSeason6.cs | 56 +++++++++++++++++++ .../Initialization/Updates/UpdateVersion.cs | 5 ++ .../VersionSeasonSix/Items/Weapons.cs | 22 ++++++++ 3 files changed, 83 insertions(+) create mode 100644 src/Persistence/Initialization/Updates/AddImperialWeapons050UpdateSeason6.cs diff --git a/src/Persistence/Initialization/Updates/AddImperialWeapons050UpdateSeason6.cs b/src/Persistence/Initialization/Updates/AddImperialWeapons050UpdateSeason6.cs new file mode 100644 index 0000000..c060f1b --- /dev/null +++ b/src/Persistence/Initialization/Updates/AddImperialWeapons050UpdateSeason6.cs @@ -0,0 +1,56 @@ +// +// 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.DataModel.Configuration; +using MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Items; +using MUnique.OpenMU.PlugIns; + +/// +/// Adds two new weapons at item number 50: Imperial Sword (group 0, Magic Gladiator) and +/// Imperial Staff (group 5, Wizard), as full working weapons (damage, attack speed, requirements, +/// options, equip flags). Placed at free slots so they never collide with standard items. +/// +[PlugIn] +[Display(Name = PlugInName, Description = PlugInDescription)] +[Guid("BE9DD7D1-F352-4C56-A646-D78C36978982")] +public class AddImperialWeapons050UpdateSeason6 : UpdatePlugInBase +{ + internal const string PlugInName = "Add Imperial Weapons (0/50, 5/50)"; + internal const string PlugInDescription = "Adds Imperial Sword (0/50) and Imperial Staff (5/50) as fully working weapons."; + + /// + public override UpdateVersion Version => UpdateVersion.AddImperialWeapons050Season6; + + /// + 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, 07, 16, 12, 0, 0, DateTimeKind.Utc); + + /// +#pragma warning disable CS1998 + protected override async ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration) +#pragma warning restore CS1998 + { + // Idempotency guard: skip if the Imperial Sword 0/50 already exists. + if (gameConfiguration.Items.Any(i => i.Group == 0 && i.Number == 50)) + { + return; + } + + new Weapons(context, gameConfiguration).CreateImperialWeapons050(); + } +} diff --git a/src/Persistence/Initialization/Updates/UpdateVersion.cs b/src/Persistence/Initialization/Updates/UpdateVersion.cs index 53219ac..7edf6b3 100644 --- a/src/Persistence/Initialization/Updates/UpdateVersion.cs +++ b/src/Persistence/Initialization/Updates/UpdateVersion.cs @@ -479,4 +479,9 @@ public enum UpdateVersion /// The version of the . /// AddIsQuestItemFlag = 94, + + /// + /// The version of the . + /// + AddImperialWeapons050Season6 = 95, } \ 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 8979d3a..a02d718 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/Items/Weapons.cs @@ -269,6 +269,9 @@ internal class Weapons : InitializerBase 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); + // ADAMU-CUSTOM: new Imperial weapons at free slots (fresh-DB seed path; existing DBs get them via AddImperialWeapons050UpdateSeason6). + this.CreateImperialWeapons050(); + this.AddGuardianOptions(); } @@ -522,6 +525,25 @@ internal class Weapons : InitializerBase } } + /// + /// Creates only the two new "Imperial" weapons at item number 50 (Imperial Sword 0/50 and + /// Imperial Staff 5/50), reusing and the already-persisted + /// item level bonus tables (looked up by name). Intended for a configuration update + /// plug-in running against an existing database, so it does NOT recreate the tables. + /// + public void CreateImperialWeapons050() + { + this._weaponDamageIncreaseTable = this.GameConfiguration.ItemLevelBonusTables.First(t => t.Name == "Damage Increase (Weapons)"); + this._staffRiseTableEven = this.GameConfiguration.ItemLevelBonusTables.First(t => t.Name == "Staff Rise (even)"); + this._staffRiseTableOdd = this.GameConfiguration.ItemLevelBonusTables.First(t => t.Name == "Staff Rise (odd)"); + + // Imperial Sword (copy of 0/28, Magic Gladiator) at number 50. + this.CreateWeapon(0, 50, 0, 56, 1, 4, true, "Imperial Sword", 139, 98, 122, 45, 90, 109, 380, 91, 73, 17, 0, 0, 0, 0, 1, 0, 0, 0); + + // Imperial Staff (copy of 5/31, Wizard) at number 50. + this.CreateWeapon(5, 50, 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); + } + private void AddGuardianOptions() { var weaponOption = this.GameConfiguration.ItemOptions.First(io => io.PossibleOptions.Any(po => po.OptionType == ItemOptionTypes.GuardianOption && po.Number == (int)ItemGroups.Weapon));