From 90d5a4b924afe89f3558a31f142245d962feacc0 Mon Sep 17 00:00:00 2001 From: nolt Date: Wed, 17 Jun 2026 17:33:13 +0200 Subject: [PATCH] fix(npc): give empty merchant NPCs a general-goods store Christine the General Goods Merchant (545) and Market Union Member Julia (547) in the Loren Market, and Moss The Merchant (492) in Elvenland, have a merchant window but no MerchantStore, so talking to them opens an empty, non-working shop and the click can even fall through. Add a configuration update (UpdateVersion 84) that clones the general-goods (potion girl) store carried by Thompson the Merchant (231) onto each of them. The update is idempotent (skips NPCs that already have a store) and optional. After it runs they sell items and appear in the admin panel's merchant editor. --- .../Updates/AddMissingMerchantStoresPlugIn.cs | 86 +++++++++++++++++++ .../Initialization/Updates/UpdateVersion.cs | 5 ++ 2 files changed, 91 insertions(+) create mode 100644 src/Persistence/Initialization/Updates/AddMissingMerchantStoresPlugIn.cs diff --git a/src/Persistence/Initialization/Updates/AddMissingMerchantStoresPlugIn.cs b/src/Persistence/Initialization/Updates/AddMissingMerchantStoresPlugIn.cs new file mode 100644 index 000000000..025155b3f --- /dev/null +++ b/src/Persistence/Initialization/Updates/AddMissingMerchantStoresPlugIn.cs @@ -0,0 +1,86 @@ +// +// 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.PlugIns; + +/// +/// This update gives a merchant store to the NPCs which have a merchant window +/// but no items assigned, so talking to them opens an empty (non-working) shop. +/// +/// +/// Affected NPCs: Christine the General Goods Merchant (545) and Market Union Member Julia (547) +/// in the Loren Market, and Moss The Merchant (492) in Elvenland. Each one is given a clone of +/// the general-goods (potion girl) store carried by Thompson the Merchant (231). +/// +[PlugIn] +[Display(Name = PlugInName, Description = PlugInDescription)] +[Guid("f78d6e1d-1cb5-45f7-912d-54b2cb1220eb")] +public class AddMissingMerchantStoresPlugIn : UpdatePlugInBase +{ + /// + /// The plug in name. + /// + internal const string PlugInName = "Add missing merchant stores"; + + /// + /// The plug in description. + /// + internal const string PlugInDescription = "Gives a general-goods store to merchant NPCs which had a shop window but no items (Christine 545, Julia 547, Moss 492), cloned from Thompson the Merchant (231)."; + + /// + /// The number of the NPC whose store is cloned for the empty merchants. + /// + private const short StoreSourceNpcNumber = 231; // Thompson the Merchant - carries the general-goods (potion girl) store + + /// + /// The numbers of the NPCs which have a merchant window but no store. + /// + private static readonly short[] EmptyMerchantNpcNumbers = [545, 547, 492]; + + /// + public override UpdateVersion Version => UpdateVersion.AddMissingMerchantStores; + + /// + public override string DataInitializationKey => VersionSeasonSix.DataInitialization.Id; + + /// + public override string Name => PlugInName; + + /// + public override string Description => PlugInDescription; + + /// + public override bool IsMandatory => false; + + /// + public override DateTime CreatedAt => new(2026, 06, 17, 0, 0, 0, DateTimeKind.Utc); + + /// + protected override ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration) + { + var storeSource = gameConfiguration.Monsters.FirstOrDefault(m => m.Number == StoreSourceNpcNumber); + if (storeSource?.MerchantStore is null) + { + return default; + } + + foreach (var number in EmptyMerchantNpcNumbers) + { + var npc = gameConfiguration.Monsters.FirstOrDefault(m => m.Number == number); + if (npc is null || npc.MerchantStore is not null) + { + continue; + } + + npc.MerchantStore = storeSource.MerchantStore.Clone(gameConfiguration); + npc.MerchantStore.SetGuid(npc.Number); + } + + return default; + } +} diff --git a/src/Persistence/Initialization/Updates/UpdateVersion.cs b/src/Persistence/Initialization/Updates/UpdateVersion.cs index a1e209a93..abfdc4c72 100644 --- a/src/Persistence/Initialization/Updates/UpdateVersion.cs +++ b/src/Persistence/Initialization/Updates/UpdateVersion.cs @@ -422,4 +422,9 @@ public enum UpdateVersion /// The version of the . /// AddRandomExperienceConfigAttributesSeason6 = 83, + + /// + /// The version of the . + /// + AddMissingMerchantStores = 84, }